1

在域驱动设计文献中,经常说域服务应该是无状态的。

我相信这是因为服务调用应该代表单个工作单元。不应该有多个服务方法会使用的任何服务状态。

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

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,我需要有状态(属性),以便服务方法可以访问相关的存储库等。

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

我如何构建域服务以使其无状态? 这甚至有必要吗?

编辑:

领域驱动设计中的Eric Evans :解决软件核心的复杂性:

当域中的重要过程或转换不是实体或值对象的自然责任时,将操作添加到模型中作为声明为服务的独立接口。根据模型的语言定义接口,并确保操作名称是 UBIQUITOUS LANGUAGE 的一部分。使 SERVICE 无状态

Vaughn Vernon还在他的《实现领域驱动设计》一书中推荐了无状态服务。

4

2 回答 2

2

在我看来,您将拥有属性与拥有状态混淆了。

UserService是一项服务。它只有无状态服务的只读(请删除 setter)属性,例如IUserRepository. 这使UserService自己成为无状态服务。

是的,我们甚至可以在上面添加一个更高级别的服务,IUserService它的组件之一是。该服务也将是无国籍的。

你为什么问?

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

诚然,如果我们的服务根本没有任何属性,这个问题就可以避免——UserRepository也许是。另请注意,当更高级别的服务(例如)仅具有此类服务的只读属性时,同样可以避免UserService这种情况,因为没有什么可分配的。我们可以放心,注入的服务将始终正确运行,因为它的层次结构中没有状态可供它依赖。

于 2017-12-21T16:48:38.920 回答
0

接近您的目标的一种方法是将 IOC 容器注入您的服务类,然后覆盖您的属性获取方法以解析必要类的实例。您的新课程将如下所示:

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 容器,这不是一件好事,但如果您试图更接近无状态服务,则可以这样做。

于 2014-02-26T14:44:11.143 回答