假设你是一个贫血领域模型(ADM):
public class Employee
{
public Employee()
{
_roles = new List<Role>();
}
private IList<Role> _roles;
public Guid Id { get; set; }
public string Name { get; set; }
public IList<Roles> Roles { get { return _roles; } }
}
public class EmployeeManager
{
public Employee GetByName(string name)
{
Contract.Requires(name != null);
return repositoryOfEmployeesInstance.GetByName(name);
}
public void AddEmployee(string name)
{
Contract.Requires(name != null);
// The unique identifier will be generated by the OR/M behind the scenes...
repositoryOfEmployeesInstance.Add(new Employee { Name = "Matias" });
}
}
稍后,在其他地方,你有这段代码:
Employee some = new EmployeeManager().GetByName("Matias");
some.Roles.Add("Principal");
现在,除了域模型之外,还有一个名为DomainValidationAspect
的方面,它会在新员工在Repository
实施中保留之前对其进行验证。
整个ValidateEmployeeAspect
可以在添加或更新一个Employee
时验证Employee
,这是添加角色的情况。它负责加载Employee
的域规则并验证它们。域规则使用规范模式实现。
最后,所有事情都发生在域名交易中。
是的,从面向对象编程的角度看,它似乎是一个贫血的领域模型,但面向方面的编程呢。
......域名驱动的设计可能因为:
而贫血Employee
个角色? 我的观点是,面向方面编程的缺点是在域(或任何其他层)的主流中隐藏了大量细节,但对于面向对象加上背后的概念却有所了解。面向方面的方法将映射到富域模型而不是贫血域模型。
答案 0 :(得分:3)
想到几点(没有特别的顺序):
在域驱动设计中,聚合(此处为员工)永远不允许处于无效状态。它自己强制执行不变量,因此不需要进行外部验证。
这听起来非常像我的CRUD。为什么在简单的 CRUD 上强制 DDD ?
EmployeeManager
做了什么,只是包装了存储库方法,因此只是另一层复杂性。
repositoryOfEmployeesInstance
对我来说听起来非常人为。就像你不会打电话给EmployeeClass
或EmployeeManagerClass
一样,为什么你会用Instance
作为后缀?
另外为什么要附加模式名称(这里是 Repository )?请继续称之为employees
。这听起来像是一件真实的事情:
employees.GetByName(name)
甚至更好:
employees.Called(name)
答案 1 :(得分:1)
我认为,面向方面的编程具有这样的优点 在域的主流中隐藏大量细节的缺点(或 任何其他层)
IMO,这是在DDD中使用这种AOP方法的核心问题 - 它隐藏了细节。现在,对于严格的技术领域,例如日志记录,这通常是可取的。 AOP适用于这些领域,因为从某种意义上说,它是技术领域本身的特征 - 对传统OOP组合的扩展。另一方面,DDD针对非技术领域 - 业务用例。因此,DDD的目标之一是distillation of domain knowledge尽可能地将其从技术问题中解放出来。实现OOP的一步是将数据和行为聚集在对象内部。另一个步骤是从行为的技术名称转向更多业务特定的行为名称。这允许您捕获与行为相关的周围业务上下文,而不仅仅是技术上下文。
对DDD有用的是一组新的抽象。这不是一个不必要的复杂层,而是创造新语义的东西。正如Dijkstra所述,抽象应该创建新的语义级别。这可以以DSL的形式出现,其允许表达与技术问题无关的领域知识。然后,应用程序将这个DSL表达的域附加到基础设施 - 持久性,UI,服务等。创建这样的DSL既富有表现力又可以随时附着&#34;是一个很大的挑战。
要回答你的问题,是的,你的对象模型本身就是贫血,即使它是通过各方面的更丰富的行为组成的。然而,这只能解决您的对象模型以及对象模型是否贫血只是难题的一部分 - 对象模型是战术模式而非战略模式。
您的目标似乎朝着正确的方向发展 - 您希望将抽象级别提升到OOP提供的设施之外。我只是认为AOP的缺点超过了DDD案例中的好处。