我正在努力净化'我的一些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
变得纯净(并且作为一个好处,很容易可测试的)?
答案 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)