Javascript Node.js的域驱动设计
我目前正在设计一个基于Node.js微服务的应用程序,我想使用域驱动设计作为构建单个服务的指导原则。我有以下几个问题:Javascript Node.js的域驱动设计,javascript,node.js,domain-driven-design,Javascript,Node.js,Domain Driven Design,我目前正在设计一个基于Node.js微服务的应用程序,我想使用域驱动设计作为构建单个服务的指导原则。我有以下几个问题: 据我所知,域层通常应该包含存储库接口,然后应该在基础架构层中创建这些接口的特定实现。这将底层存储/技术问题从域层抽象出来。在我的项目中,鉴于JavaScript本身不支持接口之类的东西,我们如何才能实现类似的效果呢 特别是一个服务将通过OAuth处理身份验证。人们通常会将OAuth相关逻辑归类为应用程序服务吗?还是属于基础设施层?我的理解是,它与基础架构无关,也与核心域无关,但
app/
----app.js
----package.json
----lib/
--------app/
------------service/
----------------oauth.js
----------------todo.js
--------domain/
------------list/
----------------model.js
----------------repository.js
----------------service.js
------------task/
----------------model.js
----------------repository.js
----------------service.php
--------http/
------------controller/
----------------list.js
----------------task.js
------------middleware/
----------------auth.js
----------------error.js
--------infrastructure/
------------db.js
------------logger.js
------------email.js
我很想听听你对这个布局的想法。我完全知道,项目结构的主题在某种程度上是基于观点的,但我总是渴望听到其他人的意见。领域驱动设计指导将系统分解为一组有限的上下文/服务/微服务。但是,您设计每个服务的方式是独立的,并且取决于服务的业务域。例如,您企业的核心域服务和支持域服务应该以不同的方式进行架构。您考虑过吗 它是一个用于Node.js和JavaScript的CQRS和事件源框架,可与域驱动设计(DDD)配合使用。它可能会让您对如何构造代码有一个很好的了解,还可以提供一个运行时来执行操作,而无需重新发明轮子
我知道背后的人,他们花了3-4年的时间思考,付出了血汗。即使这个问题已经很老了,我认为在你的第一次审问中增加一点精确性是有用的: 据我所知,域层通常应该包含存储库接口,然后应该在基础架构层中创建这些接口的特定实现。这将底层存储/技术问题从域层抽象出来。在我的项目背景下,鉴于JavaScript本身并不支持接口之类的东西,如何才能实现类似的效果 JavaScript不提供接口。与其模仿OOP的概念,为什么不看看更实用的呢?高阶函数非常适合javascript,您可以使用它们“声明”依赖项并在运行时注入它们:
const { FooData } = require('./data');
const getFooOfId = (getFooOfIdImpl = async (fooId) => { throw new Error(`Can't retrieved foo of id ${fooId} : missing implementation`) }) => async fooId => {
try {
const fooData = await getFooOfIdImpl(fooId);
return FooData(fooData);
} catch (err) {
throw new Error(`Unable to retrieve Foo with id ${fooId}`);
}
}
/*
This function is used to build a concrete implementation, for example with an in-memory database :
const inMemoryFooDatabase = {
foo17: {
id: 'foo17',
foo: 'a foo value',
bar: 'a bar value',
foobaz: 1234,
},
};
const getFooOfIdFromInMemoryDatabase = getFooOfId(fooId => inMemoryFooDatabase[fooId])
*/
module.exports = {
getFooOdId,
}
没有什么可以阻止您完全绕过此函数,因为javascript中没有强类型检查,但它充当了域“接口”需求的声明
如果您想了解更多信息,可以阅读我关于这个主题的帖子:您认为DDD设计会告诉您需要为项目中使用的子目录选择哪些名称吗?我对这件事所知甚少,听起来好像没有那么详细。看起来更重要的是确保在一个地方构建业务模型逻辑,并保留所有其他所需的支持材料(例如用户身份验证和其他简单的基础结构材料),但与实际业务逻辑无关,放在一个方便的单独地方。@jfriend00完全同意。在我看来,这就是DDD的主要驱动力——围绕“核心业务领域”构建。也许为了澄清,我会编辑我的帖子,强调我不太关注结构/命名,更多关于确保正确分类/分离的内容。但您的整个问题听起来像是关于将内容放在哪些目录中,而不是定义应用程序中的核心业务逻辑是什么,以及如何将其与其他内容分开进行结构。坦率地说,其他所有东西的去向并不是那么重要(例如,什么是服务,什么是基础设施)。这些只是应该选择的标签,以使您的项目布局对其他人清晰且便于使用。据我所知,DDD的主要目标是确保您知道核心业务逻辑是什么,它是如何构造的,以及它是如何编写的,以独立于所有与核心业务逻辑无关的支持代码。在许多方面,它与非常好的面向对象设计没有什么不同,它特别强调确保业务逻辑代码不会与非业务逻辑代码混合在一起。在启动一个新项目或一个新组件时,我会在同一个文件夹/名称空间中设置每个文件。然后我开始重构,一起行动。它避免了将重点放在基础设施或设计相关的名称上,而更多地放在业务上,这就是ddd的全部内容