在领域驱动设计文献中,人们常说域名服务应该是无国籍的。
我认为这是因为服务电话应该代表单个工作单位。不应该是多种服务方法将使用的任何服务状态。
我在服务架构中违反了这条规则,以便构造函数可以注入服务中所需的所有相关存储库。例如:
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中推荐无国籍服务。
答案 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
)仅具有此类服务的只读属性时,同样可以完全避免,因为没有任何要分配的内容。我们可以放心,注入的服务将始终正常运行,因为它的层次结构中没有状态可供它依赖。