DDD无状态服务和构造函数注入

时间:2014-02-26 09:44:44

标签: design-patterns dependency-injection domain-driven-design domainservices onion-architecture

在领域驱动设计文献中,人们常说域名服务应该是无国籍的。

我认为这是因为服务电话应该代表单个工作单位。不应该是多种服务方法将使用的任何服务状态。

我在服务架构中违反了这条规则,以便构造函数可以注入服务中所需的所有相关存储库。例如:

public class UserService : IUserService
{
    public IUnitOfWork UnitOfWork { get; set; }

    public IUserRepository UserRepository { get; set; }

    public ICustomerRepository CustomerRepository { get; set; }

    public UserService(IUnitOfWork unitOfWork, IUserRepository userRepository, ICustomerRepository customerRepository)
    {
        UnitOfWork = unitOfWork;
        UserRepository = userRepository;
        CustomerRepository = customerRepository;
    }

    public User RegisterNewUser(...)
    {
        // Perform relevant domain logic
    }

    // ...
}

为了让我在UserService上使用构造函数注入,我需要有状态(属性),以便服务方法可以访问相关的存储库等。

虽然我希望将个别服务方法设计为独立的工作单元,但我不一定能阻止这种情况发生。

我如何构建域名服务以使其无国籍?这是否必要?

修改

Domain-driven Design: Tackling Complexity in the Heart of Software中的 Eric Evans

  

当域中的重要流程或转换不是a   ENTITY或VALUE OBJECT的自然责任,添加操作   将模型作为声明为SERVICE的独立接口。定义   根据模型的语言界面并确保   操作名称是UBIQUITOUS LANGUAGE的一部分。制作服务   的无状态

Vaughn Vernon 还在他的书Implementing Domain Driven Design中推荐无国籍服务。

2 个答案:

答案 0 :(得分:0)

接近目标的一种方法是将IOC容器注入服务类,然后覆盖属性get方法以解析必要类的实例。你的新课程看起来像这样:

public class UserService : IUserService
{
  private IUnitOfWork UnitOfWork 
  { 
    get{return container.Resolve<IUnitOfWork>()}
  }
  private IUnityContainer container {get;set;}

  public UserService(IUnityContainer container )
  {
    this.container = container;
  }

  public User RegisterNewUser(User user)
  {
     //Domain logic
  }

}

您的服务类现在依赖于IOC容器,这不是一件好事,但如果您想要接近无状态服务,那么就可以实现。

答案 1 :(得分:0)

在我看来,你混淆了拥有属性的状态。

UserService是一项服务。它只有readonly(请删除setters )属性,这些属性是无状态服务,例如IUserRepository。这使UserService本身成为无状态服务。

是的,我们甚至可以在顶部添加更高级别的服务,其中IUserService作为其组件之一。那项服务也是无国籍的。

为什么,你问?

无国籍状态的目的(或至少 目的)是允许控制反转:我们放弃对我们得到的实例的控制权。如果其他人正在控制我们获得的实例,那么这些实例最好是无状态的!如果我们得到另一个类获得的相同实例,并且我们都开始改变它的状态怎么办?结果将是不确定的。

显然,如果我们的服务没有属性(例如UserRepository),则可以避免此问题。另请注意,当较高级别的服务(例如UserService)仅具有此类服务的只读属性时,同样可以完全避免,因为没有任何要分配的内容。我们可以放心,注入的服务将始终正常运行,因为它的层次结构中没有状态可供它依赖。