Javascript Node.js的域驱动设计

Javascript Node.js的域驱动设计,javascript,node.js,domain-driven-design,Javascript,Node.js,Domain Driven Design,我目前正在设计一个基于Node.js微服务的应用程序,我想使用域驱动设计作为构建单个服务的指导原则。我有以下几个问题: 据我所知,域层通常应该包含存储库接口,然后应该在基础架构层中创建这些接口的特定实现。这将底层存储/技术问题从域层抽象出来。在我的项目中,鉴于JavaScript本身不支持接口之类的东西,我们如何才能实现类似的效果呢 特别是一个服务将通过OAuth处理身份验证。人们通常会将OAuth相关逻辑归类为应用程序服务吗?还是属于基础设施层?我的理解是,它与基础架构无关,也与核心域无关,但

我目前正在设计一个基于Node.js微服务的应用程序,我想使用域驱动设计作为构建单个服务的指导原则。我有以下几个问题:

  • 据我所知,域层通常应该包含存储库接口,然后应该在基础架构层中创建这些接口的特定实现。这将底层存储/技术问题从域层抽象出来。在我的项目中,鉴于JavaScript本身不支持接口之类的东西,我们如何才能实现类似的效果呢
  • 特别是一个服务将通过OAuth处理身份验证。人们通常会将OAuth相关逻辑归类为应用程序服务吗?还是属于基础设施层?我的理解是,它与基础架构无关,也与核心域无关,但作为向客户提供应用程序的一部分,它仍然是必需的。因此,我现在将其放在应用程序层中
  • 从第2点开始,OAuth相关的实体/存储库(即令牌/客户机)最好放在哪里?我很想把它们和我的其他实体/存储库一起放在域层,即使它们在技术上不是一个业务问题
  • 对上述内容添加的一些注释:

  • 我不喜欢使用打字脚本(如建议的那样)
  • 我完全意识到有些人可能认为JavaScript不适合DDD类型的方法。我熟悉其中的一些陷阱,我再次使用DDD作为指导 另一方面,我提出了以下项目结构,其灵感来源于Laravel一个基于DDD的伟大项目:

    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的全部内容