写点什么

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

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

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

关注

评论

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

通义灵码最全使用指南,一键收藏

阿里云云效

阿里云 云原生 通义灵码

淘宝商品详情API:优惠券与红包信息的深度解析

代码忍者

api 网关 API 策略

低代码平台这么多,JNPF凭什么能火?

高端章鱼哥

AI助攻开学季,百度文心智能体平台上线2000+教育智能体

Geek_2d6073

飞书发布最强业务工具:新一代多维表格、低代码平台、飞书项目

ToB行业头条

TikTok海外直播专线:提供稳定、高效直播体验

Ogcloud

海外直播专线 海外直播 tiktok直播专线 海外直播网络 tiktok直播网络

Java核心知识体系-并发与多线程:线程基础

EquatorCoco

Java Python

网络管理方法及软件选择指南

Geek_a83400

面试场景题:一次关于线程池使用场景的讨论。

快乐非自愿限量之名

程序员 面试 线程池

JNPF低代码开发平台,一切尽在掌握

秃头小帅oi

零一万物开源 Yi-Coder 模型;原 OpenAI 首席科学家新公司 SSI 融资 10 亿美元丨 RTE 开发者日报

声网

活动在即,不容错过丨亚信安慧AntDB诚邀您参加“PostgreSQL数据库技术峰会”

亚信AntDB数据库

AntDB 月PK

通义灵码最全使用指南,一键收藏

阿里巴巴云原生

阿里云 云原生 通义灵码

天翼云,AI取经路上的逐梦人

脑极体

AI

淘宝商品详情API返回值中的优惠券与红包信息

技术冰糖葫芦

api 网关 API Explorer API 策略 pinduoduo API

高基数 GroupBy 在 SLS SQL 中的查询加速

阿里巴巴云原生

阿里云 云原生 sls

SD-WAN解决企业远程服务难题

Ogcloud

SD-WAN 企业组网 SD-WAN组网 SD-WAN服务商 SDWAN

Redis 主从复制、切片集群

不在线第一只蜗牛

数据库 redis

深入理解 Babel - 微内核架构与 ECMAScript 标准化|得物技术

得物技术

web前端 企业号2024年8月PK榜

听书APP创业者的救命稻草:源码在手,开发公司倒闭都不慌!

软件开发-梦幻运营部

2024世界消费电子展览会

AIOTE智博会

消费电子展

Databend 产品月报(2024年8月)

Databend

VMware Workstation 17.6 Pro Unlocker & OEM BIOS 2.7 for Windows & Linux

sysin

macos vmware OEM BIOS Workstation

进出口银行重庆分行支持航空飞机整机进口

科技热闻

如何精准选择多表查询的表连接方式?

测吧(北京)科技有限公司

测试

电商创新策略:深度挖掘亚马逊国际商品详情API返回值

代码忍者

AV-Comparatives确定2024年夏季的主要网络安全威胁

财见

分布式数据库系统环境的“无感”升级

PingCAP

掌握多表查询中的表连接查询方式

测吧(北京)科技有限公司

测试

如何处理 MySQL 主从延迟?

伤感汤姆布利柏

基于 TiDB 资源管控 + TiCDC 实现多业务融合容灾测试

PingCAP

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