Я пытался выяснить подход, который следует принять, чтобы позволить JavaFX TableView (или любой другой вещи JavaFX) представлять некоторые данные Clojure и позволять пользователю манипулировать данными через графический интерфейс.
Для этого обсуждения предположим, что у меня есть список / вектор карт, то есть что-то вроде [{:col1 "happy1" :col2 "sad1"} {:col1 "happy2" :col2 "sad2"}]
, и я хочу, чтобы он отображался в графической таблице следующим образом:
mykey1 mykey2
------------------
happy1 sad1
happy2 sad2
Довольно просто. Это было сделано миллионы раз в мировой истории.
Проблема в том, что TableView настаивает на взятии ObservableList и т. Д., Что по своей сути является изменчивым, как и все Observables в JavaFX. Это отлично подходит для поддержания таблицы в актуальном состоянии, а в изменяемой модели также отлично подходит для того, чтобы позволить пользователю напрямую манипулировать данными через графический интерфейс. Я не эксперт, но в этом случае кажется, что JavaFX хочет, чтобы объект GUI действительно содержал реальные данные. Мне это кажется смешным (не ха-ха). Чтобы поддерживать мою собственную модель и общаться между графическим интерфейсом пользователя и моделью через некоторый API или интерфейс, также подразумевается, что я поддерживаю данные в двух местах: в моей собственной модели и в графическом интерфейсе. Это правильный образ действий? Возможно, это нормально, поскольку графический интерфейс отображает только небольшую часть всех данных и позволяет моим данным модели быть просто обычными данными модели, а не экземпляром какого-либо типа, производного от Java.
Таким образом, это приводит к следующим трем общим вопросам при попытке поместить графический интерфейс в модель без сохранения состояния / неизменяемость:
Каким образом модель может быть по-настоящему неизменной, если графический интерфейс обязательно позволяет вам что-то менять? Я специально думаю о каком-то инструменте дизайна, редакторе и т. Д., Где пользователь явно меняет вещи вокруг. Например, LightTable - это редактор, но история основана на неизменных данных. Как это может быть? Меня не интересует FRP для этого обсуждения.
Предполагая, что на каком-то уровне существует хотя бы один
Atom
или другой изменяемый тип Clojure (ref / var / agent / и т. Д.) (Будь то одинAtom
, содержащий всю базу данных дизайна в памяти, или база данных проекта является неизменяемым списком mutableAtoms
), какая из моделей [MVP, MCP, MVVM и т. д.] лучше всего подходит для этого типа создания?JavaFX засоряет иерархию классов всеми мыслимыми вариантами интерфейса Observable (http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html), с такими драгоценными камнями, как
Observable[whatever]Value
, включая, например,ObservableMap
иObservableMapValue
, а затем десятки и десятки классов реализации, таких какIntegerProperty
иSimpleIntegerProperty
. .. блин! wtf ?. Предполагая, что мне нужно создать несколько объектов Clojure (defrecord
и т. Д.) И реализовать некоторыеObservable
методы интерфейса на моих в основном неизменяемых объектах, могу ли я просто придерживатьсяObservable
, или я должен реализовать каждый до конечного узла, то естьObservableIntegerValue
, и т.д.?
Каков правильный подход высокого уровня? Поддерживать один атом верхнего уровня, который заменяется каждый раз, когда пользователь меняет значение? Поддерживать тысячу низкоуровневых атомов? Позволить моим значениям жить как наблюдаемые объекты JavaFX и забыть о структурах данных Clojure? Реализовать мой собственный набор Observables в Clojure с использованием некоторого класса reify / proxy / gen, но реализовать их как неизменяемые, которые заменяются каждый раз при внесении изменений? Есть ли необходимость или место в функции Clojure add-watch
? Я бы очень предпочел, чтобы мои данные были просто обычными данными в Clojure, а не «типом» или реализацией интерфейса чего-либо. Целое число должно быть целым числом и т. Д.
Благодарность