Mongodb 在Clojure应用程序的DAO层中避免全局状态

Mongodb 在Clojure应用程序的DAO层中避免全局状态,mongodb,clojure,dao,Mongodb,Clojure,Dao,我正在尝试将中的想法实现到我的代码库中 我有一个dao层,在这里我现在需要传入一个数据库以避免全局状态。有一句话让我很反感: 任何需要这些组件之一的功能都必须将其作为 参数这并不像看上去那么麻烦:每个函数 获取最多一个额外的参数,该参数提供它所处的“上下文” 运作。该上下文可以是整个系统对象,但更多 通常会有一些子集。通过明智地使用词法闭包 额外的参数从大多数代码中消失 我应该在哪里使用闭包以避免每次调用都传递全局状态?一个示例是在dao层中创建一个init函数,如下所示: (defprotoc

我正在尝试将中的想法实现到我的代码库中

我有一个dao层,在这里我现在需要传入一个数据库以避免全局状态。有一句话让我很反感:

任何需要这些组件之一的功能都必须将其作为 参数这并不像看上去那么麻烦:每个函数 获取最多一个额外的参数,该参数提供它所处的“上下文” 运作。该上下文可以是整个系统对象,但更多 通常会有一些子集。通过明智地使用词法闭包 额外的参数从大多数代码中消失

我应该在哪里使用闭包以避免每次调用都传递全局状态?一个示例是在dao层中创建一个init函数,如下所示:

(defprotocol Persistable
  (collection-name [this]))

(def save nil)

(defn init [{:keys [db]}]
  (alter-var-root #'save (fn [_] (fn [obj] (mc/insert-and-return db (collection-name obj) obj WriteConcern/SAFE)))))
(defn start
  [{:keys [db] :as system}]
  (let [d (-> db
              (mc/connect)
              (mc/get-db "my-test"))]
    (dao/init d)
    (assoc system :db d)))
这样,我可以从系统/启动功能启动dao层,如下所示:

(defprotocol Persistable
  (collection-name [this]))

(def save nil)

(defn init [{:keys [db]}]
  (alter-var-root #'save (fn [_] (fn [obj] (mc/insert-and-return db (collection-name obj) obj WriteConcern/SAFE)))))
(defn start
  [{:keys [db] :as system}]
  (let [d (-> db
              (mc/connect)
              (mc/get-db "my-test"))]
    (dao/init d)
    (assoc system :db d)))

这很管用,但感觉有点恶心。有更好的办法吗?如果可能的话,我希望避免迫使dao层的客户端在每次使用函数时都必须传递数据库。

您可以使用高阶函数来表示dao层-这是函数编程的关键,使用函数来表示系统从小到大的部分。因此,您有一个更高阶的函数,它将DB连接作为param,并返回另一个函数,您可以使用该函数调用数据库上的各种操作,如save、delete等。下面是一个这样的例子:

(defn db-layer [db-connection]
  (let [db-operations {:save (fn [obj] (save db-connection obj))
                       :delete (fn [obj] (delete db-connection obj))
                       :query (fn [query] (query db-connection query))}]
    (fn [operation & params]
      (-> (db-operations operation) (apply params)))))
数据库层的使用:

(let [my-db (create-database)
      db-layer-fn (db-layer my-db)]
  (db-layer-fn :save "abc")
  (db-layer-fn :delete "abc"))
这只是一个高阶函数如何允许您为另一组函数创建上下文的示例。通过将此概念与其他Clojure功能(如协议)相结合,您可以进一步了解它