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

Mat*_*caj 5 domain-driven-design responsibility

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

如果工厂创建了新的对象/图形/聚合实例,但也从Repository 中“重构”了对象/图形,则:

(1) 您的服务层功能/作业/任务/工作单元是否调用了工厂或实体实例或域服务功能上的行为方法?我对基于这些组件的职责的调用堆栈感到迷茫。

(2) Entity 实例甚至有像上面那样的“行为方法”吗?例如,Post 是否具有p.UpdatePost(string bodyText)域模型的关注点,因此存储库也应该实现相同的目标?或者服务层功能,在这种情况下它是否应该调用 Repository 而实体实例只是具有特定于域的行为方法而不是持久性?但是,为什么听起来像“更新帖子”是用户的目标时的域功能?

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

Arn*_*psa 4

(1) 您的服务层函数/作业/任务/工作单元是否调用工厂或实体实例或 DomainService 函数上的行为方法?由于这些组件的职责,我对调用堆栈感到困惑。

通常 - 顶层检索必要的聚合根并调用其上的函数。有时,顶层会检索多个聚合根并将它们传递给域服务,但这种情况并不常见,因为域服务是一个非常强烈的信号,表明存在无法识别的聚合根。在最后 - 顶层确保聚合根被持久化。

(2) 实体实例是否也有像上面这样的“行为方法”?例如,帖子是否有 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);
}
Run Code Online (Sandbox Code Playgroud)

域外:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)