大白话之辩论DDD,阿里面试中台化理解

·  阅读 9885
大白话之辩论DDD,阿里面试中台化理解

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

前言

我在最近一年经常听到大家在讨论DDD,而且议论纷纷,大家各抒己见。

比如说在某技术微信群讨论,有些人说DDD是噱头,为了搞个业绩(又不是不能跑 😉),还有些表示自己是CRUD Boy 不知道DDD是什么高大上东西。

接下来我用大白话来表达我对DDD的看法。

现状

  1. 当我们去看招聘网站的时候,会发现有些要求要会领域设计理念。还有些要求会SOA面向服务设计

  2. 在业务发展到一定体量,业务越来越复杂的时候,我们会发现很多的重复劳动,代码堆得像🚯一样,然后大家还在不断往里面丢代码(PS:这样对代码的可扩展性和维护带来很大的麻烦)

  3. 曾经一位小伙伴实现了更新某实体,然后记录操作日志的功能,由于很多方法都会更新到这个实体,他在每个方法里面都去记录修改的日志。这就埋下隐患 (⚠️ 你怎么保证别人在其他方法修改实体的时候,也能记录到操作日志呢,也就是太分散)

  4. 曾经面阿里国际化事业部的时候,被问了问题:你理解的中台化是什么?

大白话辩论

领域设计的作用

Q:针对第一点,不用领域设计行不行?

A:可以不用领域设计,在项目前期的时候,为了将业务快速跑起来,产生价值,这时是顾不上设计的合理性。而且当项目没有到一定的体量,是无法预知到未来会遇到什么变更。当然如果该系统一开始预估的体量就很大,在前期就需要严格去设计好整个架构。


Q:那什么时候需要用上呢?

A: 回到现状第二点,当业务发展到一定体量,业务复杂程度到达一定量的时候,需要用到领域设计来进行改造。这个时候你会发现,大量的代码重复copy,扩展性很差,每次新增需求的时候,都要不断重新开发,这时需要进行领域改造。


Q:第三点导致的原因是什么,怎么解决?

A:本质问题就是,每个方法都会影响到这个实体的更新,导致影响面很大,无法收集到一个点。我们的解决方法就是,将这些更新的地方,全部收集到一个方法里面,然后其他方法只是去调用该变更方法。这样实现日志记录,我只需要去监控一个方法即可!

DDD 精髓

还是大白话讲,就是高内聚,低耦合

PS :我见过很多人上来就是一堆理论,当然理论熟悉也是好事,这样执行起来有条理。

但是🤔 很多知识学到最后就是思想、逻辑、本质,其他都是它幻化出来的东西。这是比较玄学的,顺便讲下我的想法:虚的东西其实是在指引大的方向,比如说企业的愿景,你说它能给业务起作用吗?没有。它是为了给所有行动起到方向的意义。实的东西是为了落地,在落地的时候,又不是用虚的,这样就无法实施。

从实质去讲讲DDD


  • 高内聚,低耦合

Q:为什么需要高内聚,低耦合呢?

我们可以看现状的第三点,其实就是他的变更方法扩散开来了,这样导致很多地方可以去修改方法。所以我们需要去将这些方法抽取到一个方法,这就是高内聚,我一个领域里面,它有什么功能,有什么属性,然后外界是没有这个领域有的功能

Q:低耦合又是啥?

举个常见的例子,A逻辑之后->B逻辑,那么问题来了,哪天我不用B逻辑,我要换C逻辑,但是B跟C我可以根据情况来切换。

有些大聪明站起来说:可以用策略模式。没错,但是它的本质是什么,就是低耦合。A是不知道B,也不知道C的具体实现,它只知道接口,具体它怎么实现,由适配器,什么规则去注入对应的实现类。

Q:既然低耦合的好处是什么?

为了可扩展性,当某天我不用某个中间件,而采用其他中间件,其实我只需要写另一个适配器就解决这个问题。如果代码跟其他中间件强耦合,那GG,你得去改写之前代码,随着中间件越来越多,代码的可读性也会越来越差。


  • 我理解的中台化是什么?

🎄 中台化,SOA面向服务架构,其实都是一个思想,分而治之。一个服务里面,会有这个业务领域对应的相关操作,有对应领域模型,领域对象,值对象,上下文,然后对外提供服务,这体现高内聚,把对应的功能点收拢到一个服务里头进行管理。

🎃 中台概念里头,有个大前台,领域概念里头有个应用层。它作用是干嘛的?是做编排。就是我每个服务都有对应的功能,那么一个业务下来肯定会有很多不同服务来提供功能,需要一个地方来对他们进行编排。

Q:大前台的作用是什么?

在单体服务里头,我们通常写在service里面,像现状第三点,每个方法或者每个服务都有编排任务**,这样的话就有可能每个服务都会有重复的代码以及相似功能**,其实我们需要去抽象出来,变成一个单独的服务,这就是大前台


从理论上讲讲DDD


概念

  1. 领域:领域是相对于业务领域,或者问题域,范围概念。一个领域会包含多个子域,比如说订单域,会有商品、订单等等子域
  2. 限界上下文:既然有范围,那么就有边界,领域之间靠context上下文来进行通讯
  3. 实体、值对象:实体对应PO,值对象,在实体基础上会加上其他属性
  4. 聚合,聚合根:对实体、值对象会进行聚合,聚合根,可以通过这个访问内部实体的东西,不会直接操作跟内部实体
  5. 防腐层 ACL:限界上下文处理外界上下文的时候,需要做业务处理

贫血模型 里面只有属性,但是它的校验、属于它方法放在外面。违反单一原则,封装性比较差的

充血模型 里面包括属性,以及对应的方法实现。这样的好处,开闭原则,以后扩展的话在类里头新增方法。放在外面去做的话,其实是修改,应该减少修改的情况


Domain Primitive

在很多业务中,我们面向过程,比如说一个方法(String,String) 参数,他就会有前后顺序,分别代表什么 如果我们把它封装成对象的话,可以减少这样的问题。

原则

  1. 隐形概念显式化 ,比如说聚合根,对于一个东西,它有唯一的标识。如果是前者的话,可以是name,phone等等做标识
  2. 隐式上下文显式化
  3. 封装多对象

这就是为什么有很多值对象,聚合根,entity,其实是为了封装对应类,以及相关的方法,符合开闭原则

DDD分层

在这里插入图片描述

经典分层


接口层、应用层、领域层、基础层

接口层:面向接口,controller

Application 属于编排,就是其他层都封装各自小单元类,他们执行的顺序由应用层来处理

应用层:面向用例,就是会管理各个领域的调用关系,比如说校验完->A领域->B领域

领域层:有领域服务,以及对应子域。处理该领域的业务逻辑

基础层:处理数据库、缓存、第三方等等

在这里插入图片描述

六边形架构


概念上就是以适配器,来达到低耦合的效果,外界通过适配器访问内部接口,向内进行依赖

Q:向内依赖是什么?

越到底层,耦合越高,是我具体实现哪里,比如说我用到什么中间件,这里耦合是最高的。越到外面,就变成抽象接口,适配器,供外部去调用。


依赖倒置分层


基础设施层都是接口,而domain去实现对应接口功能。这样依赖的方向是向外,我用什么中间件,由domian层去解决注入什么类型。

Q:这样设计的好处是什么?

我们很多框架都强依赖第三方框架,比如说mybatis、mq等等中间件 那么它有什么坏处呢?就是当我换其他组件的时候,会改很多东西

domain层设计成接口的好处,就是具体实现不会强依赖其他组件,随时可以另外实现

domain包含内容描述
Repositity映射mapper以及扩展,避免强依赖底层
ACL防腐层,处理跟外部不一样的东西,比如说协议、api、缓存

按照个人见解画的分层图


在这里插入图片描述

总结

DDD目的是为了高内聚,低耦合。它通过业务领域的划分,然后在领域里面实现对应的功能,实现高内聚。然后通过适配器,依赖倒置,实现低耦合。

在业务体量到达一定程度,还有业务复杂度比较高的项目,是有比较好的扩展性

DDD的怎么实践?

觉得有帮助的,请关注下博主,感谢~🧧🧧🧧

分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改