写点什么

领域驱动设计 DDD

用户头像
积极&丧
关注
发布于: 2020 年 12 月 26 日

为什么需要DDD

  • 很多项目的实际情况

  • 用户或者产品经理的需求零零散散。不断变更。

  • 工程师在各处代码中寻找可以实现这些需求变更的代码,修修补补。

  • 软件只有需求分析,并么有真正的设计,系统没有一个统一的领域模型维持其内在的逻辑一致性。

  • 功能特性并不是按照领域模型内在的逻辑设计,而是按照各色人等自己的主观想象设计。

  • 项目时间一长各种困难重重,需求不断延期,线上bug不断,管理者考虑是不是要推倒重来,而程序员则考虑是不是要跑路。

贫血模型VS充血模型

  • 由于事务脚本模式中,Service、Dao这些对象只有方法,没有数值成员变量,而方法调用时传递的数值对象,比如Contract,没有方法(或者只有一些gettter,setter方法),因此事务脚本又被称作贫血模型。

  • 领域模型的对象则包含了对象的数据和计算逻辑,比如合同对象,既包含合同数据,也包含合同相关的计算。因此从面向对象的角度看,领域模型才是真正的面向对象。收入确认是合同强相关的,是合同对象的一个职责,那么合同对象就应该提供一个calculateRecognition方法计算收入。

  • 领域模型是合并了行为和数据的领域的对象模型。通过领域模型对象的交互完成业务逻辑的实现,也就是说,设计好了领域模型对象,也就设计好了业务逻辑实现。和事务脚本被称作贫血模型相对应的,领域模型也被称为充血模型。

  • 我们现在工作中,实际是贫血模型的方式来编程的,充血模型比贫血模型更好。

DDD战略设计

  • 包含

  • 战略设计

  • 领域、子域、界限上下文、上下文映射图

  • 战术设计

  • 实体、值对象、聚合、CQRS、事件溯源

  • 通过战略设计,划分模块和服务的边界及依赖关系,对微服务架构的设计至关重要。

  • 领域是一个组织所做的事情以及其包含的一切,通俗地说,就是组织的业务范围和做事方式,也是软件开发的目标范围。

  • 领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。

子域

  • 领域四一个组织所做的事情以及其包含的一切。这个范围就太大了,不知道该如何下手。所以通常的做法是把整个领域拆分成多个子域,比如、用户、商品、订单、库存、物流、发票等。

  • 如何划分子域

  • 限界上下文

  • 在一个子域中,会创建一个概念上的领域边界,在这个边界中,任何领域对象都只表示特定于该

边界内部的确切含义。这样边界便称为限界上下文。限界上下文和子域具有一对一的关系,用来控制子域的边界,保证子域内的概念统一性。

  • 通常限界上下文对应一个组件或者一个模块,或者一个微服务,一个子系统。

  • 上下文映射图

  • 不同的限界上下文,也就是不同的子系统或者模块之间会有各种的交互合作。DDD使用上下文映射图来设计这种关联和交互。

实体

  • 领域模型对象也被称为实体,每个实体都是唯一的,具有一个唯一标识,一个订单对象是一个实体,一个产品对象也是一个实体,订单ID或者产品ID是它们的唯一标识。实体可能会发生变化,比如订单的状态会变化,但是它们的唯一标识不会变化。

  • 实体设计是DDD的核心所在,首先通过业务分析,识别出实体对象,然后通过相关的业务逻辑设计实体的属性和方法。这里最重要的,是要把握住实体的特征是什么,实体业务承担什么职责,不应该承担什么职责,分析的时候要放在业务场景和界限上下文中,而不是想当然地认为这样的实体就应该承担这样的角色。

值对象

  • 并不是领域内的对象都应该被设计为实体,DDD推荐尽可能将对象设计为值对象。比如像住址这样的对象就是典型的值对象,也许建在住址上的房子可以被当做一个实体,但是住址仅仅是对房子的一个描述,像这样仅仅用来做度量或描述的对象应该被设计为值对象。

  • 值对象的特点是不变性,一个值对象创建以后就不能再改变了。如果地址改变了,那就是一个新地址,而一个订单实体则可能会经历创建、待支付、已支付、代发货、已发货、代签收、待评价等各种变化。

聚合

  • 聚合是一个关联对象的集合,我们将其作为一个单元来处理数据更改。每个集合都有一个跟和一个边界。边界定义聚合内部的内容。根是聚合中包含的单个特定实体。

  • 聚合根:将多个实体和值对象聚合在一起的实体。

  • 一个微服务可以包含一个聚合或者多个聚合,但是一个聚合不能被拆到多个服务里面去了。

  • 演变,早起一个微服务可以有多个聚合,慢慢再拆分成很多单个或者很少聚合的服务。

DDD分层架构

  • 领域实体的组合调用和事务控制在应用层。

DDD六边形架构

  • 领域模型通过应用程序封装成一个相对比较独立的模块,而不同的外部系统则通过不同的适配器和领域模型交互,比如可以通过HTTP接口访问领域模型,也可以通过WebService 或者消息队列访问领域模型,只需要为这些不同的访问接口提供不同的适配器就可以了。



用户头像

积极&丧

关注

还未添加个人签名 2019.02.13 加入

还未添加个人简介

评论

发布
暂无评论
领域驱动设计DDD