Redian新闻
>
DDD 落地难?这三个迭代让你从入门到进阶 | 极客时间

DDD 落地难?这三个迭代让你从入门到进阶 | 极客时间

公众号新闻

大家好,我是钟敬。我是一名在 IT 界奋斗了二十多年的老兵。

目前在 Thoughtworks 公司担任首席咨询师,也是数字化转型与运营团队的 DDD 负责人。平时的工作主要是给客户提供软件开发方法学、架构治理、研发效能提升等方面的帮助。

说到 DDD 不少朋友都会吐槽 DDD 落地太难了,主要源于领域建模不好掌握、不好实现、概念混乱、以及理念和方法进化发展问题而导致的。

其实,DDD 的学习只要掌握了方法和规律,并非那么困难。以下就是我梳理的「DDD 学习」知识地图:

这张图出自于我在极客时间的《手把手教你落地 DDD》专栏里,这门课程适合对 DDD 感兴趣的初级和中级开发人员,尤其是已经学习过 DDD 的一些基础知识,但仍然觉得有些概念不太清楚,或落地有困难的伙伴。

正好,最近有 11.11 特惠,到手只要 6 折,推荐给需要的同学。

专栏即将迎来上线一周年的重要时刻,目前已有近 2 万人参与学习,共同分享了他们的学习心得。我们也可以从别人的学习方法中寻找适合自己的方式。下面是一篇来自 Fredo 同学的学习心得,让我们一起学习借鉴,探索更高效的学习方法。

Fredo 学习心得正文:

你好,我是东(在极客时间的 ID 是 Fredo)。大学的时候我读的是计算机专业,现在是一名工作了近 3 年的程序员,很高兴能和你分享我的学习体会。

我是怎样学习课程的?

首先聊聊我是怎么学习这门课的。

DDD 是一个很老的概念,但在我身边的技术圈,这仍然是个常常被提起的词。不过很多人在谈论这个概念,但很少有人说清楚,并给出详细具体的实践指导。

我就是抱着试试的心态,想看看作者到底是要怎么“手把手”教我 DDD 。我急迫地寻找课程里一些 DDD 的概念名词,试图验证一下作者讲的和我之前理解的是不是一回事,稍后我再专门说说对我启发最大的几点。

课程案例以迭代的形式展开,我试着投入其中,想象自己是敏捷团队中的一员,正在参与这个迭代。

迭代一按照“捕获需求、建立领域模型、模型实现”的顺序串了一遍,这大概还是一个三段论的模式,即发现问题(收集需求)、分析问题(建立模型)、解决问题(编码实现)。

由于我之前有一些 UML 的基础,课程里的分析图看起来没有多大障碍。每看完一节课,我都会将其中涉及的 DDD 中的术语记录在导图中。同时,跟随老师的分析,我结合自己的理解,提炼了一些重要的区分点和有助于回忆内容的关键词,把它们体现在了导图里。

第二遍阅读课程(正在进行中),我的关注点主要放在了 DDD 代码实现层面,主要会对比迭代中的代码,与我当前的项目结构以及代码组织方式有什么异同。

之后,我打算再跟着迭代案例分析过程,将其中的领域模型图再好好画一遍,进一步体会“领域模型与业务需求一致,系统实现与领域模型一致”的原则。

我从课里学到了什么

课程里有很多值得反复咀嚼的内容,这里我就抛砖引玉,分享一些印象最深刻的点。

编程范式的选择不是非黑即白

印象里在上大学的时候,我曾经在一门系统分析与设计类的课程,趁着课间,跑上讲台跟老师问过这样一个问题:“面向对象强调对象的属性与行为在一起,而我现在的编程方式自然地将逻辑都放在 Service 里面了。虽然使用的是面向对象的编程语言,但感觉自己还是在用面向过程的思路,该怎么办呢?”。

老师的回答已淡出了记忆,然而这个问题始终萦绕心头。不排除是大一的时候就学了 C 语言的缘故,过于习惯面向过程的处理方式。

后来工作了,编程范式上的“纠结”还是困扰着我。[第10节课](https://time.geekbang.org/column/article/617473)《要“贫血”模型还是要“充血”》讲的就是这个问题,编程范式在一个发展的过程中,开发者的认知也在成长,编程范式的选择不是一个非黑即白的问题,需要我们根据所开发的软件、编程语言、团队编程习惯等去找到一个平衡点。

模块划分方法

在第 11 节课《怎么创建领域对象、实现领域逻辑》中,老师提到了一种指导模块划分的方法——打横(分层)与打竖(耦合关系)。

打横是站在按性质的角度对代码进行分层,如适配器层、应用服务层、领域服务层、基础 Common 层。

打竖是按耦合性,我们可以在已经分层的包下,再根据耦合关系来分包。按我之前的分包方式,通常是按照代码的性质分包的,也就是仅仅做了打横这一步。

对比之后不难发现,按打横与打竖的分包方式,后面的包结构在各层下面会更加细粒度。虽然包结构变多了,但是 Domain 层的各聚合内,代码显得更加紧凑、高内聚。

以聚合为单位进行持久化

我之前对仓库的认知是一个数据库表对应一个 DAO,就算有单独拎出一个 Repository,也仅仅做了对 DAO 的一个委派,然后在业务代码层面将数据取出来处理。

而第 16 节课《怎么实现不变规则》中讲到,Repository 是针对整个聚合的,而不是从数据库表的角度。

这个说法打破了我的惯性认识,现在想起来仍然记忆犹新。我原先的想法缺乏领域意识,将应用服务和领域逻辑混杂在了一起,变成了基于 CRUD 的面向过程编程。

而一个 Repository 负责一个聚合的持久化,聚合内部紧密相关的对象生命周期就得到了统一管理。如果我们需要测试领域服务,只需要 mock 聚合对应的仓库即可,这有利于我们对领域服务代码的测试。

值对象和实体的本质区别

值对象和实体虽然是 DDD 里“人尽皆知”的知识点了,但想要说清楚两者的本质区别还是有难度的。

第 20 节课里,从认识论的角度去讲解,让我觉得很新颖。

这两者的区分,有一个有趣的方式可供参考判断,我们可以向自己提问:存在 F 的属性 / 属性值可以改变吗,如果属性 / 属性值改变了,存在 F 还是存在 F 吗?

如果得到的答案是“是”,则 F 为实体,否则就是值对象。

还有一些需要注意的点,需要根据上下文结合判断(这也是 DDD 原书中提到的),比如在邮政软件或地图软件中重新划分了行政区域,那么所有使用邮政软件或地图软件的地址都将改变,这个上下文里面,地址就是**实体**。而对于某个用户的购物软件中的收件地址,仅表示这个用户实体的收件地址,这里就应该当成**值对象**来处理。

我还尝试用数学语言和图解描述了一下(可能不准确,欢迎批评指正)。

泛化的表设计策略

软件架构或设计里经常需要我们做取舍,没有唯一的答案,具体问题具体分析,权衡利弊之后,才能得到当前问题域下的一个相对最优解。这种不确定性很有意思,同时也很有挑战。

就拿泛化的数据库表设计来说,我之前的常用做法是整个泛化体系一张表。可能我碰到的大多数情况,子类没有太多的不同属性,即便有几个字段的空间浪费,也可以接受。

而第 25 节课里,不但提到了泛化的三种数据库表设计策略。更重要的是给了我一个指导方针,在空间效率、时间效率、系统的可维护性这些维度去考量。相比原先凭直觉行事,知其所以然的衡量判断,才更有可能在设计上给出有说服力的方案。

品读经典与刻意练习

工作之后,我们常常被一些糟糕的代码“折磨”,但心中仍追求着整洁代码、优雅的分析设计,希望实现“良质”的软件开发(“良质”这个词来自《禅与摩托车维修艺术》这本书,你有兴趣的话可以去翻一下)。

在我看来,计算机领域里,“良质”和软件大师们探索、归纳出的分析方法、原则、模式是异曲同工的。沿着他们的思路,配合自己的实践,我们才更有可能实现一个具备“良质”的软件系统。

而想要了解这些经验模式,很重要的一个途径就是阅读经典、学习原著。老师经常在课程中指出知识点在 DDD 原书中的出处,正好我旁边也放着两本书《领域驱动设计》和《实现领域驱动设计》,可以随时看一下对应的章节。

课程里还特意用两节选学的内容介绍了相关的经典书籍,让我燃起了重读经典的兴趣,算是意外惊喜。

之前我曾细读了《实现领域驱动设计》,可惜因畏难情绪而将原书《领域驱动设计》放置一旁,《分析模式》更是从未问津。老师有个“经”与“传”的提法,将原书比作“经”,一手资料的知识密度及重要性可见一斑。

我尝试了在课程学习过程中去阅读一些相关图书,感觉对巩固知识很有帮助。在迭代一第 12 节课中,老师的案例用到了不少重构手法,我们可以在《重构》原书中找到对应的章节。

比方说有两个技能点,我现在已经有意识地用在了日常工作里,分别是提高封装性的“表意接口”,还有发现和消除“特性依恋”。你可以在《重构》的 3.9 节找到它们,这两招能让我们的代码更加 OO done right (把面向对象做对)。

通过命名表达意图将函数写短的方法也很实用,如果命名已经清晰地说明了一切,就没有注释的必要(《重构》3.24 节)。

另外,再补充一个我在实际开发时发现的问题,也和封装性有关。项目开发中很多小伙伴喜欢用的 lombok 插件,虽然能够为我们节约一些时间,但不假思索地使用 @Data 注解会破坏封装性,需要收敛着用

经典仰之弥高,课程里的迭代案例亦循循善诱。在阅读经典的过程中,我时常会惊讶于我所遇到的问题,前人早已就碰到了,并且分析问题直捣本质,给人以启发。

不过,软件工程没有银弹,这些经典提供了各式各样的思路和方案,能培养我们对“好”的认识。但想要把高手的心法招式化为己用,还离不开刻意练习。

就像王小波说的那样,“生活就是个缓慢受锤的过程”,编程技艺的学习旅程也是同样的体验。希望我们面对各种锤炼仍然能生猛下去,热爱雕琢技艺,也热爱滚烫生活。

点击「阅读原文」,跟我一起加入 DDD 的学习吧。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
Power BI实战宝典:从入门到精通的全程指南极客时间 VIP 重磅升级|买即赠左耳朵耗子《程序员练级攻略》新书懂点 React Hooks,就这么香?| 极客时间仅剩3席|九大行IBD高级经理亲自授课投行进阶课程,三周带你从0到1逆袭,决战投行Offer!心理咨询师从入门到精通,都需要经历什么?| 培养计划早鸟价进行中累死累活干不过写 PPT 的?你不知道 PPT 到底多难写 | 极客时间离开阿里 4 个月,曾经的“阿里守护神“去哪儿了? | 极客时间为什么程序员都在冲软考?| 极客时间从入门到就业,心理咨询师高效成长有何秘诀?丨最后5人我是销售冠军(3)well, it is official now为什么征服了全球无数开发者的 C语言可能被 Rust 取代?| 极客时间生娃后圆肩驼背没气质?这套动作让你从头美到脚0 基础开发了个 AI 应用,牛大了!| 极客时间911, 美中反恐的结果金星人告诉你真理:癌症是思想造成的我做了120节PyTorch课程,从入门到实战【包邮送书】大模型框架 LangChain 杀疯了,普通人如何把握机遇?| 极客时间揭示计算主义世界观,这本新书问世即成经典!| 极客时间【活动】1.5h搞定Co-op:大佬手把手带你从入门到精通2023回国 走走看看,上海街拍(图)心理学从入门到精通,5本全掌握!(豆瓣9.0+)适合PyTorch小白的中文教程:涵盖数理编程基础,从入门到实战!撬动万亿级别市场的 AI 大模型,开发者如何借势乘风破浪?| 极客时间优秀架构图的标准是啥?阿里P9实践总结 | 极客时间OpenAI 再次颠覆行业,开发者的下一个增长曲线 | 极客时间道哥:成为 CTO 是个相当糟糕的目标 | 极客时间玩转并发编程!没到 35k 的 Java 开发都值得好好读一读 | 极客时间学好 Prompt,和大模型双向奔赴!| 极客时间国内最牛逼的 Spring Cloud,不接受反驳!| 极客时间云原生面经分享:精心整理的 K8s / Docker / DevOps 面试真题!| 极客时间告别焦虑!如何成为掌控 AI 工具的技术人?| 极客时间极客时间六周年 • 致用户信 | 极客时间App监管走向何方?个保法落地难点何解?有读者进字节前,把这套 Go 八股反复啃了5遍 | 极客时间
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。