领域驱动设计的简略设计步骤

首先,需要根据需求建立一个初步的领域模型,至少要识别出领域对象和领域对象之间的关系(可以是没有方向的关联关系)。这些领域对象只应该放在领域层中。如果存在应用职

首先,需要根据需求建立一个初步的领域模型,至少要识别出领域对象和领域对象之间的关系(可以是没有方向的关联关系)。这些领域对象只应该放在领域层中。如果存在应用职责,可以识别出应用类。它们用来协调领域对象,只负责提出问题,本身并不解决问题。解决问题是领域层的职责。这些应用类将被放在应用层中。

接下来分析领域模型,识别出实体对象和值对象。如果是实体对象,最好判断其标识的组成与生成方式。然后,再细致地分析关联关系,确定关联关系的游历方向。要注意几种特殊的关联关系。如果是多对多,则要看是否可以转换为有限定的一对多。对于循环引用关系,则需要特别注意。可以考虑利用查询(利用资源库)来解除其中一方的引用关系。如果要继续维护这种循环引用,需要考虑参与循环引用的多个对象之间的不变量。如果是双向关联,很可能是组成聚合的两个对象,但要判断哪个是聚合根。此时,彼此的构造函数是双重委派的,但其中非根对象的创建应该封装在根对象的构造函数(或者工厂)中。

之后,是划分聚合的边界,找到聚合根。放在聚合中的实体对象通常存在两个特点:1)不需要对它进行全局访问;2)它与聚合根有非常紧密的联系。如果无法确定聚合根,且又不是某个聚合范围中的对象,可以暂时当作聚合根对象来处理。

需要考虑资源库(Repository)对象了。通常,我们只需要对聚合根考虑资源库。主要是从查询的角度来判断资源库(这里存在查询方法的定义,需要哪些查询关键字,或者利用Criteria)。接着考虑对象的创建。需要考虑几个方面。一个是对象的构造函数参数,尤其是聚合根对象,要考虑聚合中的对象保持不变量。同时,还需要考虑标识的问题。第二要考虑是否需要工厂来封装对象的创建;第三需要考虑是否需要复制对象,即是否采用原型模式。如果需要复制,则要考虑聚合中的对象,哪些需要创建新的对象,哪些需要复制。

接下来,需要对模型进行进一步的细化。例如重点考虑循环引用。同时,还要分析是否需要对象的抽象和多态,以及是否需要考虑服务对象。

最后,是对模块的划分。最好不要根据模式来分类,将实体对象、值对象、资源库等对象分别放在一起,而应该按照业务逻辑的内聚性对对象进行模块划分。

注意,在识别领域模型时,对于业务规则和约束来说,需要利用规格(Specification)模式对这些进行封装。另外,切忌将与业务和业务规则相关的职责放到应用层中。应用层应该是薄薄的一层。当然,在整个DDD设计过程中,还需要不断迭代、精化和重构。