在项目中引入领域驱动设计的经验

  • Jan Stenberg
  • 邵思华

2015 年 8 月 18 日

话题:Ruby方法论Ruby on Rails架构语言 & 开发

Chris Patuzzo近期在一次演讲中介绍领域驱动设计(DDD)的原则,并结合一个基于Ruby on Rails的真实项目进行讲解。在这次项目之前,Chris 所在的团队为重新设计公司的主营网站所做的两个概念验证都因为可伸缩性方面的问题而失败了。因此,业务主管部门决定在这一次尝试中采取一种更为敏捷的、增量式的方法,他们受到了 DDD 的启发,在这次重启的开发过程中全力促进开发者与领域专家的交流。

Patuzzo 是Which?的技术主管。在他看来,DDD 的要点是捕捉到业务的概念,软件的构建需要围绕着对业务的理解而展开。在这次项目重启的过程中,开发者开始学会与领域专家进行深入交流,以试图理解整个业务的实际行为。在此基础上设计出合适的领域模型,并找到系统中存在的各个边界。按 Patuzzo 的经验来看,在具有清晰的边界划分的系统中开展工作要轻松许多。通过保持关注分离,系统将更易于理解,如果之后需要将系统中的某些部分提取出来,实现起来也会更简单。

DDD 建议将问题分解为多个层,每一层各司其职,例如表示层、领域层以及基础设施层。Patuzzo 特别提到在进行 Rails 开发时存在着一种常见的实践,即将领域层与基础设施层合并在一起,这种方式显然违背了 DDD 的建议。除了分层架构外,另一种选择是由Alistair Cockburn定义的多边形架构(Hexagonal architecture),但 Patuzzo 并不强烈主张这种架构风格,他认为这种架构可能会令人迷惑。他表示,这些架构有助于管理系统的复杂度,保持对核心领域的专注,但他也承认这些思想对于 Ruby 社区来说还比较新鲜,需要一定的时间去适应。

衡量复杂度的一种方式是计算对象间的交互,通过使用聚合与聚合根,可以将这种交互限制在聚合之内,以及聚合根之间的交互,从而将这种交互的频率减至最低。Patuzzo 将其称为系统的表面区域。Ruby 项目通常会使用活动目录(Active Record)这种设计方式,因此每个类都表现为全局的常量,可以在系统中的每一处随意访问。为了绕开这个问题,开发者通常会用聚合的名称作为类名的前缀。通过将系统功能分解为聚合,使对象间的通信显得更为结构化。这种新的设计方式对于团队来说确实引入了一个陡峭的学习曲线,这一部分在开发过程中所产生的分歧也是最大的。但在项目的回顾会议中,Patuzzo 对于最终的结果表示很满意。

Patuzzo 在总结中表示:虽然全新的开发过程为开发者带来了一些负担,但好处也很明显。开发者学到了 DDD 的基本模式与思想、如何将架构分解为多个层、关注分离的思想、以及如何设计一个能够应对变化的系统。由于新系统是基于一个能够充分表现业务需求的模型而建立的,因此他相信他的团队将能够更好地满足新的需求。

查看英文原文:Experiences Introducing DDD in a Project

Ruby方法论Ruby on Rails架构语言 & 开发