竹笋

首页 » 问答 » 灌水 » 肝了一个月的DDD,一文带你掌握
TUhjnbcbe - 2023/4/13 20:47:00

整体阅读时间,在0分钟左右。

为了证明该文没有注水,列一下当时的学习资料:

小米内部DDD系列分享;小米内部DDD脚手架;小米内部授权认证项目(应用DDD);极客时间欧创新的《DDD实战课》;掘金“柏炎”的DDD系列文档和DDDDmo;美团技术团队、阿里云开发社区、网上博客等。

直接上思维导图!

1.走进DDD

1.1为什么要用DDD?

面向对象设计,数据行为绑定,告别贫血模型;降低复杂度,分而治之;优先考虑领域模型,而不是切割数据和行为;准确传达业务规则,业务优先;代码即设计;它通过边界划分将复杂业务领域简单化,帮我们设计出清晰的领域和应用边界,可以很容易地实现业务和技术统一的架构演进;领域知识共享,提升协助效率;增加可维护性和可读性,延长软件生命周期;中台化的基石。

1.2DDD作用

说到DDD,绕不开MVC,在MVC三层架构中,我们进行功能开发的之前,拿到需求,解读需求。往往最先做的一步就是先设计表结构,在逐层设计上层dao,srvic,controllr。对于产品或者用户的需求都做了一层自我理解的转化。

用户需求在被提出之后经过这么多层的转化后,特别是研发需求在数据库结构这一层转化后,将业务以主观臆断行为进行了转化。一旦业务边界划分模糊,考虑不全,大量的逻辑补充堆积到了代码层实现,变得越来越难维护。

假如我们现在要做一个电商订单下单的需求,涉及到用户选定商品,下订单、支付订单、对用户下单时的订单发货:

MVC架构:我们常见的做法是在分析好业务需求之后,就开始设计表结构了,订单表,支付表,商品表等等。然后编写业务逻辑。这是第一个版本的需求,功能迭代饿了,订单支付后我可以取消,下单的商品我们退换货,是不是又需要进行加表,紧跟着对于的实现逻辑也进行修改。功能不断迭代,代码就不断的层层往上叠。DDD架构:我们先进行划分业务边界。这里面核心是订单。那么订单就是这个业务领域里面的聚合逻辑体现。支付,商品信息,地址等等都是围绕着订单实体。订单本身的属性决定之后,类似于地址只是一个属性的体现。当你将订单的领域模型构建好之后,后续的逻辑边界与仓储设计也就随之而来了。

DDD整体作用总结如下:

消除信息不对称;常规MVC三层架构中自底向上的设计方式做一个反转,以业务为主导,自顶向下的进行业务领域划分;将大的业务需求进行拆分,分而治之。

2.DDD架构

2.1DDD分层架构

严格分层架构:某层只能与直接位于的下层发生耦合。

松散分层架构:允许上层与任意下层发生耦合。

在领域驱动设计(DDD)中采用的是松散分层架构,层间关系不那么严格。每层都可能使用它下面所有层的服务,而不仅仅是下一层的服务。每层都可能是半透明的,这意味着有些服务只对上一层可见,而有些服务对上面的所有层都可见。

分层的作用,从上往下:

用户交互层:wb请求,rpc请求,mq消息等外部输入均被视为外部输入的请求,可能修改到内部的业务数据。业务应用层:与MVC中的srvic不同的不是,srvic中存储着大量业务逻辑。但在应用服务的实现中,它负责编排、转发、校验等。领域层:或称为模型层,系统的核心,负责表达业务概念,业务状态信息以及业务规则。即包含了该领域所有复杂的业务知识抽象和规则定义。该层主要精力要放在领域对象分析上,可以从实体,值对象,聚合(聚合根),领域服务,领域事件,仓储,工厂等方面入手。基础设施层:主要有2方面内容,一是为领域模型提供持久化机制,当软件需要持久化能力时候才需要进行规划;一是对其他层提供通用的技术支持能力,如消息通信,通用工具,配置等的实现。

在设计和开发时,不要将本该放在领域层的业务逻辑放到应用层中实现,因为庞大的应用层会使领域模型失焦,时间一长你的服务就会演化为传统的三层架构,业务逻辑会变得混乱。

2.2各层数据转换

每一层都有自己特定的数据,可以做如下区分:

VO(ViwObjct):视图对象,主要对应界面显示的数据对象。对于一个WEB页面,或者SWT、SWING的一个界面,用一个VO对象对应整个界面的值。DTO(DataTransfrObjct):数据传输对象,主要用于远程调用等需要大量传输对象的地方。比如我们一张表有个字段,那么对应的PO就有个属性。但是我们界面上只要显示10个字段,客户端用WEBsrvic来获取数据,没有必要把整个PO对象传递到客户端,这时我们就可以用只有这10个属性的DTO来传递结果到客户端,这样也不会暴露服务端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO。在这里,我泛指用于展示层与服务层之间的数据传输对象。DO(DomainObjct):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。PO(PrsistntObjct):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。最形象的理解就是一个PO就是数据库中的一条记录,好处是可以把一条记录作为一个对象处理,可以方便的转为其它对象。

.DDD基础

学习DDD前,有很多基础概念需要掌握,这幅图总结的很全,他把DDD划分不同的层级:

最里层是值、属性、唯一标识等,这个是最基本的数据单位,但不能直接使用。然后是实体,这个把基础的数据进行封装,可以直接使用,在代码中就是封装好的一个个实体对象。之后就是领域层,它按照业务划分为不同的领域,比如订单领域、商品领域、支付领域等。最后是应用服务,它对业务逻辑进行编排,也可以理解为业务层。

.1领域和子域

在研究和解决业务问题时,DDD会按照一定的规则将业务领域进行细分,当领域细分到一定的程度后,DDD会将问题范围限定在特定的边界内,在这个边界内建立领域模型,进而用代码实现该领域模型,解决相应的业务问题。简言之,DDD的领域就是这个边界内要解决的业务问题域。

领域可以进一步划分为子领域。我们把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。

领域的核心思想就是将问题域逐级细分,来降低业务理解和系统实现的复杂度。通过领域细分,逐步缩小服务需要解决的问题域,构建合适的领域模型。

举个简单的例子,对于保险领域,我们可以把保险细分为承保、收付、再保以及理赔等子域,而承保子域还可以继续细分为投保、保全(寿险)、批改(财险)等子子域。

.2核心域、通用域和支撑域

子域可以根据重要程度和功能属性划分为如下:

核心域:决定产品和公司核心竞争力的子域,它是业务成功的主要因素和公司的核心竞争力。通用域:没有太多个性化的诉求,同时被多个子域使用的通用功能的子域。支撑域:但既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域。

核心域、支撑域和通用域的主要目标:通过领域划分,区分不同子域在公司内的不同功能属性和重要性,从而公司可对不同子域采取不同的资源投入和建设策略,其

1
查看完整版本: 肝了一个月的DDD,一文带你掌握