Domain driven design 与服务层或域对象本身的接口?(DDD)

Domain driven design 与服务层或域对象本身的接口?(DDD),domain-driven-design,responsibility,Domain Driven Design,Responsibility,我仍在学习DDD,我有两个问题(可能很简单): 如果创建了新的对象/图形/实例,但也从中创建了对象/图形,则: (1) 您的服务层功能/作业/任务/工作单元是否调用实体实例或DomainService功能的工厂或行为方法?基于这些组件的责任,我对调用堆栈一无所知 (2) 实体实例是否有上述“行为方法”?例如,一篇文章是否有p.UpdatePost(string bodyText),或者这不是域模型的问题,因此应该使用存储库实现同样的功能?或者服务层功能,在这种情况下,它是否应该调用存储库,而实体

我仍在学习DDD,我有两个问题(可能很简单):

如果创建了新的对象/图形/实例,但也从中创建了对象/图形,则:

(1) 您的服务层功能/作业/任务/工作单元是否调用实体实例或DomainService功能的工厂或行为方法?基于这些组件的责任,我对调用堆栈一无所知

(2) 实体实例是否有上述“行为方法”?例如,一篇文章是否有
p.UpdatePost(string bodyText)
,或者这不是域模型的问题,因此应该使用存储库实现同样的功能?或者服务层功能,在这种情况下,它是否应该调用存储库,而实体实例只是具有特定于域而不是持久性的行为方法?但是,为什么听起来“更新帖子”是一个域函数,而这是用户的目标呢

你可以看到我到处都是。请帮忙

(1) 您的服务层功能/作业/任务/工作单元是否调用实体实例或DomainService功能的工厂或行为方法?基于这些组件的责任,我对调用堆栈一无所知

通常-顶层检索必要的聚合根并对其调用函数。有时顶级检索多个聚合根并将其传递给域服务,但并不经常,因为域服务是存在无法识别的聚合根的非常明显的标志。最后,顶层确保聚合根被持久化

(2) 实体实例是否有上述“行为方法”?例如,一篇文章是否有p.UpdatePost(字符串bodyText),或者这不是域模型的问题,因此应该在存储库中实现同样的功能?或者服务层功能,在这种情况下,它是否应该调用存储库,而实体实例只是具有特定于域而不是持久性的行为方法?但是,为什么听起来“更新帖子”是一个域函数,而这是用户的目标呢

是的,有。域模型应该知道它的状态变化。而这在一开始看起来更有益。这样做的好处是您获得了可扩展性点。如果客户在一周后走到您跟前,说他希望系统在用户更新post时检查其他内容,而不是搜索
post.bodyText=“new value”
的每一行,您将能够直接转到
post.UpdatePost
方法,并在那里附加必要的内容

另一方面,CRUD与领域驱动设计并不相互排斥。例如,在我的应用程序中,对用户及其角色的管理非常枯燥,我甚至没有尝试对其进行粒度建模。您需要识别应用程序描述和使用的业务中重要的部分

请记住,域驱动设计仅适用于复杂应用程序。简单的博客应用程序不需要它

(3) 我认为服务层(不是域服务)应该封装接口与域层交互的方式,这是错误的吗

正如我所看到的,应用程序服务更多地用于编排基础架构。如果不涉及基础设施,则应用程序服务:

应用程序服务基本上只是表面的。如果复杂性增加了它所解决的问题的分量,那么每个门面都是不好的


域内:

//聚合根不知道持久性。
//它不应该直接引用存储库
公共类客户{
公共字符串名称{get;private set;}
公共静态客户寄存器(字符串名称){
返回新客户(名称);
}
受保护的客户(字符串名称){
//在这里,它知道状态的变化。
//聚合根更改其自身的状态
//而不是从外部改变状态
//通过公共财产
this.Name=Name;
}
}
//域模型包含持久性的抽象
公共接口ICCustomerRepository{
作废保存(客户);
}
域外:

公共类CustomerRepository:ICCustomerRepository{
//在这里,我们实际上将客户的状态保存到数据库/cloud/xml/任何地方
公共作废保存(客户){
//注意,我们并没有改变客户的状态,我们只是将其保存在这里
_voodoo.StoreItSomehow(客户);
}
}
//asp.net mvc控制器
公共类客户控制器{
公共CustomerController(ICCustomerRepository存储库){
如果(repository==null)抛出新ArgumentNullException();
_存储库=存储库;
}
公共操作结果寄存器(字符串名称){
var customer=客户登记簿(名称);
_保存(客户);
}
}

我认为服务层(而非域服务)应该封装接口与域层的交互方式吗?虽然我同意你的观点,博客应用程序似乎不需要DDD方法,但我试图通过一个非常简短的示例“顶级检索”来量化我思维中的变化?我不知道你这是什么意思?@cottsak在我的应用程序中,它通常是控制器。有时是应用程序服务。我认为,通过聚合来旋转业务逻辑的东西很好。另一个查询:“域模型应该知道它的状态变化”——通过这个查询,您是否在“状态变化”中包含持久性?根据我的理解,我假设您不基于@cottsak-域模型应该包含从外部实现和使用的持久性抽象。