写点什么

阅读者 (二十八):实现领域驱动设计

  • 2014-05-15
  • 本文字数:2398 字

    阅读完需:约 8 分钟

从 Eric Evans 写下经典名著 Domain-Driven Design: Tackling Complexity in the Heart of Software 至今,DDD 刚好发展了十年的时间。它几乎成了开发复杂软件系统主要的领域设计方法,既是面向对象(组件)设计的补充,又超越了面向对象(组件)设计。DDD 中提出的诸多概念如实体、值对象、聚合等,已经成为了耳熟能详的设计术语。DDD 社区的发展也如火如荼,似乎并没有被层出不穷的设计思想所取代,相反,它仍在强劲地发展,吸收了许多新的概念与方法,例如函数式编程思想、Event Source、CQRS 等。然而,就我个人所观察到的情况来看,许多项目虽然号称应用了 DDD 设计,但主要都停留在 Eric 所谓的“战术设计”层面。即使是战术层面,依旧有许多程序员没有弄明白实体与值对象之间的区别,不知道该怎么定义聚合以及聚合根,更谈不上合理地划分上下文(Context)。

我不明白其中内含的真实原因,只能冒昧地揣测是否 DDD 显得高高在上?究其原因,会否还是 Eric 惹的祸,他的那本经典之作美则美矣,却显得有些不接地气?至少,我的阅读感受正是如此。虽然在之后,国内也引进了其他一些与 DDD 相关的著作,例如 Jimmy Nilsson 的著作《领域驱动设计与模式实战》。这些书好虽好,却并没有全面深入地阐述领域驱动设计,更谈不上完整地实践,直到 Vaughn Vernon 的《实现领域驱动设计(Implementing Domain-Driven Design)》的出现。

这本书首先吸引我的是书中的第 2 章至第 4 章。虽然书中内容几乎忠实地反映了 Eric Evans 的 DDD 理论,但作者却创造性地在一开始就着眼于 DDD 的战略性设计,包括领域(Domain)、子域(Subdomain)、受限上下文(Unbounded Context)、上下文映射(Context Map)以及架构。以第 4 章架构为例,书中对 DDD 经典的分层架构进行了深入探讨与分析,并颠覆性地提出将基础设施层(Infrastructure Layer)置于用户接口层(User Interface Layer)之上。最初读来,简直让我莫名惊诧,然而仔细思索,从依赖倒置原则的角度来分析,实在是合乎情理。坦白说,它彻底解决了之前一直纠缠在我心底的一个问题:若我们视实体为 Repository 以及数据访问的对象,应将实体置于哪一层?在 DDD 中,实体对象承担了领域业务行为,但同时又可能通过 ORM 与数据表产生映射。基础设施层的数据访问对象(即传统的 DAO)需要调用这些实体对象。若它处于最底层,则会造成业务行为与基础设施的混合。若将实体与数据映射对象分离,既会造成对象之间的重复,又会导致不好的贫血对象。而将基础设施层放在分层架构的上端,非常巧妙地解决了这一问题。

我尤其喜欢本书引荐的由 Corkburn 提出的六边形(Hexagonal)架构。它完全突破了传统分层架构的窠臼,以独到的边界划分手法指导我们遵循关注点分离原则。该架构模式对端口(Port)与适配器(Adapter)的强调,使得我们可以在架构分析与设计时,更加关注系统之间的集成点,从而形成可视性极强的物理架构。这对于建立可伸缩的分布式架构尤有价值。我已在多个项目的架构设计中,运用了六边形架构模式,可谓收获颇丰。书中还提到了相对较新的 RESTful 架构,CQRS 架构以及事件驱动的架构模式和网格分布式计算。该书的附录还进一步探讨了聚合对象与事件源的组合设计。这些内容有助于我们树立整体的 DDD 架构观,可以说弥补了 Eric 书中对这些内容的空白。

Vaughn Vernon 是真正懂得写作的技术专家,他非常懂得如何“讨好”读者。翻开书,阅读第一章,你就会爱上它,爱上 DDD。书中给出的例子实在太棒了。看看他对 saveCustomer() 方法的版本演进,你会幡然醒悟,原来代码应该这样写。领域对象是一位谨慎的保密者,他严格地谨守着自己的秘密,只把业务外部行为暴露给你,使得你可以读懂它,却不应该干扰它的内部实现。这正是 DDD 中通用语言的价值。身为一名技术人员,我们精通 Java、C#、Scala、Ruby 等等语言,却忘了在企业开发中,真正需要展现的其实是业务通用语言。写代码首先是与人交流,而不是机器。

本书的精彩章节有很多,几乎阅读每篇都会有感悟。但我个人认为,尤其彰显本书价值的是第 8 章与第 10 章。并非其他章节不够好,但相对于实体、值对象等容易理解的概念而言,聚合总是被人所误用,又或者让人茫然不知所措。第 10 章总结了非常实用的聚合设计原则。例如,在一致性边界之内对真正的不变量进行建模的原则;设计小聚合的原则;通过唯一标识引用其他聚合的原则。在边界之外使用最终一致性的原则。

至于第 8 章介绍的 Domain Event,则是因为它不同于 Eric 的著作,将事件当做了与实体同等地位的头等公民。结合本书对事件驱动以及事件源的讲解,相信你在之后的领域建模时,会重视对领域事件的识别。若能正确地理解事件,则可以更好地掌握 CQRS 模式,并因地制宜地运用这一模式。

该书书名为 Implementing(实现) Domain-Driven Design,就说明作者的意图是要让 DDD 真正落地。怎么做到?——上实例!书中给出的虽然是虚拟案例,却非常接近真实。作者甚至按照一种演进设计的方式深入浅出地介绍了这两个完整案例。最能够帮助人理解的是,他在讲授 DDD 时,还结合案例给出了之前欠佳的反面案例,并通过识别设计的坏味道,运用 DDD 方式对其进行改进。作者甚至创造了虚拟的场景,使得我们在阅读这些内容时,就好像真正参与了设计师的讨论,甚至能听到他们的唇枪舌剑,最后是 DDD 专家的总结陈词,真好比身临其境地加入了这个虚拟团队,一起学习,一起分享,共同成长。

坦白说,我在阅读本书时方才发觉自己在 DDD 上的浅薄无知。或许是自己的悟性不够,未能很好地理解 Eric 提出的 DDD 概念。阅读此书,让我有醍醐灌顶之感。现在,对于 DDD,我已渐窥门径。若能多结合项目实践,定能登堂入室,甚至走得更远。


感谢张逸对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2014-05-15 08:568748
用户头像

发布了 109 篇内容, 共 43.7 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

定制开发软件的步骤

Geek_16d138

软件定制 app定制开发 软件开发定制

另辟蹊径者 PoseiSwap:背靠潜力叙事,构建 DeFi 理想国

鳄鱼视界

stable diffusion为什么能用于文本到图像的生成

3D建模设计

Stable Diffustion 文本到图像 AI 绘图

智能低代码洪流涌动程序员节,华为云Astro触发1024的乘法效应!

YG科技

提示找不到某些组件?

矩视智能

深度学习

私人服务器有什么用?

Geek_f19a80

服务器

观测云产品更新 | 数据转发、监控器告警策略等优化

观测云

监控告警 日志备份

微服务架构下的调试进阶:多环境多服务调试实践与策略

Apifox

架构 微服务 后端 多服务 多环境

分布式数据库 GaiaDB-X 与宝兰德应用服务器完成兼容互认

Baidu AICLOUD

分布式数据库

线上SQL超时场景分析-MySQL超时之间隙锁 | 京东物流技术团队

京东科技开发者

MySQL 数据库 间隙锁 企业号11月PK榜 SQL超时

直播实时数仓基于DataLeap开放平台在发布管控场景的业务实践

字节跳动数据平台

大数据 数据中台 数据安全 数据研发 企业号11月PK榜

华为云全新上线Serverless应用中心,支持一键构建文生图应用

YG科技

亚马逊云科技海外服务器初体验

三掌柜

亚马逊云科技

百度CTO王海峰:文心一言用户规模已达7000万

飞桨PaddlePaddle

文心一言4.0

使用VUE开发有什么好处呢?

Onegun

Vue 前端框架

SAM + 用于文本到图像修复的稳定扩散

3D建模设计

Stable Diffustion 稳定扩散 文本生成图像

2024杭州国际智慧城市与安防产品展览会

AIOTE智博会

智慧城市展 安防展

阿里Java一面,难度适中!(下篇)

王磊

Java 面试

凡泰极客亮相香港金融科技周,投身大湾区数字化建设

FinClip

前端安全沙箱技术会不会成为安全的标配?

Onegun

小程序 小程序容器 安全沙箱

数智化竞价, 企业数智化助力企业实现增收增利

用友BIP

降本增效 数智营销

为什么在财务共享中心建设初期人员不降反增?

用友BIP

财务共享

如何在本地运行稳定扩散模型

3D建模设计

Stable Diffusion Ai绘图 文本到图像

质量诊所案例分享之Junior QA常见问题诊断

QE_LAB

质量 质量保障

强大好用的shell:shell的工作原理

小齐写代码

阅读者(二十八):实现领域驱动设计_语言 & 开发_张逸_InfoQ精选文章