在Clojure中处理应用程序配置的惯用方式是什么?
到目前为止,我使用这种环境:
;; config.clj
{:k1 "v1"
:k2 2}
;; core.clj
(defn config []
(let [content (slurp "config.clj")]
(binding [*read-eval* false]
(read-string content))))
(defn -main []
(let [config (config)]
...))
有很多缺点:
config.clj
的路径可能无法始终正确解析没有清晰的方法来构造二手库/框架的配置部分
不能全局访问(
@app/config
)(当然,这可以看作是一种很好的功能样式方式,但是会使跨源文件访问config变得乏味。像Storm这样的大型开源项目似乎使用YAML而不是Clojure,并通过一些丑陋的攻击使配置全局访问:
(eval ``(def ~(symbol new-name) (. Config ~(symbol name)))).
最佳答案
首先使用clojure.edn,尤其是clojure.edn / read。例如
(use '(clojure.java [io :as io]))
(defn from-edn
[fname]
(with-open [rdr (-> (io/resource fname)
io/reader
java.io.PushbackReader.)]
(clojure.edn/read rdr)))
关于使用io / resource的config.edn的路径只是处理此问题的一种方法。由于您可能希望在运行时保存更改后的config.edn,因此您可能希望依赖以下事实:使用非限定文件名构造的文件读取器和写入器的路径,例如
(io/reader "where-am-i.edn")
默认为
(System/getProperty "user.dir")
考虑到您可能想在运行时更改配置这一事实,可以实现这样的模式
(草图)
;; myapp.userconfig
(def default-config {:k1 "v1"
:k2 2})
(def save-config (partial spit "config.edn"))
(def load-config #(from-edn "config.edn")) ;; see from-edn above
(let [cfg-state (atom (load-config))]
(add-watch cfg-state :cfg-state-watch
(fn [_ _ _ new-state]
(save-config new-state)))
(def get-userconfig #(deref cfg-state))
(def alter-userconfig! (partial swap! cfg-state))
(def reset-userconfig! #(reset! cfg-state default-config)))
基本上,这段代码包装了一个非全局原子,并提供了设置并可以访问它。您可以读取其当前状态,并使用sth像原子一样对其进行更改。就像
(alter-userconfig! assoc :k2 3)
。对于全局测试,可以重置! userconfig,还将各种userconfig注入到应用程序(alter-userconfig! (constantly {:k1 300, :k2 212}))
中。需要userconfig的函数可以这样写
(defn do-sth [cfg arg1 arg2 arg3]
...)
并使用各种配置进行测试,例如default-userconfig,testconfig1,2,3 ...
像在用户面板中一样操作userconfig的函数将使用get / alter ..!功能。
同样,上述让我们在userconfig上包装了一个监视,该监视在每次更改userconfig时都会自动更新.edn文件。如果您不想这样做,则可以添加save-userconfig!将原子内容吐入config.edn的函数。但是,您可能想创建一种向原子添加更多手表的方法(例如,在更改自定义字体大小后重新渲染GUI),我认为这会破坏上述模式的模样。
相反,如果您要处理更大的应用程序,则更好的方法是为userconfig定义一个协议(具有与let块类似的功能),并使用文件,数据库,原子(或任何您喜欢的东西)的各种构造函数来实现该协议。需要使用reify或defrecord测试/不同的使用场景)。可以在应用程序中传递它的一个实例,每个状态操作/ io函数都应使用它而不是全局变量。
关于configuration - Clojure中的惯用配置管理?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17719976/