从面向方面的编程角度看贫困领域模型。贫血?

时间:2013-01-11 10:36:18

标签: c# oop domain-driven-design domain-model aop

假设你是一个贫血领域模型(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个角色?
  • ...从纯面向对象编程的角度来看,{{1}}中没有行为?

有些话

我的观点是,面向方面编程的缺点是在域(或任何其他层)的主流中隐藏了大量细节,但对于面向对象加上背后的概念却有所了解。面向方面的方法将映射到富域模型而不是贫血域模型

2 个答案:

答案 0 :(得分:3)

想到几点(没有特别的顺序):

  • 在域驱动设计中,聚合(此处为员工永远不允许处于无效状态。它自己强制执行不变量,因此不需要进行外部验证。

  • 这听起来非常像我的CRUD。为什么在简单的 CRUD 上强制 DDD

  • EmployeeManager做了什么,只是包装了存储库方法,因此只是另一层复杂性。

  • repositoryOfEmployeesInstance对我来说听起来非常人为。就像你不会打电话给EmployeeClassEmployeeManagerClass一样,为什么你会用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案例中的好处。