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

时间:2010-11-29 04:25:32

标签: domain-driven-design responsibility

我还在学习DDD,我有这两个(可能是简单的)问题:

如果Factory创建了新的对象/图表/ aggregate个实例,还有来自"reconstitutes"Repository个对象/图表,那么:

(1)您的服务层功能/作业/任务/工作单元是否调用了Factory或Entity实例或DomainService函数的行为方法?基于这些组件的责任,我迷失了调用堆栈。

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

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

1 个答案:

答案 0 :(得分:3)

  

(1)您的服务层功能/作业/任务/工作单元是否调用了Factory或Entity实例或DomainService函数的行为方法?基于这些组件的责任,我迷失了调用堆栈。

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

  

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

是的,他们这样做。域模型应该知道它的状态变化。而这一开始似乎更有益。关于这一点的好处是你获得了可扩展性。如果客户端会在一周后向您走来并说他希望系统在用户更新发布时检查其他内容 - 而不是搜索post.bodyText="new value"的每一行,您将能够直接使用post.UpdatePost方法在那里附上必要的东西。

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

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

  

(3)假设服务层(不是域服务)应该封装接口如何与域层交互,我错了吗?

正如我所看到的 - 应用程序服务更多地用于协调基础架构。如果没有涉及基础设施 - 那么应用服务loses value

  

应用服务基本上只是外观。如果复杂性增加了它解决的问题,那么每个外观都很糟糕。


内部域名:

//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);
  }
}