preview

设计领域模型的一般步骤

  1. 根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;
  2. 进一步分析每个上下文内部,识别出哪些是实习,哪些是值对象;
  3. 对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;
  4. 为聚合根设计仓储,并思考实体或值对象的创建方式;
  5. 在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。

​ 现实世界中,领域包含了问题域解系统。在DDD中,解系统可以映射为一个个限界上下文,限界上下文就是软件对于问题域的一个特定的、有限的解决方案

模块Module是DDD中明确提到的一种控制限界上下文的手段,在工程中一般尽量用一个模块来表示一个领域的限界上下文

​ 一般的工程中,的组织方式为:{com.公司名.组织架构.业务.上下文.},这样的组织结构能够明确地将一个上下文限定在包的内部*。

​ 对于模块内的组织结构,一般是按照领域对象、领域服务、领域资源库、防腐层等组织方式定义。

有以下几种情况会考虑引入防腐层

  • 需要将外部上下文中的模型翻译成为当前上下文理解的模型。
  • 不同上下文之间的团队协作关系,如果是供奉者关系,建议引入防腐层,避免外部上下文变化对本上下文的侵蚀。
  • 该访问本上下文使用广泛,为了避免改动影响范围过大。

限界上下文

​ 一个由显示边界限定的特定职责。领域模型便存在于这个边界之内。在边界内,每一个模型概念,包括它的属性和操作,都具有特殊的含义。

划分限界上下文

  • 考虑产品所讲的通用语言,从中提取一些术语称之为概念对象,寻找对象之间的联系;
  • 或者从需求里提取一些动词,观察动词对象之间的关系;
  • 紧耦合的各自圈在一起,观察他们内在的联系,从而形成对应的限界上下文
  • 形成之后,可以尝试用语言来描述界限上下文的职责,看它是否清晰、准确、简洁和完成;
  • 简而言之,限界上下文应该从需求出发,按领域划分

限界上下文之间的映射关系

​ 明确限制了限界上下文的耦合性,无论是上下文内部交互还是与外部上下文交互,耦合度都限定在数据耦合(Data Coupling)的层级。

  • 合作关系ParnetShip:两个上下文紧密合作的关系;
  • 共享内核SharedKernel:两个上下文依赖部分共享的模型;
  • 客户方-供应方开发Cunsomer-Supplier Development:上下文之间有组织的上下游依赖;
  • 尊奉者Conformist:下游上下文只能盲目依赖上游上下文;
  • 防腐层Anticorruption Layer:一个上下文通过一些适配和转换与另一个上下文交互;
  • 开放主机服务Open Host Service:定义一种协议来让其他上下文来对本上下文进行访问;
  • 发布语言Published Language:通常与OHS一起使用,用于定义开放主机的协议;
  • 大泥球Big Ball of Mud:混杂在一起的上下文关系,边界不清晰;
  • 另谋他路SeparateWay:两个完全没有任何联系的上下文;

上下文集成:通常集成上下文的手段有多种,常见的手段包括开放领域服务接口、开放HTTP服务以及消息发布-订阅机制。

DDD的一些定义

  • 实体Entity:一个对象由其标识(而不是属性)区分。在实践上建议将属性的验证放到实体中。

  • 值对象Value Object:一个对象用于对事务进行描述而没有唯一标识。具有不变形、相等性、可替换性。在实践中,需要保证值对象创建后就不能被修改,即不允许外部再修改其属性。在不同上下文集成时,会出现模型概念的公用。

  • 聚合根Aggregate Root:聚合是一组相关对象的集合,作为一个整体被外界访问。聚合根是这个聚合的根节点。核心领域往往都需要用聚合来表达。聚合在技术上可以知道详细设计。聚合由根实体、值对象实体组成。

    创建好的聚合

    • 边界内的内容具有一致性:在一个事务中只修改一个聚合实例。如果你发现边界内很难接受强一致,不管是出于性能或产品需求的考虑,应该考虑剥离出独立的聚合,采用最终一致的方式。
    • 设计小聚合:大部分的聚合都可以只包含根实体,而无需包含其他实体。即使一定要包含,可以考虑将其创建为值对象
    • 通过唯一标识来引用其他聚合或实体:当存在对象之间的关联时,建议引用其唯一标识而非引用其整体对象。如果是外部上下文中的实体,引用其唯一标识或将需要的属性构造值对象。 如果聚合创建复杂,推荐使用工厂方法来屏蔽内部复杂的创建逻辑。

    ​ 聚合内部多个组成对象的关系可以用来指导数据库创建,但不可避免存在一定的抗阻。如聚合中存在List<值对象>,那么在数据库中建立1:N的关联需要将值对象单独建表,此时是有id的,建议不要将该id暴露到资源库外部,对外隐蔽。

  • 领域服务:一些重要的领域行为操作。既不是实体,也不是值对象的范畴。当采用了微服务架构风格,一切领域逻辑的对外暴露均需要通过领域服务来进行。

  • 领域事件:对领域内发生的活动进行建模。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐