代码之家  ›  专栏  ›  技术社区  ›  Matt Kocaj

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

  •  4
  • Matt Kocaj  · 技术社区  · 14 年前

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

    如果 Factory 创建新对象/图形/ aggregate 实例,但也 "reconstitutes" 对象/图形 Repository ,然后:

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

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

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

    1 回复  |  直到 14 年前
        1
  •  3
  •   Community CDub    8 年前

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

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

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

    是的,他们有。域模型应该知道它的状态变化。从一开始看起来,这样做更有益。很好的一点是,您获得了可扩展性点。如果客户会在一周后走到你跟前,说他希望系统在用户更新帖子时检查其他内容,而不是搜索 post.bodyText="new value" ,您可以直接转到 post.UpdatePost 方法和附加必要的东西。

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

    请记住,域驱动的设计只对复杂的应用程序有意义。简单的博客应用程序不需要它。

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

    正如我所见,it应用服务更多的是用于协调基础设施。如果不涉及基础设施,那么应用程序服务 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);
      }
    }
    
    推荐文章