共计 3615 个字符,预计需要花费 10 分钟才能阅读完成。
DDD 即畛域驱动设计(Domain-Driven Design)。它来源于驰名建模专家 Eric Evans 发表的十分具备影响力的书籍:《domain-driven design –tackling complexity in the heart of software》(中文:畛域驱动设计—软件外围复杂性应答之道)。其最早广泛应用于传统软件架构设计中。
往年 4 月,InfoQ 公布了软件架构与设计的趋势报告。在报告中能够看出,微服务、畛域驱动设计等已成为目前软件开发行业的支流趋势,笔者也理解到,DDD 已成为大部分企业微服务落地、中台建设的指导思想。
(图片起源:infoQ)
隔离变动和积淀复用
在互联网时代,业务零碎构建初期,场景通常简略清晰,基于数据库表设计 +CRUD 就能撑持业务的麻利迭代。随着工夫的推移,场景和业务逻辑变得复杂、定制,模块之间彼此耦合,零碎变得越来越臃肿,往往牵一发而动全身。即便加一个字段这样看似简略的逻辑,光梳理对其余性能点和模块的影响,就至多须要一个对业务和代码都很相熟的团队老成员能力稳当敲定。置信一个实现 1 年以上的业务零碎,其架构和代码就有可能正在经验着以上这些,开始缓缓腐化。
一个最经典的例子——电商零碎外面诸如以下 product 类的设计(事实中字段数可能几百个),它是不合乎高内聚低耦合这个架构设计准则的:
- product 类无所不包,什么畛域的常识都晓得;其职责不清晰,在 积淀 复用 上,团队成员的冀望都不统一,实现姿态可能千奇百怪;
- 洽购、仓储、配送业务畛域的逻辑变动可能都要批改 product,一个高内聚的零碎设计,是须要尽可能 隔离变动,使之产生的影响最小且管制在肯定边界内。
DDD 通过划分限界上下文,拆分子畛域,实现解耦和复用:
以下图片来自软件开发教父:Martin Fowler。诚然,为应酬越来越简单的业务逻辑,以自顶向下设计的畛域聚合模型代替数据表模型,能力真正实现以业务实体为外围的灵便拓展:
- 面向过程的脚本,不能很好地被扩大;
- 面向数据表的设计,适度关注数据疏忽行为,不能很好地被复用。
以上,让经验互联网泡沫存活下来的零碎弄潮儿逐步重燃对 DDD 的激情,心愿借助 DDD 能重拾建造更正当软件架构的信念。但在落地上,荆棘环生,窘境各异。上面咱们来介绍一下 DDD 在京东 DevOps 我的项目合作畛域的落地实际。
将 DDD 利用到组件化
在京东外部,我的项目合作畛域有两个用户群体笼罩特地广(总用户数 8W+)的零碎:PMP 和行云。
PMP是一个更面向项目经理的项目管理软件,蕴含我的项目流程治理、需要治理、里程碑治理、工作治理、工时治理、老本治理、OKR 治理、ROI 验证和满意度评分等。在架构设计上,PMP 是一个十分宏大的单体利用,其前后端不拆散,所有业务逻辑糅杂在一起,项目表单字段数达到了 100+。通过工夫和组织的变迁,在可扩展性和可维护性上,几乎是场劫难。
行云 起初的定位是面向研发的麻利协同软件,蕴含跨部门需要治理、麻利迭代和工作治理等。随着行云的宽泛应用,将 PMP 性能交融到行云的呼声越来越高。
同时,行云对公司内部提供 ToB 服务。内外部存在着大量差异化的场景和业务,单纯靠以往的一直增加 if else 揉泥球的形式,曾经齐全行不通。新的定位和背景下,要求咱们必须将业务逻辑拆分为一个个灵便的组件,做到复用与逻辑积淀;另一方面,差异化的逻辑能够灵便扩大。这其中有着微小的挑战:
上图两头圆弧形容的是咱们在对组件拆分时参考的准则(业务可独立经营、高内聚低耦合、数据完整性、渐进性),以此为根底,在应答业务和技术视角上的挑战时,咱们采取的相干 DDD 策略和战术。
业务的挑战
PMP 和行云中都有需要治理、工作治理。这其中需要、工作是不是一个概念?我的项目、需要、迭代、工作等之间是什么关系?如何对内和对外积淀一套清晰可复用的业务组件?
DDD 中概念比拟多,蕴含限界上下文、聚合、聚合根、实体、值对象等,本文先不关注这些细节,间接聚焦以下问题:
1、划分边界,辨认畛域对象或者畛域类,保障其职责清晰纯正;
2、明确畛域类之间的关联、依赖,界定调用关系和形式。
通过畛域剖析建模,造成对立语言,最终将我的项目合作治理这个整体,拆分为一个个性能残缺、业务逻辑明确的业务域,如我的项目域、工作域、工时域等等。每一个业务域对外提供明确的畛域服务,一个业务畛域能够治理多个业务实体。
x_lazy=1&wx_co=1)
技术的挑战
在划分完畛域后,现实的状况是各畛域高度自治,缩小依赖,甚至各畛域能够由不同的团队来实现,各团队聚焦积淀该畛域外围能力。
最终,咱们造成了一个组件化计划:依据划分进去的畛域,将零碎拆分成业务组件(外围子畛域)和根底组件(通用和撑持子畛域),各组件前后端拆散。即会有以下前端利用:需要治理、项目管理、缺点治理、用例治理等;后端利用相应提供不同的畛域服务,畛域服务采纳分层架构(interface, application, domain, infrastructure)。权限治理、网关服务、音讯服务等根底组件下沉,实现最大化组件复用。
依照畛域拆分成业务组件,对系统来说,最终提供给终端用户还需是一个整体。但组件化意味着拆散,那对于业务组件的前后端利用又面临怎么的协同挑战呢?**
业务组件前端利用的挑战
为了实现各业务组件能并行、独立演进,现实状况下,前端子利用需满足独立编译、打包、部署,并最终集成到一个平台上出现对立的 UI 格调和统一的交互体验。
以上业界将此归结为微前端架构:实现一种架构格调,能够将泛滥独立交付的前端利用组合成一个大型整体,对客户体现为一件繁多残缺的产品。
最终,咱们行云团队落地了一个 Jmodule 微前端组件框架。
前端利用通过微前端架构和前端组件框架注册到平台,零碎层实现组件元数据管理、运行时热加载动态资源和组件间通信,对用户侧提供齐全可插拔可配置的组件。具体原理和实现等将在后续另一篇章节中开展。
业务组件后端利用的挑战
行云在设计之初,后端服务采纳的是微服务的架构(利用 spring cloud gateway、Eureka 等实现服务注册、网关调用等),这和 DDD 井水不犯河水。在外围业务组件内,畛域服务依照经典分层架构(interface, application, domain, infrastructure)来组织。
- interface- 用户界面层:Controller、restful 接口调用,或者 web 端 UI 界面、挪动端 UI 界面、第三方服务等;
- apllication- 应用层 :对外为展示层提供各种利用性能,对内调用畛域层(畛域服务),应用层更像是实现某个特定场景的策略,或者流程上的编排等。其协同多个畛域的服务, 实现场景和业务的隔离;
- domain- 畛域层 :负责表白业务概念,业务行为,业务状态以及业务规定,畛域模型处于这一层,是业务软件的外围。 其提供的是一系列原子服务,在这一层提供丰盛的 OPEN API,是实现组件化至关重要的一步;
- infrastructure- 根底层 : 实现业务和技术的隔离层。个别蕴含:网络通讯、数据库长久化、异步音讯服务、南向网关服务等。这一层在落地的时候,能够实现多种适配器 adaptor 来兼容对内、对外、多云异构中间件环境。
除了界定组件外部分层的边界,还须要明确组件间的调用和依赖关系,进一步明确组件的职责。在 DDD 中相应地定义了限界上下文之间的映射关系:
- 单干关系:两个上下文严密单干的关系;
- 客户方 - 供应方:上下文之间有组织的上下游依赖;
- 遵奉者:上游上下文只能自觉依赖上游上下文;
- 拆散形式:两个齐全没有任何分割的上下文;
- 共享内核:两个上下文依赖局部共享的模型;
- 防腐层:一个上下文通过一些适配和转换与另一个上下文交互;
- 凋谢主机服务:定义一种协定来让其余上下文来对本上下文进行拜访;
- 事件公布订阅:通常用于定义凋谢主机的协定。
在组件的调用和依赖关系上,咱们能够借鉴以上映射关系的理念来落地。
举个例子,咱们曾经积淀了我的项目组件和工作组件。假如须要实现的业务场景:当删除某个我的项目时,须要查看我的项目中是否已有进行的工作,无则删之,有则提醒不能删。依据 DDD 的映射关系,工作被我的项目依赖,工作处在上游的地位,现实状况下它不须要晓得我的项目业务畛域删除的具体逻辑规定,同时尽量减少我的项目业务规定的变动所带来的影响。
于是,咱们在落地的时候,淘汰了下图左侧的实现形式——单干关系(我的项目和工作网状式互相调用,我中有你,你中有我),而是在上游我的项目畛域加了一层适配层,来隔离业务的变动对上游的影响。同时,也确保工作这层逻辑洁净、清晰,以供更多其余组件复用。
总结
总结一下,本文大体给出了 DDD 思潮在以下方面落地上的指导意义:
- 如何积淀清晰可复用的业务组件?
- 如何隔离组件间的变动对其余组件的影响?
敬请期待
之后会在后续章节中分享 DDD 在插件落地的实际,解决如下问题:
如何疾速响应形形色色的定制化需要,同时放弃本身不腐化?