我正在学习域驱动设计,并且对实体和向其注入域服务有些困惑。我发现此博客的结论是将服务注入实体是一个坏主意。我部分同意这一点,但是在这种情况下该怎么做:我有一个User实体,它是一个聚合根,其中包含Password值对象。看起来像这样:
密码值对象:
public class Password { public string Hash { get; private set; } public string Salt { get; private set; } private readonly IHashGeneratorService _hashGeneratorService; public Password(IHashGeneratorService hashGeneratorService) { _hashGeneratorService = hashGeneratorService; } public void GenerateHash(string inputString) { //Some logic Salt = hashGeneratorService.GenerateSalt(); Hash = hashGeneratorService.GenerateHash(inputString); } }
用户实体:
public class User { public Password Password { get; private set; } public User(IHashGeneratorService hashGeneratorService) { this.Password = new Password(hashGeneratorService); } }
在这种情况下,如果我通过工厂创建User实体,则需要向工厂构造函数或Create()
方法提供IHashGeneratorService实现。在那之后,如果我的工厂被使用,例如。SomeUserService我必须为其提供实现(例如,通过ctor注入)。依此类推...老实说,它从我身上散发出来,因为我的许多类都依赖于哈希生成器服务实现,但只有密码类使用它。而且我认为这也违反了密码类的SRP原理。
我发现了一些解决方案:
使用服务定位器。但是它也有气味,因为它是一种反模式,如果我们使用它很难测试和管理实体。
直接在密码方法中实现哈希算法。
坚持上面所说的:)缺点,优点是我的类更易于测试,因为我可以提供模拟服务而不是完整实现。
就我个人而言,我倾向于将我的代码重新构造为第二种解决方案,因为它不会破坏SRP(或者会破坏SRP?:)),类不依赖于哈希服务实现。还有吗?还是您还有其他解决方案?