【问题标题】:Interface with service layer or domain objects themselves? (DDD)与服务层或领域对象本身的接口? (DDD)
【发布时间】:2011-05-17 02:19:49
【问题描述】:

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

如果Factory 创建了新的对象/图/aggregate 实例,而且还从Repository 创建了"reconstitutes" 对象/图,那么:

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

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

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

【问题讨论】:

  • wrong in assuming 是否认为服务层(而不是域服务)应该封装接口如何与域层交互?

标签: domain-driven-design responsibility


【解决方案1】:

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

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

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

是的,他们有。域模型应该知道它的状态变化。这比一开始看起来更有益。这样做的好处是您获得了可扩展性点。如果客户将在一周后走到您身边并说他希望系统在用户更新帖子时检查其他内容 - 而不是搜索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);
  }
}

【讨论】:

  • 虽然我同意你的观点,博客应用程序似乎不支持 DDD 方法,但我试图从一个非常简略的示例开始量化我的思维变化。
  • “顶级检索”?我不确定你的意思是什么?
  • @cottsak 在我的应用程序中它通常是控制器。有时应用服务。想要通过聚合根来旋转业务逻辑的东西。
  • @Arnis 太好了,我就是这么想的。另一个查询:“域模型应该知道它的状态变化” - 你是否在“状态变化”中包含持久性?我假设你不是基于other feedback i've received regarding this
  • @cottsak 根据我的理解 - 域模型应该包含从外部实现和使用的持久性抽象。
猜你喜欢
  • 2021-01-08
  • 1970-01-01
  • 2011-04-03
  • 2011-08-01
  • 2011-10-21
  • 1970-01-01
  • 2022-10-17
  • 2019-08-23
  • 1970-01-01
相关资源
最近更新 更多