Clojure GUI编程很难

Ral*_*lph 13 mvp scala clojure mocking

我正在使用Swing GUI编写实用程序.我正在尝试使用Martin Fowler的演示模型来促进测试.我的应用程序将使用java.util.prefs.Preferences(即:主窗口位置和大小)自动存储多个用户首选项.我花了几个小时在周末试图创建一个PreferencesAPI 的Clojure模拟(使用EasyMock),以便我可以测试我的演示者代码,但无法使其工作.使用非OO风格的Clojure GUI编程对于长期的OO程序员来说很难.我觉得如果我能发现/开发这些东西的模式(模拟,视觉"类"的"接口"等),我可以继续在整个应用程序的其余部分使用相同的模式.

我也在Scala中开发相同的应用程序来比较编程模式并发现它更加直观,即使我试图以相当严格的函数风格使用Scala(当然不包括调用Java类,如Swing API - 它在Clojure版本中具有相同的可变性问题,但当然也将是单线程的).

在我的Scala代码中,我创建了一个名为MainFrame扩展JFrame并实现特征的类MainView.MainView将所有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)
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用伪单例(setInstance包括使得模拟可以替换"真实"版本)的首选项,因此细节不会显示.我知道蛋糕模式,但发现在这种情况下使用它会更容易一些.

我一直在努力在Clojure中执行类似的代码.是否有任何开源项目的好例子可以做这种事情?我读过几本关于Clojure的书(Clojure编程,Clojure的喜悦,实用的Clojure),但还没有看到这些问题.我也研究过Rich Hickey ants.clj,但他在这个例子中使用Swing是非常基本的.

Ati*_*nch 1

检查 clojure 世界中非常流行的这两个选项:

  • CLJFX如果您同意从 swing 迁移到 javafx。
  • 如果您想继续摇摆的话,可以玩跷跷板。

编辑:新鲜信息: https: //tonsky.me/blog/skija/