在Clojure中处理数据库读取

时间:2014-11-19 15:36:54

标签: clojure functional-programming side-effects purely-functional

我正在努力净化'我的一些Clojure功能。我想谈谈在一个函数中显式声明我所有的副作用代码。在开始时很容易获得一些数据,并在最后将数据写入数据库,并且只需要在两者之间进行转换。但是,通常的情况是转换函数需要在逻辑中间的某处读取另一个DB:

(defn transform-users
      [users]
      (let [ids (map :id users)
            profiles (db/read :profiles ids)]
       (profiles->something profiles)))

(->> (db/read :users)
     (transform-users)
     (db/write :something)

显然这是一个非常简单的例子,但问题是,我如何从那里获得副作用db/read函数,如何使transform-users变得纯净(并且作为一个好处,很容易可测试的)?

2 个答案:

答案 0 :(得分:1)

你可以在这里做的一件事是类似依赖注入的方法,提供(潜在的)副作用函数作为可选参数,例如:

(defn transform-users
  [users & {:keys [ids->profiles]
            :or {ids->profiles #(db/read :profiles %)}]
  (let [ids (map :id users)
        profiles (ids->profiles ids)]
    (profiles->something profiles)))

这应该很容易测试,因为你可以毫不费力地模拟注入的函数。作为奖励,通过提供默认值,您可以记录您期望的内容并使功能更方便。

答案 1 :(得分:1)

为什么要将配置文件的读取与转换配置文件相结合?

  (->> (db/read :users)
       (map :id)
       (db/read :profiles)
       (profile->something)
       (db/write :something)

(这也暴露了这样一个事实,即您正在两次往返数据库。db/read :user-profiles在哪里?)

  (->> (db/read :user-profiles)
       (profile->something)
       (db/write :something)

或者也许:

  (->> (read-profiles-from-users)
       (profile->something)
       (db/write :something)