7

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

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

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

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

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

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

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

  • uri像原子一样保存在图书馆里

4

2 回答 2

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在单个线程上开始和结束。

观看谈话,更多关于设计的技巧。

于 2013-12-19T16:33:58.787 回答
3

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

让查询函数采用数据库。让写入函数 ( transact) 建立数据库连接。这最大限度地提高了潜在的重用性并避免了隐含的假设,例如只与一个数据库连接交谈或无意中隐含地对查询函数进行硬编码以仅在当前数据库值上工作 - 而不是过去 ( as-of) 或“未来” ( with) 数据库值。

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

于 2013-12-19T16:19:37.120 回答