我从斯图尔特的谈话了解什么是这样的:
(ns state.core)
(defn create-user-module [] (atom []))
(defn add-user [module user]
(swap! module conj user))
(defn get-users [module]
@module)
现在有你的“芯”作为操作状态的功能没有全局状态指望得到它作为一个参数。这些可以轻松进行测试,因为您可以为每个测试创建一个“用户模块”的新实例。另外,这个模块的客户端不应该关心他们在create-user-module函数中获得什么,他们应该只是传递它而不检查它,这样你可以随时更改用户模块的实现。如果您要有多个实现,Stuart还会谈谈如何为这些模块创建协议。
试图回答你的问题,一个环适配器仅1个PARAM的功能,并且的Compojure只是一个路由库,因此你可以使用闭包,如创建一个web应用程序:
(ns state.web
(:use compojure.core)
(:require [state.core :as core]))
(defn web-module [user-module]
(routes
(GET "/all" [] (core/get-users user-module))))
现在你可以调用Web模块来创建Web应用程序,并将其作为参数传递给需要的依赖项。当然,你仍然需要有人来创建正确的用户模块的Web应用程序,所以你只需要一个电线都在一起了“主要”功能:
(ns state.main
(:require state.core
state.web)
(:use ring.adapter.jetty))
(defn start []
(let [user-module (state.core/create-user-module)
web-module (state.web/web-module user-module)]
(run-jetty web-module {:port 3000 :join? false})))
(defn stop [app]
(.stop app))
start
将您的应用程序main
方法被调用。这只是意味着你需要切换到lein-run插件。
现在,鉴于您询问的是init
(我假设来自lein ring插件),我想您打算将webapp部署到容器中。由于雷音环插件拥有了Java Servlet FW限制范围内,并且该处理结束编译为Java Servlet的工作,或许您可以做的最好的是一样的东西:
(ns state.web
(:use compojure.core)
(:require [state.core :as core]))
(def module-deps (atom {})
(defn init-app [] (swap! module-deps conj [:user-module (core/create-user-module)]))
(defroutes web-module []
(GET "/all" [] (core/get-users (:user-module @module-deps))))
这仍然意味着你的核心命名空间很容易测试,但是您仍然在Web命名空间中拥有全局状态,但是我认为这是“正确”封装的,如果您必须使用java容器,则可能已经足够好了。
而这只是为什么图书馆比框架“更好”的另一个理由:)
y!这是一个好方法。 – hsestupin 2013-03-25 05:55:46
@hsestupin:这是一个问题或肯定:) – Ankur 2013-03-25 06:06:29
肯定c。我的意思是,当国家不能通过直接引用而改变时,我完全同意这种做法。 – hsestupin 2013-03-25 08:52:40