2012-02-07 17 views
2

コンテキスト:私は主なUIがグリッドと手がかりの2つのタブを持つJTabbedPaneであるclojureベースのクロスワードアプリを持っています。手掛かり表は手がかりのベクトル上のビューですが、ベクトル自体はデータの正式なストアではなく、(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)) 

誰かがするTableModelクラス外で何が今まであってはならないので、(update-cluelist)は手動、fireTableDataChangedを呼び出すされることが主要なコードのにおいであることに注意そのメソッドを呼び出す。しかし、私はこれがテーブルが外部ソースから動的に生成されることは避けられない結果であると感じています。ドキュメントはあまりにも便利ではありません - 。彼らは

カスタムクラスは、単に各時刻表データは 外部ソースによって変更された1次 AbstractTableModelにメソッドを呼び出す必要があると述べています

これは、CustomTableModelクラスがデータの信頼できるソースであることを暗黙的に前提としています。

もここのClojure/Javaのインピーダンス不整合のビットがあります - Clojureのcluelistとテーブルモデルで動的にそのVARSをスコープしているのに対し、Javaで私は、cluelistupdate-cluelistは私のTableModelのプライベートメンバとメソッドも持っているだろうupdate-cluelistにアクセスしています。

私の主な問題は、私がベストプラクティスを探すためにたくさんのクロージャー/スイングコードがないことです。これを行うための最善の方法については誰にもアドバイスがありますか?

+1

_someone_は私です:-) – kleopatra

+0

kleopatra:yep :)デザインを再検査してくれてありがとう! –

答えて

2

提案:cluelistにアトムを使用してください。絶えず変更されたデータを表現するには、cluelistを常に再定義することは正しい方法ではありません。正直なところ、私はそれが例外をスローすることを期待します。

cluelistにアトムを使用する場合は、手動で呼び出す代わりに、ウォッチャーからfireTableDataChangedメソッドを呼び出すことができます。これは、いつでも(そしてどこでも)原子を変更すると、明示的な呼び出しなしでfireTableDataChangedが自動的に呼び出されることを意味します。

defの問題は、マルチスレッド環境でdefを複数回呼び出してもうまく動作せず、Clojureはすべてのスレッドをスレッドセーフにすることを基本としています。私が理解しているように、varを使用する "適切な"方法は、ルートバインディングだけを残すことです(つまり、defを再度呼び出さないでください)。ローカルに変更する必要がある場合はbindingを使用してください。 defは、あなたがそれを使用している方法で動作するかもしれませんが、この種の状況で原子、参照、またはエージェントをサポートするように言語が設定されており、これらはたいてい時間のほうが優れています(つまりウォッチャーを取得します)。また、後でスレッドを追加する場合は、スレッドについてまったく心配する必要はありません。

+0

原子は間違いなく良いアイデアのように思えます。私はそれにウォッチャーを追加することができますが、なぜvarが間違っているのでしょうか?私は、頻繁にclojureコードで使用されていて、同時に書き込む必要のない "変更可能な"データ構造を格納するのを見てきました。 –

+0

@MartinDeMello拡大返信を参照してください – Retief

+0

ありがとう、それは理にかなっています。 –

関連する問題