Clojure Модель-View-Controller (MVC)
Я пишу приложение Desktop GUI в Clojure с помощью Java Swing. Обычно при работе с Java я буду разрабатывать приложение в соответствии с шаблоном проектирования MVC с использованием шаблона Observer. Таким образом, вид отделяется от модели, и изменения ни в одном не влияют друг на друга, что облегчает дальнейшие изменения.
Мне было интересно, имеет ли Clojure лучший подход к этой проблеме, чем обычный шаблон проектирования MVC и Observer? Я новичок в функциональном программировании, поэтому я не уверен, как я могу сделать модель отдельной от представления. Я требую этого, так как приложение будет разрабатываться итеративно, и могут возникнуть сложные требования, которые идут дальше по линии.
Поблагодарили бы за любую помощь.
Спасибо,
Адам
Ответы
Ответ 1
Многие шаблоны проектирования из мира Java MVC становятся немного глупыми, когда у вас есть функции первого порядка, макросы (код-данные) и параллельные постоянные структуры данных. например, "шаблон наблюдателя" - это просто агент с некоторыми наборами часов. Это от шаблона вызова функции.
если вы сохраняете состояние (модель) в ref или агенте и делаете свое представление функцией (в смысле функционального программирования слова), которая отображает это состояние; делая ваш контроллер функцией (опять-таки в смысле FP слова), который создает новое состояние, учитывая старое состояние и некоторый новый вход, тогда модель MVC выпадает очень красиво.
он немного устарел, но Stuart Sierra расположение макета сетки действительно помог мне начать работу в этой области.
Ответ 2
В Clojure вы, безусловно, можете сделать MVC, но я бы предложил реализовать его с помощью часов на Clojure ссылках.
Код будет выглядеть примерно так:
; define the model as an immutable structure stored in a ref
(def model (ref (create-my-model)))
; function to update the UI when the model changes
(def update-function [old-model new-model]
(do-whatevever-updates old-model new-model))
; add a watch to the model to call update-function when a change happens
(add-watch model :on-update
(fn [key reference old-state new-state]
(if (not= old-state new-state)
(update-function old-state new-state))))
Также, если вы создаете графический интерфейс в Clojure, возможно, стоит взглянуть на некоторые из существующих оболочек Swing-библиотеки, например:
- Clarity - имеет хороший DSL для определения элементов пользовательского интерфейса.
- Seesaw - возможно, самая зрелая оболочка для Swing
- clj-swing