Clojure模块依赖项

Clojure模块依赖项,clojure,dependency-management,modularity,Clojure,Dependency Management,Modularity,我试图在clojure中创建一个模块化应用程序 假设我们有一个博客引擎,它由两个模块组成,例如数据库模块和文章模块(为博客存储文章的东西),所有这些都带有一些配置参数 因此-article模块依赖于存储,并且具有article模块和database模块的两个实例(具有不同的参数)允许我们在两个不同的数据库中托管两个不同的博客 我试图实现这一点,为每个初始化的模块动态创建新的名称空间,并使用部分应用的参数在名称空间中定义函数。但我认为,这种方法是某种黑客行为 做这件事的正确方法是什么?模块是一个名

我试图在clojure中创建一个模块化应用程序

假设我们有一个博客引擎,它由两个模块组成,例如数据库模块和文章模块(为博客存储文章的东西),所有这些都带有一些配置参数

因此-article模块依赖于存储,并且具有article模块和database模块的两个实例(具有不同的参数)允许我们在两个不同的数据库中托管两个不同的博客

我试图实现这一点,为每个初始化的模块动态创建新的名称空间,并使用部分应用的参数在名称空间中定义函数。但我认为,这种方法是某种黑客行为


做这件事的正确方法是什么?

模块是一个名词,就像Steve Yegge的“模块”一样

尽可能地坚持它们的参数(动词)的无副作用或纯函数,除非是在抽象的最高层。你可以随意组织这些功能。在最顶层,您将拥有一些应用程序状态,有许多方法可以管理这些状态,但我最常用的方法是将这些顶级服务隐藏在clojure协议下,然后在clojure记录中实现它(该记录可能包含对数据库连接或类似连接的引用)

这种方法最大限度地提高了灵活性,并防止您将自己写进一个角落。这对java的依赖项注入很有帮助。斯图尔特·塞拉(Stuart Sierra)最近在Clojure/West 2013上就这些话题做了一次很好的演讲,但视频尚未发布

请注意与您的方法的差异。您需要将对象的管理和解析与其生命周期分开。将它们绑定到名称空间可以快速访问,但这意味着您作为使用该代码的客户端编写的任何函数现在都在访问全局状态。通过协议,您可以将全局状态的实现细节与访问接口分离

<如果你需要一个激励的例子来说明为什么这是有用的,考虑一下,你如何拦截对全局可访问的服务的所有访问?好的,您可以向下推完整的实现,并使入口点成为包装函数,而不是将相关细节推到更接近客户机代码的位置。如果您希望代码的某些客户机有某种行为,而不是其他客户机,该怎么办?现在你被卡住了。这只是期待着先发制人地做出那些不可避免的权衡,让你的生活更轻松