Domain Driven Design 领域驱动设计

Domain Driven Design 领域驱动设计 — DDD

前言

在阅读的很多资料中,DDD有很多概念:领域、子域、核心域、通用域、支持域、实体、领域服务、聚合、聚合根、工厂、仓库、领域边界 … …

众多的概念令人眼花缭乱,直接去理解这些概念是一件很麻烦的事情。所以,让我们先梳理一下DDD的脉络,再去理解这些细节。

软件设计的最终目的是什么?

其实软件设计的最终目的是为了提高代码的复用,想用实现复用,那么首先就需要封装变化

DDD到底是什么?

DDD是Eric Evans在2003年出版的《领域驱动设计:软件核心复杂性应对之道》(Domain-Driven Design: Tackling Complexity in the Heart of Software)一书中提出的具有划时代意义的重要概念:
领域驱动设计是指通过统一语言、业务抽象、领域划分和领域建模等一系列手段来控制软件复制度的方法论

简单的说,DDD是为了解决快速变化的复杂系统的设计问题的一种设计思想

DDD解决的问题?

DDD是杜绝软件退化的利器

  • 软件退化的根源:

    • 最初只能将简单、清晰、易于理解的业务逻辑做到软件中
    • 还有许多不简单、不明了、不易理解的业务逻辑没做到软件中
    • 也就是说,软件退化,是软件业务由简单向复杂转变的必然结果
  • 运用DDD,当系统业务变得越来越复杂时,将业务的理解绘制成领域模型,可以正确的指导软件开发。

  • 组织微服务的钥匙:

    • 微服务不是"银弹",也有很多的“坑”
    • Martin Flower在定义微服务时提到“小而专”,很多人get到了“小”,而忽略了“专”。微服务内高内聚,微服务间低耦合。
    • 转型微服务的根源,其实是系统规模越来越大,维护越来越困难,才需要拆分“微服务”,而微服务直接的组织的钥匙,便是DDD。
  • 要让DDD在团队中用的好,需要一个支持DDD与微服务的技术中台

Domain Driven Design 领域驱动设计_第1张图片

实例对比

伪代码实现

我们先来看一段伪代码,业务便是简单的学生选课

下面是一段常用的MVC的实现,下午称为代码1

Domain Driven Design 领域驱动设计_第2张图片
Domain Driven Design 领域驱动设计_第3张图片

在这段代码中,student实体是一种贫血模型,那么什么又是贫血模型呢,之后我们会和充血模型进行对比说明。


看明白MVC的实现之后,我们再来看另一种实现,下文称为代码2:

Domain Driven Design 领域驱动设计_第4张图片
这这段实现中,抽象出来的checkService,会应对业务的变化,做出相应的改变,我们称之为防腐层

抽象出MQ基础设施层,防止第三方组件的变化(可能是rabbitmq,可能是kafka,可能是rocketmq等等)

贫血模型VS充血模型

在代码对比之前,我们先要搞明白贫血模型与充血模型的区别。

  • 贫血模型: 代码1中,在常用的MVC模式下,student采用贫血模型,之后提供属性与相关的set/get方法,这类对象会被各种Service所调用,从而分布在不同的业务中。如此下来,你还敢随便改student信息么?除非你读懂每个Service的调用过程。

  • 充血模型: 如果改为充血模型,student类中可以加入run()、upGrade()等等和自身业务相关的业务逻辑。这类对象,也就可以理解为域(Domain)
    对于域的封装,每个域不要受其他域的影响,每个域操作自己的变化。而跨域的变化,通过领域服务搞定,由领域服务调用域的方法来完成状态的变化。
    我们来举个例子:student与teacher两个对象,teacher类的提问()需要调用student类的回答(),而想这样的域与域之间的联系(调用),我们可以将它写到一个Service中,而这个Service,就可以称作领域服务


防腐层

防腐层:隔离变化

代码2中,checkService做业务检验,也不不变,代码不变;当业务发生变化,也只有checkService内的代码发送变化。代码2中的代码还是不会发生变化。


对比

  • 业务逻辑清晰度:代码2业务人员也可以大体读懂
  • 业务稳定性: 代码2业务不动,代码不动
  • 防腐层隔离变化
  • 各领域内自治,可以自我发展
  • 用仓库StudentRepository来管理Student的存储
  • 仓库中集成工厂Factory/Builder应对复杂对象的组装
  • MVC保证了实现最差也差不到哪去(但基本总是最差),DDD如果做的差,会比MVC还要差,如果做的好,的确可以应对业务变化(了解业务,预测业务变化)

两个问题

1、充血模型和充血模型怎么做交互?

跨域的变化,通过领域服务搞定,由领域服务调用域的方法来完成状态的变化。

2、怎么和数据库做交互?

用仓库StudentRepository来管理Student的存储

你可能感兴趣的:(基础知识,系统架构)