Domain driven design 对应用程序结构和通信方向的质疑

Domain driven design 对应用程序结构和通信方向的质疑,domain-driven-design,clean-architecture,Domain Driven Design,Clean Architecture,我目前正在构建一个CQS风格的DDD应用程序。我对所有“组件”如何相互作用有些怀疑 但首先,我将简要概述应用程序的结构: ApplicationService -> Receives command objects -> doesn't return any results -> Acts on Domain model -> Speaks with Aggregate repository for domain modifications Quer

我目前正在构建一个CQS风格的DDD应用程序。我对所有“组件”如何相互作用有些怀疑

但首先,我将简要概述应用程序的结构:

ApplicationService 
  -> Receives command objects 
  -> doesn't return any results
  -> Acts on Domain model
  -> Speaks with Aggregate repository for domain modifications

QueryService
  -> Bypasses domain model; doesn't speak with Aggregate Repositories
  -> Executes queries against database to populate view
  -> Returns 'Representation' objects

REST Controller
  -> Receives HTTP requests and binds 'body content' & request params to Command objects
  -> delegates to ApplicationService for POST, PUT & DELETE requests
  -> Always returns at least some HTTP code
  -> delegates to QueryService for GET requests

Infrastructure
 -> Handles persistence to DB
 -> Contains some scheduling operations
 -> Handles foreign domain events our domain model is 'interested' in

'Open Host'
  -> This is mainly a Facade to be used by other domains
  -> Facade delegates methods to ApplicationService for domain modifications and to QueryService for data retrieval (bypassing Repositories)

我的问题是:

  • DomainEventHandler
    存储库
    相对应并调用
    聚合
    上的一些方法是否可以?还是应该始终与
    应用程序服务
    对应
  • QueryService
    返回“
    Representation
    ”对象。UI和
    'openhost'Facade
    使用它们作为返回值。
    Facade
    可以将这些对象作为返回值重用吗?还是应该
    Facade
    创建自己的对象,即使结果基本相同
  • ApplicationService
    将“
    命令
    ”作为输入参数。这些
    命令也被
    开放主机门面使用,可以吗?或者当委托给
    ApplicationService
    时,
    Facade
    是否只接受原语值并将其转换为
    命令
  • DomainEventHandlers
    似乎位于“
    基础设施”层。
    应用程序服务
    域服务
    是否也可能订阅
    域事件
    ?或者这始终是基础设施的责任
  • 欢迎所有建议

    DomainEventHandler与存储库对应并调用聚合上的某些方法可以吗?还是应该始终与应用程序服务相对应

    根据我的经验,任何处理程序都是应用程序服务

    QueryService返回“表示”对象。UI和“开放主机”外观使用这些作为返回值。Facade可以将这些对象作为返回值重用吗?还是Facade应该创建自己的对象,即使结果基本相同

    关于开放主机服务和应用程序服务之间的区别有很多讨论。我不清楚谁会使用开放主机服务,也不清楚它存在的原因

    ApplicationService将“命令”作为输入参数。这些命令是否也被开放主机门面使用?或者,当委托给ApplicationService时,Facade应该只接受基本值并将其转换为命令吗

    我将在应用程序的边缘传递原语,并将它们转换为命令,然后在应用程序服务中处理这些命令

    DomainEventHandler似乎位于“基础设施”层。ApplicationService或域服务是否也可能订阅域事件?或者这始终是基础设施的责任

    我一直认为我的处理程序是应用程序服务——负责编排用户案例的东西。因此,用例可能是“当收到EventX时,发送电子邮件并更新数据库”。在这个例子中,您可能会考虑“发送电子邮件的代码”和“保存到数据库的代码”作为基础设施的关注点,但是处理程序本身不会。

    public class ExampleHandler : IHandle<ExampleEvent> 
    {
        private IRepository _repo;
        private ISendEmails _emailer;
    
        public ExampleHandler(Repository repo, ISendEmails emailer)
        { 
            .... set the private fields..
        } 
    
        public void When(ExampleEvent event) 
        {
            _emailer.Send(event.whatever);
            _repo.Save(something);
        }
    }
    
    public类示例处理程序:IHandle
    {
    私人投资回购;
    私人ISendEmails(电邮);;
    公共示例处理程序(存储库repo、ISendEmails和emailer)
    { 
    ..设置专用字段。。
    } 
    公共无效时间(例如事件)
    {
    _emailer.Send(event.whatever);
    _保存(某物);
    }
    }
    

    老实说,我并不是真的从层的角度来思考——我更喜欢六边形架构的思维方式。在上面的示例中,事件处理程序只需要将依赖项注入到它们中,然后就可以开始它们的业务了

    谢谢你的回复!关于开放主机服务->我已经将其实现为其他域使用的接口。它可以被视为跨域通信的单个“接入点”。我的ApplicationService只在内部调用。其他域如何访问它?它是进程中的还是通过http等?只是想知道其他域是否可以使用相同的消息传递基础结构,因此它们所做的只是对发布的消息作出反应或发布自己的消息-如果您可以这样做,则可能根本不需要开放主机。其他域有两种可能:或者它们对异步发布的域事件作出反应;或者它们与facade(=开放主机)对应,用于数据检索或调用某个进程。facade当前由普通方法调用调用;然而,在将来,当我们发展到一个微服务架构时,这将成为一个REST服务。我认为你走对了方向