2011-04-11 79 views
13

我正在使用Swing GUI編寫一個實用程序。我正在嘗試使用Martin Fowler的Presentation Model來促進測試。我的應用程序將使用java.util.prefs.Preferences(即:主窗口位置和大小)自動存儲多個用戶首選項。我在週末花了幾個小時嘗試創建Preferences API的Clojure模擬(使用EasyMock),以便測試演示者代碼,但無法使其工作。使用非OO風格的Clojure GUI編程對於長時間的OO程序員來說很難。我覺得如果我能夠發現/開發這些東西的模式(嘲笑,視覺「類」的接口等),我可以繼續在應用程序的其餘部分使用相同的模式。Clojure GUI編程很難

我也一直在開發Scala中的相同應用程序來比較編程模式,並發現它更直觀,即使我試圖在相當嚴格的功能樣式中使用Scala(當然不包括調用到像Swing API這樣的Java類 - 在Clojure版本中會有相同的可變性問題,但當然也會是單線程的)。

在我的Scala代碼中,我創建了一個名爲MainFrame的類,該類擴展了JFrame並實現了特徵MainViewMainView公開所有的JFrame電話爲抽象方法,我可以在模擬對象的實施:對於

trait LabelMethods { 
    def setText(text: String) 
    //... 
} 

trait PreferencesMethods { 
    def getInt(key: String, default: Int): Int 
    def putInt(key: String, value: Int) 
    //... 
} 

trait MainView { 
    val someLabel: LabelMethods 
    def addComponentListener(listener: ComponentListener) 
    def getLocation: Point 
    def setVisible(visible: Boolean) 
    // ... 
} 

class MainFrame extends JFrame with MainView { 
    val someLabel = new JLabel with LabelMethods 
    // ... 
} 

class MainPresenter(mainView: MainView) { 
    //... 
    mainView.addComponentListener(new ComponentAdaptor { 
    def componentMoved(ev: ComponentEvent) { 
     val location = mainView.getLocation 
     PreferencesRepository.putInt("MainWindowPositionX", location.x) 
     PreferencesRepository.putInt("MainWindowPositionY", location.y) 
    } 
    mainView.someLabel.setText("Hello") 
    mainView.setVisible(true) 
} 

class Main { 
    def main(args: Array[String]) { 
    val mainView = new MainFrame 
    new MainPresenter(mainView) 
    } 
} 

class TestMainPresenter { 
    @Test def testWindowPosition { 
    val mockPreferences = EasyMock.mock(classOf[PreferencesMethods]) 
    //... setup preferences expectation, etc. 
    PreferencesRepository.setInstance(mockPreferences) 

    val mockView = EasyMock.createMock(classOf[MainView]) 
    //... setup view expectations, etc. 
    val presenter = new MainPresenter(mockView) 
    //... 
    } 
} 

我使用的是僞單身(setInstance包括在內,以便進行模擬可以代替「真實」的版本)首選項,所以細節不顯示。我知道蛋糕模式,但發現在這種情況下我的使用更容易一些。

我一直在努力做類似的代碼在Clojure。有什麼好的開源項目的例子可以做這種事情嗎?我已經閱讀了幾本有關Clojure的書(Clojure編程,Clojure的喜悅,實用Clojure),但是沒有看到這些問題處理過。我也研究過Rich Hickey的ants.clj,但他在這個例子中使用Swing是非常基本的。

回答

5
+0

@dnolen:是的。我會重新閱讀它。謝謝。我認爲我發現最困難的是「重構」我的代碼而不是類的功能。有趣的是,自從我在上個世紀八十年代做了一大堆C編程。 – Ralph 2011-04-11 14:38:25

+0

@Ralph:在大多數情況下,c中的「功能」是指「程序」。因此程序性而非功能性編程:) – 2011-04-11 17:42:36

+0

@Vagif Verdi:是的。當我開始學習Clojure時,我意識到了這種差異,但在某種程度上,「動詞」而不是「名詞」的想法也適用於C程序編程。畢竟,「過程」是一系列影響對象的操作,即使這些對象確實是命令式的狀態。 – Ralph 2011-04-11 17:48:33