域驱动设计:如何处理包含大量数据字段的复杂模型?

时间:2015-10-11 16:55:22

标签: domain-driven-design domain-model rich-domain-model

我正在尝试为我的应用程序应用域驱动设计原则,其中包含包含数据字段和业务逻辑的丰富域模型。我读过许多DDD书籍,但似乎他们的域名模型(称为实体)非常简单。当我有一个包含10-15个数据字段的域模型时会出现问题,例如下面的那个:

class Job extends DomainModel{

    protected int id;
    protected User employer;
    protected string position;
    protected string industry;
    protected string requirements;    
    protected string responsibilities;    
    protected string benefits;
    protected int vacancy;
    protected Money salary;
    protected DateTime datePosted;
    protected DateTime dateStarting;
    protected Interval duration;   
    protected String status;
    protected float rating;  

    //business logic below 
}

如您所见,此域模型包含许多数据字段,所有这些字段都很重要,无法将其删除。我知道一个好的富域模型不应该包含setter方法,而是将其数据传递给构造函数,并使用业务逻辑来改变状态。但是,对于上面的域模型,我无法将所有内容传递给构造函数,因为它将导致构造函数方法中的15个以上参数。一个方法不应该包含超过6-7个参数,你不觉得吗?

那么我该怎么做才能处理具有大量数据字段的域模型?我应该尝试分解吗?如果是这样,怎么样?或者,我应该在实例化时使用Builder类或反射来初始化它的属性,这样我就不会用如此多的参数污染构造函数?谁能提出一些建议?谢谢。

2 个答案:

答案 0 :(得分:9)

您错过的是价值对象的概念。值对象是小的,不可变的对象,在相应的域中具有意义。

我不知道您所在域的具体细节,但查看您的Job实体,可能会有一个如下所示的值对象JobDescription

class JobDescription {
    public JobDescription(string position, string requirements, string responsibilities) {
        Position = position;
        Requirements = requirements;
        Responsibilities = responsibilities;
    }

    public string Position {get;}
    public string Requirements {get;}
    public string Responsibilities {get;}
}

这是C#代码,但我认为无论您使用何种语言,这个想法都应该清晰。

基本思路是以相应领域中有意义的方式对值进行分组。这当然意味着值对象也可以包含其他值对象。

您还应确保通过值而不是引用来比较值对象,例如:通过在C#中实现IEquatable<T>

如果使用这种方法重构代码,您将在实体上获得更少的字段,因此使用构造函数注入(强烈建议)再次变得可行。

有关与示例代码无直接关联的示例代码的进一步说明:

  • 域模型是一个整体,实体是其中的一部分。因此,您的基类应该被称为Entity而不是DomainModel

  • 您应该创建班级private的字段,并提供protected个访问者,以保持封装。

答案 1 :(得分:2)

在你的Job域模型对象中发生了很多事情 - 它似乎混合了大量的问题,并且(至少对我来说)暗示了一些有限的背景,其中一些很容易辨别出来做一个例子。

  1. 薪酬(薪酬,福利)
  2. 组织职位(报告专线)
  3. 人员规格(技能)
  4. 工作规范(职责)
  5. 当您考虑与“工作”模型相互作用的事物时,是否需要检查或改变工资属性和工业属性?例如?

    在不知道域名的完整细微差别的情况下,您获得职位所获得的薪酬和您所从事的行业并没有真正联系,是吗?不是一个修辞点;这些是您需要向领域专家提出的问题。

    如果他们没有任何互动,那么你已经发现这两件事存在于两个不同的有界背景中。薪酬方面不需要与行业方面进行任何互动,反之亦然,即使他们这样做了,他们是否需要同时在同一过程中保持状态?

    考虑一个人如何成为一名员工的生命周期;一个人申请工作。这份工作有规格,工资范围。这个人参加面试。租用者向该人提供该职位。该人接受。这个人现在是一名雇员,而不再是候选人。新员工现在正在积累假期和福利,并有开始日期等。

    DDD教导我们,对世界的单一,统一的观点很少能正确地解决任何问题。请探索有界的背景 - 因此,您的软件将更加灵活和灵活。