我的团队非常努力地坚持使用域驱动设计作为架构策略.但是,大多数时候,我们的域名实体是非常有启发性的.我们希望将更多的业务/域名行为放在我们的域实体上.
例如,活动记录将数据访问放在实体上.我们不希望这样,因为我们很高兴地使用存储库模式进行数据访问.
此外,我们将软件设计为SOLID(Bob叔叔组合的五个软件设计原则).那么对我们来说重要的是在设计实体时注意单一责任,开放式,liskov,接口隔离和依赖性反转.
那么我们应该包括什么样的行为呢?我们应该怎么办?
自从我问这个问题已经差不多一年了,我和我的团队从那以后学到了很多.以下是我今天回答这个问题的方法:
领域应该代表(代码)业务是做什么的(在现实生活中).那么,域实体就是在现实生活中发现的工件或行为者.这些人造文具和演员有什么样的行为?所有的.反过来,域名实体对他们有什么样的行为?所有的.
例如,在现实生活中,经理可以聘请一名新员工.域名的代表应包括“经理”和“新员工”等实体.经理是演员,在这里.
//newEmployee comes from somewhere else... possibly the UI //someManagerId comes from the logged in user var manager = _repository.Get<Manager>(someManagerId); manager.Hire(newEmployee);
所以,经理实体模型/反映现实生活中的行为,在这里.替代方案是跳过经理实体作为一个演员,并把他推到角落,所以一个繁重的“域名服务”可以做所有的工作,像这样:
//newEmployeeService comes from somewhere else... possibly injected using IOC newEmployeeService.Create(newEmployee,someManagerId);
在贫血域中,您将使用此类域名服务来创建或雇用员工.它的工作原理,但并不表达,行为不是可以发现的.谁做了什么?为什么经理需要创建一个新员工?
我想当初我问这个问题时,我想尝试开始在我的实体中增加更多的行为,但是我真的不知道如何在我的实体中注入服务(例如使用构造器注入).从那时起,我们学到了一些新的技巧,我们团队的实体是超级表现力的.简而言之,我们在做什么:
>我们尽可能地使用演员实体来表达正在执行动作的人物或事物.
演员有方法表达他们可以执行的动作
>当需要一个服务时,它被作为参数注入到使用它的方法中.
>我们使用每个域实体上的每种方法使用BlingBag触发域事件,以提供可扩展性,并赋予实体自我坚持的能力.