首页 文章

在clojure应用程序中放置数据库访问/功能的位置?

提问于
浏览
6

我正在编写一个小型的Clojure应用程序,该应用程序与具有2-3个不同集合的MongoDB数据库进行了大量交互 .

我来自OOP / Ruby / ActiveRecord背景,其中标准做法是为每个数据模型创建一个类,并为每个数据模型提供访问权限 . 我感觉非常功能或类似于clojure,我想知道是否有更惯用的方式,例如 datadatabase 命名空间与 get-post 等功能,并限制只访问该命名空间的数据库 .

这似乎有利于将数据库客户端依赖关系仅隔离到一个命名空间,并且还将纯函数与具有副作用的函数分离 .

另一方面,我还需要一个名称空间,我需要从我的应用程序的许多不同部分引用它,并且拥有一个名为“data”的命名空间对我来说似乎很奇怪 .

在Clojure中是否有传统的,惯用的方式?

2 回答

  • 2

    在Clojure应用程序中管理状态的一种不错的,可以说是最惯用的(scored 'adopt' on the Clojure radar)方式是由Stuart Sierra的伟大的Component库提出的 . 简而言之,Component的理念是将所有有状态资源存储在一个明确定义其相互关系的单一 system 映射中,然后以您的函数仅将状态传递给彼此的方式构建代码 .

  • 2

    连接/环境访问

    系统的一部分将是管理应用程序的'machinery':启动Web服务器,连接数据存储,检索配置等 . 将此部分放在与业务逻辑不同的命名空间中(您的业务逻辑命名空间不应该知道)关于这个命名空间!) . 正如@superkondukr所说,Component是经过实战检验并且记录完备的方法 .

    将数据库连接(以及其他环境依赖关系)与业务逻辑通信的推荐方法是 via function arguments, not global Vars. 这将使一切更易于测试,对REPL友好,并明确谁依赖于谁 .

    因此,您的业务逻辑函数将接收连接作为参数并将其传递给其他函数 . 但是,连接首先来自哪里?我这样做的方法是在进入系统时将它附加到事件/请求 . 例如,当您启动HTTP服务器时,将连接附加到每个进入的HTTP请求 .

    命名空间组织:

    在OO语言中,对数据的传统支持是表示数据库实体的类的实例;为了提供惯用的OO接口,业务逻辑然后被定义为这些类的方法 . 正如Eric Normand在最近的时事通讯中所说,你将模型的'名称'定义为类,将'动词'定义为方法 .

    因为Clojure强调简单的数据结构来传递信息,所以你并没有真正拥有这些激励 . 您仍然可以按实体组织命名空间来模仿这个,但实际上我并不是最佳的 . 您还应该考虑到Clojure命名空间与大多数OO语言中的类不同,不允许循环引用 .

    我的策略是: organize your namespaces by use case .

    例如,假设您的域模型包含用户和帖子 . 您可能拥有用于用户CRUD和核心业务逻辑的 myapp.user 命名空间;类似地,您可能有一个 myapp.post 命名空间 . 也许在你的应用程序中,用户可以喜欢Posts,在这种情况下,你将在 myapp.like 命名空间中管理它,这需要 myapp.usermyapp.posts . 也许您的用户可以成为您应用中的朋友,您将在 myapp.friendship 命名空间中管理 . 也许您有一个小的后台应用程序,其中包含有关所有这些的数据可视化:例如,您可以将它放在 myapp.aggregations 命名空间中 .

相关问题