这个swing Table模型代码是否设计得很糟糕?

这个swing Table模型代码是否设计得很糟糕?,swing,clojure,Swing,Clojure,上下文:我有一个基于clojure的纵横字谜应用程序,它的主要ui是一个JTabbedPane,有两个选项卡,一个网格和一个线索表。线索表是线索向量的视图,但向量本身不是数据的权威存储,而是通过(活动cluelist)函数从两个内部数据结构动态生成的,该函数由正在选择的线索选项卡触发 这就是线索表的实现: (def cluelist []) (def update-cluelist) (def model) (defn make [] (let [column-names ["Sq" "W

上下文:我有一个基于clojure的纵横字谜应用程序,它的主要ui是一个JTabbedPane,有两个选项卡,一个网格和一个线索表。线索表是线索向量的视图,但向量本身不是数据的权威存储,而是通过
(活动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))
另一次讨论中有人指出,手动调用
fireTableDataChanged
(更新cluelist)
的主要代码气味,因为TableModel类之外的任何东西都不应该调用该方法。然而,我觉得这是从外部源动态生成表的不可避免的结果。这些文件并没有太大的帮助,他们说

您的自定义类只需调用以下函数之一 AbstractTableModel方法每次通过 外部来源

它隐式地假定CustomTableModel类是数据的权威源

这里还有一点clojure/java阻抗不匹配-在java中,我会让
cluelist
update cluelist
成为我的TableModel的私有成员和方法,而在clojure
cluelist
中,表模型是动态作用域的变量,
update cluelist
可以访问这些变量


我的主要问题是没有太多clojure/swing代码可供我寻找最佳实践。有人对最好的方法有什么建议吗?

建议:使用atom作为cluelist。不断重新定义cluelist不是表示可变数据的正确方法。老实说,我希望它在第二次定义cluelist时抛出异常

如果将atom用于cluelist,则可以从观察者调用
fireTableDataChanged
方法,而不是手动调用它。这意味着无论何时何地更改atom,
fireTableDataChanged
都将自动调用,而无需显式调用


def
的问题是多次调用
def
在多线程环境中效果不佳,Clojure试图将所有内容默认为线程安全。据我所知,使用var的“正确”方法是不使用它的根绑定(即,不要再次调用
def
),如果需要在本地更改它,则使用
binding
def
可能按照您使用它的方式工作,但该语言的设置是为了在这种情况下支持atoms、ref或agent,并且这些语言在大多数情况下可能会工作得更好(例如,您有了监视者)。另外,如果以后添加线程,您根本不需要担心线程。

atom显然是个好主意,因为正如您所注意到的,我可以向它添加一个观察者,但是为什么var是错误的呢?我见过在clojure代码中非常频繁地使用变量来存储不需要并发写入的“可变”数据结构。@MartinDeMello请参阅扩展的answerkleopatra:yep:)感谢您让我重新检查设计!