DDD 即领域驱动设计(Domain-Driven Design)。它来源于著名建模专家 Eric Evans 发表的很是具备影响力的书籍:《domain-driven design –tackling complexity in the heart of software》(中文:领域驱动设计—软件核心复杂性应对之道)。其最先普遍应用于传统软件架构设计中。前端
今年4月,InfoQ 发布了软件架构与设计的趋势报告。在报告中能够看出,微服务、领域驱动设计等已成为目前软件开发行业的主流趋势,笔者也了解到,DDD 已成为大部分企业微服务落地、中台建设的指导思想。web
(图片来源:infoQ)spring
隔离变化和沉淀复用数据库
在互联网时代,业务系统构建初期,场景一般简单清晰,基于数据库表设计+CRUD 就能支撑业务的敏捷迭代。随着时间的推移,场景和业务逻辑变得复杂、定制,模块之间彼此耦合,系统变得愈来愈臃肿,每每牵一发而动全身。即便加一个字段这样看似简单的逻辑,光梳理对其余功能点和模块的影响,就至少须要一个对业务和代码都很熟悉的团队老成员才能稳妥敲定。相信一个实现1年以上的业务系统,其架构和代码就有可能正在经历着以上这些,开始慢慢腐化。后端
一个最经典的例子——电商系统里面诸如如下 product 类的设计(现实中字段数可能几百个),它是不符合高内聚低耦合这个架构设计原则的:restful
DDD 经过划分限界上下文,拆分子领域,实现解耦和复用:网络
如下图片来自软件开发教父:Martin Fowler。诚然,为应付愈来愈复杂的业务逻辑,以自顶向下设计的领域聚合模型替代数据表模型,才能真正实现以业务实体为核心的灵活拓展:架构
以上,让经历互联网泡沫存活下来的系统弄潮儿逐渐重燃对 DDD 的热情,但愿借助 DDD 能重拾建造更合理软件架构的信心。但在落地上,荆棘环生,困境各异。下面咱们来介绍一下 DDD 在京东 DevOps 项目协做领域的落地实践。app
将 DDD 应用到组件化框架
在京东内部,项目协做领域有两个用户群体覆盖特别广(总用户数 8W+)的系统:PMP 和行云。
PMP是一个更面向项目经理的项目管理软件,包含项目流程管理、需求管理、里程碑管理、任务管理、工时管理、成本管理、OKR 管理、ROI 验证和满意度评分等。在架构设计上,PMP 是一个很是庞大的单体应用,其先后端不分离,全部业务逻辑糅杂在一块儿,项目表单字段数达到了 100+。通过时间和组织的变迁,在可扩展性和可维护性上,简直是场灾难。
行云起初的定位是面向研发的敏捷协同软件,包含跨部门需求管理、敏捷迭代和任务管理等。随着行云的普遍使用,将 PMP 功能融合到行云的呼声愈来愈高。
同时,行云对公司外部提供 ToB 服务。内外部存在着大量差别化的场景和业务,单纯靠以往的不断添加 if else 揉泥球的方式,已经彻底行不通。新的定位和背景下,要求咱们必须将业务逻辑拆分为一个个灵活的组件,作到复用与逻辑沉淀;另外一方面,差别化的逻辑能够灵活扩展。这其中有着巨大的挑战:
上图中间圆弧描述的是咱们在对组件拆分时参考的原则(业务可独立运营、高内聚低耦合、数据完整性、渐进性),以此为基础,在应对业务和技术视角上的挑战时,咱们采起的相关 DDD 战略和战术。
业务的挑战
PMP 和行云中都有需求管理、任务管理。这其中需求、任务是否是一个概念?项目、需求、迭代、任务等之间是什么关系?如何对内和对外沉淀一套清晰可复用的业务组件?
DDD 中概念比较多,包含限界上下文、聚合、聚合根、实体、值对象等,本文先不关注这些细节,直接聚焦如下问题:
一、 划分边界,识别领域对象或者领域类,保证其职责清晰纯粹;
二、 明确领域类之间的关联、依赖,界定调用关系和方式。
经过领域分析建模,造成统一语言,最终将项目协做管理这个总体,拆分为一个个功能完整、业务逻辑明确的业务域,如项目域、任务域、工时域等等。每个业务域对外提供明确的领域服务,一个业务领域能够管理多个业务实体。
x_lazy=1&wx_co=1)
技术的挑战
在划分完领域后,理想的状况是各领域高度自治,减小依赖,甚至各领域能够由不一样的团队来实现,各团队聚焦沉淀该领域核心能力。
最终,咱们造成了一个组件化方案:根据划分出来的领域,将系统拆分红业务组件(核心子领域)和基础组件(通用和支撑子领域),各组件先后端分离。即会有如下前端应用:需求管理、项目管理、缺陷管理、用例管理等;后端应用相应提供不一样的领域服务,领域服务采用分层架构(interface, application, domain, infrastructure)。权限管理、网关服务、消息服务等基础组件下沉,实现最大化组件复用。
按照领域拆分红业务组件,对系统来讲,最终提供给终端用户还需是一个总体。但组件化意味着分离,那对于业务组件的先后端应用又面临怎样的协同挑战呢?**
业务组件前端应用的挑战
为了实现各业务组件能并行、独立演进,理想状况下,前端子应用需知足独立编译、打包、部署,并最终集成到一个平台上呈现统一的 UI 风格和一致的交互体验。
以上业界将此归结为微前端架构:实现一种架构风格,能够将众多独立交付的前端应用组合成一个大型总体,对客户表现为一件单一完整的产品。
最终,咱们行云团队落地了一个 Jmodule 微前端组件框架。
前端应用经过微前端架构和前端组件框架注册到平台,系统层实现组件元数据管理、运行时热加载静态资源和组件间通讯,对用户侧提供彻底可插拔可配置的组件。具体原理和实现等将在后续另外一篇章节中展开。
业务组件后端应用的挑战
行云在设计之初,后端服务采用的是微服务的架构(利用spring cloud gateway、Eureka 等实现服务注册、网关调用等),这和 DDD 相得益彰。在核心业务组件内,领域服务按照经典分层架构(interface, application, domain, infrastructure)来组织。
除了界定组件内部分层的边界,还须要明确组件间的调用和依赖关系,进一步明确组件的职责。在 DDD 中相应地定义了限界上下文之间的映射关系:
在组件的调用和依赖关系上,咱们能够借鉴以上映射关系的理念来落地。
举个例子,咱们已经沉淀了项目组件和任务组件。假设须要实现的业务场景:当删除某个项目时,须要检查项目中是否已有进行的任务,无则删之,有则提示不能删。根据 DDD 的映射关系,任务被项目依赖,任务处在上游的位置,理想状况下它不须要知道项目业务领域删除的具体逻辑规则,同时尽可能减小项目业务规则的变化所带来的影响。
因而,咱们在落地的时候,淘汰了下图左侧的实现方式——合做关系(项目和任务网状式相互调用,我中有你,你中有我),而是在下游项目领域加了一层适配层,来隔离业务的变化对上游的影响。同时,也确保任务这层逻辑干净、清晰,以供更多其余组件复用。
总结
总结一下,本文大致给出了 DDD 思潮在如下方面落地上的指导意义:
敬请期待
以后会在后续章节中分享 DDD 在插件落地的实践,解决以下问题:
如何快速响应五花八门的定制化需求,同时保持自身不腐化?