DMVP 问答总结 实战步骤?依赖导致?防腐?

本周知识星球主要发布了两篇文章:

《领域模型的图文表示法》

《对号入座法之领域服务》

两篇文章都是描述如何基于通用语言进行领域建模的,干货满满,建议小伙伴们按照星球中的公寓租房的案例,自己动手试一试哈。

历史文章目录:http://wenhe.online/?p=2043

DMVP 2.0 也开发好了,马上就要发布了,已经在测试阶段了,修复了诺干 bug 和优化,和现在的版本相比较,更加提升了业务开发的效率。

本周问答:

问:DDD 落地的具体思路?

答:和星友聊的过程中,发现此星友懂很多 DDD 理论,属于说和看 DDD 理论都懂的阶段,目前就缺实战落地了,我把自己快速落地的思路写一下,可能不是很全,我们画一张图:


 

图片有点长,看不清楚的,可以去 git 上面下载原图。

对于这个图,有两个比较集中的问题:

问:DDD 落地,第一步为什么不是去确认上下文边界,而是去需求中抓取通用语言?

答:几个方面考虑哈

1:这是一个认知的过程,我们认知事物,一般来说都是先了解这个事物是什么,才能确定这个事物和其他事物有什么不同。同理,从需求中提取通用语言的过程,就是认知业务是什么,能干什么的过程,而辨明业务的上下文边界,是需要基于认知业务的基础之上才行的哈。

2:落地难,如果你业务是什么都没有想清楚,又是如何想清楚业务之间的边界的呢?我们尝试过先去弄业务的上下文边界,很难很难,时间过了很久,业务的上下文都没有想清楚,项目就延期了。我们工作中,常常遇到工作几年的同事说,我终于把这个业务想清楚了,这个很常见,很普遍,通用语言、领域模型、业务上下文,都是通过迭代才慢慢想清楚的,并不是项目初期就一下子全部搞定,很难,只能说我们尽量的去想全。(这个思路仅限于一般的大中型互联网项目,不适合公司战略方向的业务框架项目)

3:会限制你的思路,如果一开始你就把通用语言的上下文定死,那么你设计的系统可能就只会满足当前上下文,我们建议先多想想通用语言的各种场景,可能你会想到通用语言的场景十多条,而当前业务只取其中一种场景,那么我们也仅仅落地这种场景,但你多想出来的 9 条对你的系统设计绝对是有好处的。

所以 DDD 战略设计,还是先请从需求中抓取通用语言开始吧!

问:实践中有那些注意事项呢?

答:保持质量和速度共存很重要,首先自己可以私下练练手,先从公司一个小需求战略设计开始,再到小型项目战术设计,再到中大型项目战略和战术落地,如果自己还处于不是很熟练的时候,直接在一个大中型项目中去落地,会很吃力,没做好的话,也会影响自己后续推广和落地 DDD,在公司落地 DDD,第一炮很关键,所以先选择一个小需求吧,肯定不会失手。

问:domain 层不是应该去调用 SPI 层么,接口的入参是不是应该由 SPI 层去定义,现在都是 SPI 去关注 domain 层的接口,这种实现对于 SPI 层是不是不太友好?

答:这个问题就是我们常说的依赖倒置,我们先从原理上解析下,再简单代码 mock 下。

我理解依赖倒置的好处只有一个,通过维护好 domain 层和下游的依赖关系,保证了 domain 层的高内聚低耦合,我们画个图释义一下:


 

对于这个图,延伸出两个问题:

问:SPI 层依赖 Domain 层的接口,理论上 SPI 的改动对 Domain 层没有影响,实际上 SPI 层的实现出了 bug,还是会影响到 Domain 层?

答:哈哈,这个其实和 DDD 关系不大了,A 调用 B, B 由于 bug 导致服务不可用,从而导致 A 服务不可用,这是一个技术调用问题哈。我们刚才说的高内聚低耦合系统,是从业务的角度上来说的哈。当然这种问题我们也应该重视的,可以通过一些技术手段来发现和解决这些问题,比如说定时检测下游接口是否正常,下游某种实现不正常时,能否自动切流到另外备用实现等等。

问:Domain 层不依赖 SPI 层,那么该如何实现调用?

答:分两种情况,第一种 Domain 层和 SPI 层都在同一个 Spring bean 容器里面,通过 Spring 的 IOC 机制就可以找到,代码如下:


 

第二种情况,业务越来越复杂,团队越来越大的时候,SPI 层可能会拆分成一个单独的系统,由专门的团队维护,这时候调用需要通过 rpc 的方式调用了,代码我们就不贴了,我们在后面的章节也会说到 SPI 层的系统和团队拆分。

问:DDD 里面的防腐层是什么意思?代码里面如何体现?

答:防腐的意思,可以从两个角度来说,自我保护和开放。

自我保护其实很简单,就是我向别的领域要东西的时候,我不会直接耦合别的领域的业务知识,我会在中间做一层转化。

对于 Domain 来说,主要体现在和 app 层、SPI 层或基础设施层交互上。

比如我们刚说的 Domain 层调用 SPI 层,我们会在 Domain

层定义一个接口,接口的入参和出参都是我自己定义的, SPI 层往里面填充就好了。

比如说 app 层调用 Domain 层,接口也是 Domain 层定义的,这个接口也是用来防腐的。

app 层也是有自己的防腐的,我们会在 api 层定义一些接口,这些接口主要是为了远程 rpc 调用,app 层的防腐就是这些接口,比如说订单中的结算,你可能自己开放了结算标准的 dubbo 接口,但别人可能不用,别人要求结算去监听他的消息,那这时候就要做一层防腐,你需要把消息数据转化成和结算标准服务那种入参数据,这其实是一种协议和入参的转化,我们一般放到 controller 层去做,这时候 controller 层就是 app 层的防腐层。

contorller 层和 spi 层,一个是上游的入口,一个是下游的出口,对于自身来言是没有防腐的,但它们的存在就是为了给领域自身做防腐。

这两层在提供本身标准服务的同时,又会去不断的适配其他领域,是频繁改动的两层,但又没啥业务,基本都是协议和数据的转化适配。

开放也是很有意思的话题,就是我的领域应该如何向外面展示我自己?

这主要分两种情况,对内(公司内部的服务)和对外(公司外部的服务):

如果是对内的话,建议你把自己的领域完全开放,这样最省事,因为对内的需求变化还是很多的,不同业务方需要的内容不太一样,你把自己的领域完全开发出去,业务方需要什么自己去取就好了。

如果是对外的话,就需要保守一点,就是需要防腐一点,只开放当前需求需要的字段就好了,千万不能把整个领域都开放出去。

防腐是一种设计思想,DMVP 代码里面很多地方都体现了出来,有可能是几行代码,有可能是一个接口,也可能整个模块都是用来防腐,代码就不贴了,实在太多了。

问:知识星球的文章看到那章的时候,我自己可以尝试去落地?

答:真心不需要看知识星球的文章,建议你先来个 hello world 式的学习,在搞清楚领域元素的基本概念后,参考星球内公寓租房的案例,尝试自己走一遍通用语言和领域模型(和我们画的做比较),尝试在页面录入领域模型,把下载的代码拿下来研究研究,先走一个 hello world,对整个流程有个直观的接触非常重要,然后再来看看我们的文章或者 《领域驱动设计:软件核心复杂性应对之道》一遍一下,基本上可以尝试自己落地一个小需求看看。

学习 DDD 关键在于锻炼,而不是看,这是很重要的实践总结,也是很多人迈不出的坎,很多朋友的理由就是我还没有准备好,实践 DDD 永远都没有准备好的时候哈,完全可以边实践边学习,加入星球的小伙伴更加不用担心,有实践经验可以参考落地会更快。

等你用 DDD 做了几个或者十几个项目,那时候你会发现落地 DDD 会和落地 SpringMVC一样简单。

加入知识星球,和大家一起,从 0 到 1 用 DDD 搭建系统吧。


 

关注微信公众号,不错过每周知识星球问答总结!


 

猜你喜欢

转载自www.cnblogs.com/wen-he/p/10984201.html