2013-04-08 169 views
4

我想在clojure中创建一个模块化应用程序。假设我们有一个博客引擎,它由两个模块组成,例如 - 数据库模块和文章模块(用于存储博客文章的东西),所有这些模块都带有一些配置参数。Clojure模块依赖关系

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

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

什么是正确的方法来做到这一点?

回答

2

“模块”是一个名词,如Steve Yegge的'Kingdom of Nouns'中所述。

尽可能地坚持其参数(动词)的非副作用或纯函数,除了抽象的最高级别。不管你喜欢,你都可以组织这些功能。在最高级别上你会有一些应用程序状态,但有很多方法可以管理它,但我最常用的方法是在clojure协议下隐藏这些顶级服务,然后在clojure记录中执行它(可能会存在对数据库连接的引用或者其他)。

此方法最大限度地提高了灵活性,并防止您将自己写入角落。这与java的依赖注入是一致的。 Stuart Sierra最近在Clojure/West 2013上就这些主题做了一个很好的演讲,但该视频尚未公布。

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

如果您需要一个为什么这很有用的激励性示例,请考虑如何拦截对全球可访问的服务的所有访问?那么,你会推动完整的实现,并使入口点成为包装函数,而不是将相关细节推到更接近客户端代码的位置。如果你想为代码的某些客户而不是其他人提供某些行为?现在你被卡住了。这只是预期使这些不可避免的权衡取而代之,并让您的生活更轻松。