15

好吧,我正在尝试为我的应用程序应用领域驱动设计原则,并使用包含数据字段和业务逻辑的丰富领域模型。我读过很多 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 类或反射在实例化时初始化其属性,这样我就不会用这么多参数污染构造函数?谁能给点建议?谢谢。

4

2 回答 2

12

您错过的是值对象的概念。值对象是小的、不可变的对象,在各自的领域中具有意义。

我不知道您的域的具体情况,但查看您的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# 代码,但我认为无论您使用哪种语言,这个想法都应该很清楚。

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

您还应该确保值对象是按值而不是按引用进行比较的,例如通过IEquatable<T>在 C# 中实现。

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


关于与问题没有直接关系的示例代码的进一步说明:

  • 领域模型是整个事物,实体其中的一部分。所以你的基类应该被调用Entity而不是DomainModel.

  • 您应该创建类的字段并在需要维护封装的地方private提供访问器。protected

于 2015-10-12T08:15:49.227 回答
2

您的 Job 域模型对象中发生了很多事情 - 它似乎混合了大量的关注点,并且(至少对我而言)暗示了许多有界上下文,其中一些很容易识别以便制作例子。

  1. 报酬(工资、福利)
  2. 组织职位(汇报线)
  3. 人员规格(技能)
  4. 工作规范(职责)
  5. 等等

例如,当您考虑与“工作”模型交互的事物时,是否需要检查或改变 Salary 属性和 Industry 属性?

在不了解该领域的全部细微差别的情况下,您因担任某个职位而获得的薪水与您所从事的行业并没有真正的联系,是吗?不是一个修辞点;这些是您需要询问领域专家的问题。

如果他们没有任何交互,那么您已经确定这两件事存在于两个不同的边界上下文中。Salary 方不需要与 Industry 方进行任何交互,反之亦然,即使有,是否需要同时在同一流程中保持状态?

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

DDD 告诉我们,一个单一的、统一的世界观很少能正确地解决任何问题。请探索 BOUNDED CONTEXTS - 结果,您的软件将更加灵活和灵活。

于 2015-10-13T19:18:52.983 回答