避免贫血域模型 – 一个真实的例子

我正试图了解贫血域模型,以及为什么它们被认为是反模式。

这是一个真实世界的例子。

我有一个Employee类,它有很多属性 – 名称,性别,用户名等

public class Employee { public string Name { get; set; } public string Gender { get; set; } public string Username { get; set; } // Etc.. mostly getters and setters } 

接下来,我们有一个系统,可以在销售人员之间均匀地调用来电和网站查询(称为“潜在客户”)。 这个系统是相当复杂的,因为它涉及到循环查询,检查假期,员工偏好等等。所以这个系统目前被分离出一个服务:EmployeeLeadRotationService。

 public class EmployeeLeadRotationService : IEmployeeLeadRotationService { private IEmployeeRepository _employeeRepository; // ...plus lots of other injected repositories and services public void SelectEmployee(ILead lead) { // Etc. lots of complex logic } } 

然后在我们的网站查询表单的背面,我们有这样的代码:

 public void SubmitForm() { var lead = CreateLeadFromFormInput(); var selectedEmployee = Kernel.Get<IEmployeeLeadRotationService>() .SelectEmployee(lead); Response.Write(employee.Name + " will handle your enquiry. Thanks."); } 

我并没有真正遇到这种方法的许多问题,但据说这是我应该尖叫的东西,因为它是一个贫血的领域模型

但是对于我来说,还不清楚领导轮换服务的逻辑应该在哪里。 是否应该领先? 是否应该进入员工?

轮换服务需要的所有注入的仓库等等 – 如何将它们注入员工,考虑到与员工打交道的大部分时间我们不需要任何这些仓库?

在这种情况下,这不构成一个贫血域模型。 一个贫血的领域模型是专门关于validation和转化的对象 。 所以一个例子就是如果一个外部函数实际上改变了员工的状态或者更新了他们的细节。

在这种情况下发生的事情是,你要带走所有的员工,根据他们的信息select其中的一个。 有一个单独的对象来检查他人,并就其所发现的事物做出决定,这很好。 有一个对象用于将对象从一个状态转换到另一个状态是不好的。

在你的情况下的一个贫血域模型的例子是有一个外部的方法

 updateHours(Employee emp) // updates the working hours for the employee 

这需要一个Employee对象,并更新本周工作的小时数,确保在小时数超过一定限制时提高标志。 这个问题是,如果你只有Employee对象,那么你不知道如何在正确的约束内修改他们的小时。 在这种情况下,处理它的方法是将updateHours方法移到Employee类中。 这是贫血域模式反模式的关键。

我认为你的devise在这里很好。 如你所知,贫血域模式反模式是对抗避免任何在域对象中编码的行为的趋势的反弹。 但是相反,这并不意味着与域对象有关的所有行为必须被该对象封装。

作为一个经验法则,内在地绑定到域对象的行为完全由一个域对象实例定义,可以包含在域对象中。 否则,为了保持责任清晰,最好将其外部放在合作伙伴/服务中,就像您所做的那样。

这一切都在你的脑海 – 考虑轮换服务成为领域模型的一部分,问题就解决了。

轮换需要保留很多员工的信息,所以既不属于主angular,也不属于任何一个员工对象。 它确实值得自己成为一个域对象。

只需将“RotationService”重命名为“Organization.UserSupportDepartment”即可。

如果你的领域模型只包含angular色和事物,而不是作为行为的活动,那么它是贫乏的。 但是,我正在谈论关于模型而不是对象的行为 。 我谈到他们之间的差异在另一个答案… https://stackoverflow.com/a/31780937/116442

从你的问题,你打破了我的前两个领域分析build模规则:

  1. 行为build模(logging)活动是领域模型的核心。 首先添加它们。
  2. 模型域活动作为类,而不是方法。

我会添加一个活动“调查”模型。 有了它,模型就具有行为,并且可以组合并作为对象组工作,而无需外部控制器或脚本。

EnquiryHandlerModel

Interesting Posts