我從斯圖爾特的談話瞭解什麼是這樣的:
(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