如何处理需要在其外部设置的库中的变量?

时间:2013-12-19 14:03:11

标签: clojure datomic

我在几个项目中使用Datomic,是时候将所有常用代码移动到一个小型实用程序库中。

一个挑战是处理大多数操作所依赖的共享数据库uri,但必须由项目使用库设置。我想知道是否有一种完善的方法来做到这一点。以下是我想过的一些替代方案:

  • 删除库中的uri符号并将uri作为参数添加到访问数据库的每个函数

  • 在初始化函数中通过alter-var-root或类似机制对其进行更改

  • 将其作为动态var *uri*保存在库中,并覆盖希望小的适配器层中的值,如

    (def my-url ... bla ...)

    (defn my-fun [args]    (with-datomic-uri my-uri      (应用library / my-fun args))

  • uri保留为库中的原子

2 个答案:

答案 0 :(得分:4)

Stuart Sierra最后一次Clojure / West发表了一篇名为Clojure in the Large的演讲,讨论了更大的Clojure应用程序的设计模式

其中一个是你描述的问题。

总结有关手头问题的提示:

1清除构造函数

所以你有一个定义良好的初始状态。

  (defn make-connection [uri]
      {:uri uri
       ...}

2明确依赖

  (defn update-db [connection] 
     ...

3测试更容易

(deftest t-update
  (let [conn (make-connection)]
    (is (= ... (update-db conn)))))

4更安全重装

 (require ... :reload)

uri 保留在稍后要绑定的变量中是很常见的,但引入了隐藏的依赖关系,也假定body在单个线程上开始和结束。

观看演讲,了解更多有关设计的提示。

答案 1 :(得分:3)

我的感觉是保持大多数数据组代码尽可能没有隐式状态。

让查询函数获取数据库 。写函数(transact)采用数据库连接。这最大化了潜在的重用并避免了隐含的假设,例如只与一个数据库连接交谈,或者无意中隐式地将查询函数硬编码为仅处理当前数据库值 - 而不是过去(as-of)或“future”({{1数据库值。

为库的标准用例协调单个公共连接然后成为小额外命名空间的工作。使用原子在这里有意义来保持uri或连接。如果手动编写和传递连接和数据库值是一件麻烦事,那么一些便利宏(可能称为withwith-connection可以包装主库函数。