BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

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

| 作者 张逸 关注 12 他的粉丝 发布于 2014年5月16日. 估计阅读时间: 7 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

从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)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

good by tang xuehua

这边书是不错,书中总结的几个关于聚合设计的原则,作者是通过实例的方式来论证只有那样做,系统才会更具伸缩性。但实际能做到那种程度的人,非常少;比如:聚合内强一致性、聚合间最终一致性,这点就意味着一个command只修改一个聚合根;这意味着啥?意味着像Unit of Work这种模式都不需要使用了,因为我们一次修改都只涉及到一个聚合根的修改;另外,还意味着,每个聚合根的所有行为都不需要依赖其他聚合根的状态了,因为每个聚合根都只更改自己的状态,然后通过领域事件通知外部发生了什么;结合,Event Sourcing和CQRS架构,那我们的command side的持久化完全不用我们自己来做了,ORM在command side已经不需要再使用,也就是领域对象(聚合根)无需再由程序员去用ORM来映射然后自己去保存状态了。

然后聚合根之间的最终一致性,则通过消息队列来实现,从而将一个本来要在一个Unit of Work事务内完成的多个聚合根的修改演变为了通过最终一致性的saga流程的方式来实现。流程的状态由saga来表达;

以上这种编程风格是和我们之前平时的方式完全不同的,能做到这个程度的人非常少;

所以,他提到的这几个聚合设计的原则要真正能落地,还有很多的路要走;

顺便做一下推广,呵呵。我的enode框架,目的是用来开发上述架构思想的程序的,欢迎指正和交流:
www.cnblogs.com/netfocus/category/496012.html

看这本书之前是否有必要先看Evans的领域驱动设计? by John Smith

看这本书之前是否有必要先看Evans的领域驱动设计?

Re: 看这本书之前是否有必要先看Evans的领域驱动设计? by Hu Ting

有必要,可以两者结合起来看。

DDD很好 by 李 引

ThoughtWorks应该搞DDD,好东西。毕竟老马提出的领域模型。
帮我向瑞民问好。

Unbounded Context 为啥翻译为 受限上下文? by GL Yao

如题: Unbounded Context 为啥翻译为 受限上下文。 Unbound 是 不受限的意思呀。 好奇怪.

纠正一点点 by 杨 雷

1, 纠缠在你心里的问题,应该还是没解决,'若我们视实体为Repository以及数据访问的对象,应将实体置于哪一层?'这个问题本来就有问题,Repo和DAO是一回事么,这简介导致后面你居然认可基础架构层放在顶层,里面含有DAO并且访问实体,完全乱套。。。
2,正是因为上面的混乱,导致你认可了6边型,不是说不好。正是因为它的弹性,相对而言变成你的银弹了,然后又回到最初,没有好的设计也一样能做出产品。。。
从头到尾,你还是没领悟什么是领域设计,,,可惜

Re: 看这本书之前是否有必要先看Evans的领域驱动设计? by 杨 雷

答复是,必须先看Evans的东西,否则你怎么才能赞成这种理念,并形成认可,最后才能在实践中思考如何应用

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

7 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT