DDD:我应该在域实体上放置什么样的行为?

Byr*_*ahl 17 entity domain-driven-design solid-principles

我的团队非常努力地坚持使用Domain Driven Design作为架构策略.但是,在大多数情况下,我们的域实体非常有限.我们希望在我们的域实体上添加更多业务/域行为.

例如,Active Record将数据访问权限放在实体上.我们不希望这样,因为我们乐于使用存储库模式进行数据访问.

此外,我们将我们的软件设计为SOLID(Bob叔叔放在一起的五个软件设计原则).因此,在设计我们的实体时,我们注意单一责任,开放闭合,liskov,接口隔离和依赖性反转对我们很重要.

那么,我们应该包括哪些行为?我们应该远离什么样的?

Byr*_*ahl 24

自从我提出这个问题已经差不多一年了,从那以后我和我的团队已经学到了很多东西.以下是我今天回答这个问题的方法:

域应该代表(在代码中)业务是什么或做什么(在现实生活中).然后,域实体是在现实生活中发现的工件或演员.这些艺术品和演员有什么样的行为?所有的.反过来,域实体应该对它们采取什么样的行为?所有的.

例如,在现实生活中,经理可以雇用新员工.域名的表示应包括"经理"和"新员工"等实体.经理是演员,在这里.

//newEmployee comes from somewhere else... possibly the UI
//someManagerId comes from the logged in user
var manager = _repository.Get<Manager>(someManagerId);
manager.Hire(newEmployee);
Run Code Online (Sandbox Code Playgroud)

因此,经理实体在此模拟/反映现实生活中的行为.另一种方法是跳过作为演员的经理实体,并将他推到角落,这样一个繁重的"域名服务"可以完成所有的工作......像这样:

//newEmployeeService comes from somewhere else... possibly injected using IOC
newEmployeeService.Create(newEmployee, someManagerId);
Run Code Online (Sandbox Code Playgroud)

在贫困域中,您可以使用此类域服务来创建或雇用员工.它有效,但它不具有表现力,而且行为不是可发现的.谁做了什么?为什么经理需要创建新员工?


我想当我最初问这个问题时,我想尝试在我的实体中开始包含更多行为,但我真的不知道如何在不向我的实体注入服务的情况下(例如,使用构造函数注入).从那以后,我们学会了一些新的技巧,我们团队的实体具有超强的表现力.简而言之,这就是我们正在做的事情:

  1. 我们尽可能使用actor实体来表达执行该操作的人或事物.
  2. 演员有方法表达他们可以执行的动作
  3. 当需要服务时,它将作为参数注入到使用它的方法中.
  4. 我们在每个域实体上的每个方法上使用BlingBag触发域事件,以提供可扩展性并使实体能够自我持久化.

  • 那个newEmployee怎么样?它是由工厂还是存储库创建的?它会通过创建引发域名事件吗?域事件应该由存储库处理还是应该在域层之外?我可能会问太多:D (3认同)