写点什么

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

  • 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:568616
用户头像

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

关注

评论

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

音视频剪辑DIY:用Python快速入门音视频剪辑

老猿Python

Python 音视频 视频剪辑 Moviepy 引航计划

硬核!4396万字神文精解高并发高可用系统实战,分布式系统一致性文档一经面试震惊寰宇!

Java 编程 架构 面试 程序人生

密码学系列之:海绵函数sponge function

程序那些事

密码学 程序那些事 海绵函数

谈 C++17 里的 Visitor 模式

hedzr

c++ 设计模式 Design Patterns GoF设计模式

oh,我的老伙计,你看看这近五十个dapr视频

newbe36524

k8s dapr

计算机操作系统学习笔记 | 操作系统功能

Regan Yue

操作系统 9月日更

【LeetCode】栈的最小值Java题解

Albert

算法 LeetCode 9月日更

一行Java代码实现游戏中交换装备

华为云开发者联盟

Java 线程 游戏 Exchanger JDK 1.5

数据库为何又如何走向分布式?

多颗糖

MySQL 数据库 分布式 raft TiDB

大一 PingCAP、大二 JetBrains,专访 00 后开发者:千里冰封

郭旭东

开发者 采访 大学生

小白也能看懂的dubbo3应用级服务发现详解

捉虫大师

dubbo 服务发现 Dubbo3

2021年区块链被列为“七大重点产业之一”

CECBC

移动WEB开发会用到的 5 个API

devpoint

WebGL canvas Fetch 9月日更

手撸二叉树之左子树之和

HelloWorld杰少

9月日更

在线JSON转io-ts工具

入门小站

工具

聊聊新工具Hutool

卢卡多多

POI 数据导入 9月日更

数据规范的重要性

奔向架构师

数据治理 9月日更

潜入培训机构,顺出来一份价值 2.2W 的 Python 人工智能大纲

梦想橡皮擦

9月日更

Python——lambda 函数

在即

9月日更

[资源收藏]高质量外文博客(持续更新)

baiyutang

9月日更

新思科技:部署数据安全战略,加强安全管理和隐私保护

InfoQ_434670063458

数据安全 新思科技

ECIC演讲精华|如何构建云原生应用下的高性能持久化存储?

焱融科技

技术 分布式 云原生 高性能 存储技术

MQ是一种新的通信模式

风翱

MQ 9月日更

linux之dos2unix命令

入门小站

Linux

敬自由:破壁人华为,开启PC的无界探索

脑极体

【Flutter 专题】47 图解新的状态管理 Provider (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

Python中如何优雅的使用assert断言

wangkx

Python assert

翻转未来!钢铁之城重添色彩

脑极体

macOS 制作 linux 启动盘

耳东@Erdong

Mac 软件 9月日更

源码解读Dubbo分层设计思想

vivo互联网技术

Apache dubbo 服务器 spi

华为云首席产品官方国伟:没有人拥有看到未来的水晶球,云上突围之路如何走?

华为云开发者联盟

云计算 云原生 数字化转型 华为云 伙伴云

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