DDD入门

DDD并不是一个新的概念,事实上,在十多年前,这一概念就被提出,只是没有得到广泛的应用而已,大家可以看下我们互联网系统的进化历程,应用从单体到微服务,数据从冷备热备到多活,开发方式从瀑布到敏捷,我们的系统变得更灵活,架构变得跟清晰扁平。但是我们只关注了系统层面的架构或者设计,而忽略了业务层面的设计,互联网的特点就是快,业务先跑起来再说,有问题以后再优化,再重构,结果就是业务越堆越多,架构越来越混乱,到最后谁都不敢再去重构这么一个臃肿的系统,这是我们在前期缺乏对业务的整体建模和思考的后果,尤其是对于复杂业务,这个时候大家开始寻求一种解决问题的方式,自然而然的将目光转向了DDD-领域驱动设计。

概念

什么是DDD

DDD是领域驱动设计,所谓领域驱动设计,是指我们在软件设计的时候,重点关注业务逻辑,熟悉业务逻辑,从而抽象出来领域模型,基于领域模型展开系统设计

DDD能解决什么问题

解决复杂业务系统的大泥球问题,让业务系统变的更健壮,更利于扩展&维护

谁适合DDD

复杂的业务系统

战略建模工具

之所以会采用DDD,是因为业务模型的高度复杂,我们应专注于业务复杂性而非技术复杂性

限界上下文

限界上下文是语义和语境上的边界,一个团队可以在多个限界上下文中工作,但是多个团队不能在一个限界上下文中共事

通用语言

通用语言是在限界上下文中表达其边界的工具,这一语言由在该限界上下文中开发的每个成员使用,软件模型的源代码就是这种语言的书面表达方式

子域

子域代表的是一个单一的,有逻辑的领域模型,限界上下文应该与子域一一对应,主要有一下几种子域类型

核心域

它是一个唯一的,定义明确的领域模型,要对他进行战略投资,并在一个明确的限界上下文中投入大量资源去精心打磨通用语言

支撑子域

支撑子域的场景是找不到现成的解决方案,但是重要程度远远不如核心域,可以通过定制开发或者外包的方式实现此类限界上下文

通用子域

通用子域的解决方案可以是采购现成的,外包的,或者团队内部实现的

上下文映射

上下文映射(context mapping)是指不通限界上下文之间的映射关系,包括两个限界上下文之间的集成关系以及团队之间的动态关系,由于不通的限界上下文存在不通的通用语言,上下文映射也代表不通语言之间的转译过程

映射的种类

  1. 合作关系
  2. 共享内核
  3. 客户-供应商
  4. 跟随者
  5. 防腐层
    下游团队在其通用语言和它的上游通用语言之间建立的一个翻译层,隔离了下游模型和上游模型,并完成两者之前的翻译。比如API网关
  6. 开放主机服务
    开放式主机服务会定义一套协议或者接口,让限界上下文可以被当做一组服务访问 REST
  7. 已发布语言
    已发布语言是一种有着丰富文档的信息交换语言,同事提供 和使用已发布语言的开放主机服务可以为第三方提供最佳的集成体验,比如RPC
  8. 各行其道
    没有关系,不需要控制和承诺
  9. 大泥球

集成方式有

  1. RPC
  2. RESTFul Http
  3. 消息机制
    基于领域事件的发布订阅来完成,可以很好地用来解耦,但要注意增强事件和反向查询之前的权衡
    基于数据库的集成方式是一定要避免的,可以说是一种返末世,首先,它是单点故障和性能瓶颈的源头,违背了“高内聚,低耦合”的设计原则,对数据库的任何调整将会引起霰弹是修改,消费方上下文受到数据库内部细节和技术选型的干扰

架构

  1. 端口射适配器架构,即六边形架构
  2. 事件驱动架构
  3. CQRS
  4. 响应式架构和Actor模型
  5. 具象状态传输REST
  6. SOA和微服务
    SOA将应运程序的不通功能单元(服务)通过服务之间定义好的接口和契约联系起来,SOA和微服务一脉相承,微服务可以认为是SOA的一种特定的现代实现,微服务相对于SOA更注重对独立业务单元的拆分来形成清晰的边界,并采用轻量级的通信机制,微服务的划分可以从以下几点展开思考
    • 首先是现有架构间的依赖关系
    • 其实是业务的可扩展性
    • 再次是团队目前的人员能力
    • 最后则是实现过程中可能遇到的风险与挑战
      这些划分的依据往往也是我们在DDD中对上线文和子域进行划分时需要考虑的问题
  7. 云原生

战术建模工具

实体

一个实体模型就是一个独立的事物,每个实体都拥有一个唯一的标识符,将实体与其他建模工具区分开的主要因素是他的唯一性-即他的个体性

值对象

一个值对象,是对一个不变的概念整体所建立的模型,和实体不一样,它没有唯一标识符,而是由值类型封装的属性对比来决定相等性,此外,一个值对象不是事物,而是常常用来描述,量化或者测量一个实体

聚合

聚合由一个或者多个实体或者多个值对象组成,其中一个实体被称为聚合根,每个聚合都会形成保证事务一致性的边界,其控制的业务规则必须保证原子性,一致性
贫血模型
贫血模型是指使用的领域模型只包含共有访问器(Getter&Setter),没有包含任何真正的业务逻辑行为的模型

  • 在我们经常使用的ORM框架中,会将RDS的查询和结果直接映射为对象(大部分情况下会被称为“实体”),这些对象只包含Getter&Setter,而真正的业务逻辑被放在称为服务的对象里,本来应该和这些实体有着内聚的业务逻辑完全被置于独立的服务中,最终导致服务越来越臃肿的同时,把这些ORM映射的对象变成了贫血模型
  • 领域模型应该有持久化的对象转换而来,并承担被错放在服务中的那些业务逻辑

领域事件

在领域事件的运用中,我们可能会用到事件溯源(Event Sourcing),即经常对领域对象基于持久化的领域事件重建,为了性能考虑,快照是事件溯源必须要支持的一种机制,减少事件溯源的长度和深度