我正在编写一个小的Clojure应用程序,它与具有2-3个不同集合的MongoDB数据库进行了大量的交互。
我来自OOP/Ruby/ActiveRecord背景,其中的标准实践是为每个数据模型创建一个类,并为每个类提供对数据库的访问。我已经开始在我的clojure项目中做同样的事情。每个“数据模型”都有一个名称空间,每个名称空间都有自己的数据库连接和CRUD函数。但是,这感觉并不是很实用,也不像clojure,我想知道是否有一种更常用的方法,比如使用具有get-post等函数的data或database名称空间,并将对数据库的访问限制为只能访问该名称空间。
这似乎有将数据库客户端依赖隔离到一个名称空间的好处,而且还可以将纯函数与有副作用的函数分开。
另一方面,我还有一个名称空间,我需要从应用程序的许多不同部分引用该名称空间,而拥有一个名为"data“的名称空间对我来说似乎很奇怪。
在Clojure中有没有一种传统的、惯用的方式来做这件事呢?
发布于 2016-07-05 23:33:18
在Clojure应用程序中管理状态的一种很好的、可以说是最惯用的(scored 'adopt' on the Clojure radar)方法是Stuart Sierra的伟大的Component库提出的方法。简而言之,组件的原理是将所有有状态资源存储在显式定义它们相互关系的单个system映射中,然后以这样一种方式构建代码,即您的函数只是将状态传递给彼此。
发布于 2016-07-06 16:10:54
连接/环境访问
系统的一部分将是管理应用程序的“机械”:启动web服务器、连接do数据存储、检索配置等。将这一部分放在一个与业务逻辑分离的命名空间中(您的业务逻辑命名空间不应该知道此命名空间!)。正如@superkondukr所说,Component是一种经过战斗检验和良好记录的方式。
将数据库连接(以及其他环境依赖项)与业务逻辑进行通信的推荐方式是通过函数参数进行,而不是全局变量。这将使一切变得更可测试、更易于REPL,并且明确地表明谁依赖于谁。
因此,您的业务逻辑函数将接收作为参数的连接,并将其传递给其他函数。但是这种联系从何而来呢?我这样做的方式是在事件/请求进入系统时将其附加到事件/请求。例如,当您启动HTTP服务器时,您将连接附加到传入的每个HTTP请求。
命名空间组织:
在OO语言中,对数据的常规支持是表示数据库实体的类的实例;为了提供惯用的OO接口,然后将业务逻辑定义为这些类的方法。正如Eric Normand在最近的时事通讯中所说的那样,您将模型的“名称”定义为类,将“动词”定义为方法。
因为Clojure强调用于传递信息的普通数据结构,所以您实际上没有这些动机。你仍然可以通过实体来组织你的命名空间来模仿这一点,但我实际上并不认为这是最优的。您还应该考虑到这样一个事实,即Clojure名称空间与大多数OO语言中的类不同,不允许循环引用。
我的策略是:通过用例来组织你的命名空间。
例如,假设您的域模型有用户和帖子。您可能有一个用于用户CRUD和核心业务逻辑的myapp.user名称空间;类似地,您可能有一个myapp.post名称空间。也许在你的应用程序中,用户可以喜欢帖子,在这种情况下,你将在同时需要myapp.user和myapp.posts的myapp.like命名空间中管理帖子。也许你的用户可以成为你的应用程序中的朋友,你将在一个myapp.friendship命名空间中管理它。也许你有一个小的后台应用程序,提供了关于这一切的数据可视化:例如,你可以把它放在一个myapp.aggregations名称空间中。
https://stackoverflow.com/questions/38206535
复制相似问题