этот код модели колеблющейся таблицы плохо спроектирован? - PullRequest
2 голосов
/ 07 февраля 2012

Контекст: у меня есть приложение кроссворда на основе clojure, основным пользовательским интерфейсом которого является JTabbedPane с двумя вкладками, сеткой и таблицей подсказок. Таблица подсказок представляет собой представление вектора подсказок, но сам вектор не является официальным хранилищем данных, а динамически генерируется из пары внутренних структур данных с помощью функции (active-cluelist), запускаемой выбранной вкладкой подсказок.

Итак, это реализация таблицы подсказок:

(def cluelist [])
(def update-cluelist)
(def model)

(defn make []
  (let [column-names ["Sq" "Word" "Clue"]
        column-widths [48 200 600]
        table-model (proxy [AbstractTableModel] []
                      (getColumnCount [] (count column-names))
                      (getRowCount [] (count cluelist))
                      (isCellEditable [row col] (= col 2))
                      (getColumnName [col] (nth column-names col))
                      (getValueAt [row col] (get-in cluelist [row col]))
                      (setValueAt [s row col]
                                  (let [word (get-in cluelist [row 1])]
                                    (add-clue word s) ; editing a cell updates the main clue data
                                    (def cluelist (assoc-in cluelist [row 2] s))
                                    (. this fireTableCellUpdated row col))))
        table (JTable. table-model)
        ]

; some pure display stuff elided

(def model table-model)
)

(defn update-cluelist []
  (def cluelist (active-cluelist))
  (.fireTableDataChanged model))

Кто-то в другом обсуждении заметил, что для (update-cluelist) основным запахом является ручной вызов fireTableDataChanged, потому что ничто за пределами класса TableModel никогда не должно вызывать этот метод. Однако я считаю, что это неизбежное следствие динамической генерации таблицы из внешнего источника. Документы не слишком полезны - они утверждают, что

Ваш пользовательский класс просто должен вызвать один из следующих Методы AbstractTableModel каждый раз, когда данные таблицы изменяются внешний источник.

, который неявно предполагает, что класс CustomTableModel является официальным источником данных.

Также здесь есть некоторое несоответствие импеданса clojure / java - в java у меня были бы cluelist и update-cluelist частный член и метод моей TableModel, тогда как в clojure cluelist и модели таблицы динамически изменяемые переменные, к которым update-cluelist имеет доступ.

Моя главная проблема заключается в том, что вокруг не так много кода clojure / swing, на который я мог бы обратить внимание для получения лучших практик. У кого-нибудь есть советы, как лучше всего это сделать?

1 Ответ

2 голосов
/ 07 февраля 2012

Предложение: используйте атом для celelist.Постоянное переопределение списков не является правильным способом представления изменяемых данных.Честно говоря, я ожидаю, что это вызовет исключение во второй раз, когда вы определяете список ключей.

Если вы используете атом для celelist, вы можете вызвать метод fireTableDataChanged из наблюдателя, а не вызывать его вручную.Это будет означать, что в любое время (и в любом месте) вы меняете атом, fireTableDataChanged будет вызываться автоматически, без явного вызова.

Проблема с def заключается в том, что вызов def несколько раз нехорошо работают в многопоточной среде, и Clojure пытается сделать все по умолчанию достаточно безопасным.Насколько я понимаю, «правильный» способ использовать var - это оставить привязку к корню в одиночку (т. Е. Не вызывать def снова) и использовать binding, если вам нужно локально изменить ее.def может работать так, как вы его используете, но язык настроен на поддержку атомов, ссылок или агентов в такой ситуации, и они, вероятно, будут работать лучше большую часть времени (то есть у вас есть наблюдатели).Кроме того, вам не нужно беспокоиться о потоках, если вы добавите их позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...