(1)您的服务层函数/作业/任务/工作单元是否调用工厂或实体实例或 DomainService 函数上的行为方法?基于这些组件的责任,我迷失了调用堆栈。
通常 - 顶级检索必要的聚合根并在其上调用函数。有时顶级检索多个聚合根并将它们传递给域服务,但不经常因为域服务是一个非常强烈的信号,表明存在无法识别的聚合根。最后 - 顶级确保聚合根被持久化。
(2) Entity 实例甚至有像上面那样的“行为方法”吗?例如,Post 是否具有 p.UpdatePost(string bodyText) 或者这不是域模型的关注点,因此存储库也应该实现相同的目标?或者服务层功能,在这种情况下是否应该调用存储库并且实体实例只是具有特定于域而不是持久性的行为方法?但是,为什么听起来“更新帖子”是一个域功能,而这是用户的目标呢?
是的,他们有。域模型应该知道它的状态变化。这比一开始看起来更有益。这样做的好处是您获得了可扩展性点。如果客户将在一周后走到您面前并说他希望系统在用户更新帖子时检查其他内容 - 而不是搜索每一行post.bodyText="new value"
,您将能够直接进入post.UpdatePost
方法并在那里附加必要的东西。
另一方面 - CRUD 与领域驱动设计并不相互排斥。例如 - 在我的应用程序中,用户及其角色的管理非常无趣,我什至没有尝试对其进行精细建模。您需要识别业务中重要的部分您的应用程序正在描述和使用。
请记住,领域驱动设计仅对复杂的应用程序有意义。简单的博客应用程序不需要它。
(3) 假设服务层(而不是域服务)应该封装接口如何与域层交互,我错了吗?
正如我所看到的 - 应用程序服务更多地用于编排基础设施。如果不涉及基础设施,那么应用服务就会失去价值:
应用服务基本上只是门面。如果复杂性增加了它所解决的问题,那么每一个立面都是坏的。
内部域:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
域外:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}