11 解决技术改造困局的钥匙:整洁架构 有个“大师与太空”的梗是这样说的:大师通常都站得很高很高、高瞻远瞩,站得有多高呢?都是站在太空里的,所以很多人追随大师容易缺氧。因此,我们学习大师的理论,就要脚踏实地、踏踏实实地将其落地到项目应用中,重新落地到“地面”上,这些理论才是有用的,落地 DDD 同样是这样。

如何落地 DDD 呢?除了在项目中实践 DDD,领域建模,按照 DDD 的思想设计开发以外,还需要一个支持 DDD 与微服务的技术中台。在 DDD 实现过程中,这个技术中台应当能够封装那些烦琐的聚合操作、仓库与工厂的设计,以及相关的各种技术。有了这个技术中台的支持,开发团队就可以把更多的精力放到对用户业务的理解,对业务痛点的理解,快速开发用户满意的功能并快速交付,而不再受限于那些烦琐的技术细节,从而降本增效。这样,不仅编写代码减少了,技术门槛降低了,还使得日后的变更更加容易,技术更迭也更加方便。

那么,如何设计这样一个技术中台呢?首先应当从现有系统的设计痛点开始分析。

底层技术的更迭

这些年,随着互联网、大数据、人工智能等新技术层出不穷,整个 IT 产业的技术架构也在快速迭代。

  • 过去,我们说“架构是软件系统中最稳定不变的部分”;
  • 而现在,我们说“好的架构源于不停地演变”。

因此,如今的架构设计需要思考如何让底层的架构更易于技术更迭、易于架构调整,以应对不断演进的新技术、新框架,从而获得行业竞争的技术优势。

然而,在实际项目中,特别是很多运行了七八年、十多年的老项目,要做一次技术升级,那叫一个费劲,就像脱一层皮那么痛苦。为什么技术升级那么费劲呢?究其原因,是在系统设计开发时,大量的业务代码依赖于底层的技术框架,形成了耦合。

譬如,过去采用 hibernate 进行数据持久化,每个模块的 DAO 都要继承自 HibernateDaoSupport。这样,所有的 DAO 都与 Hibernate 形成了一种依赖。当系统架构由 Hibernate2 升级成 Hibernate3,甚至升级成 MyBatis,就不是改换一个 jar 包那么简单了。

技术框架一换,底层的类、接口、包名都变了,就意味着上层的所有模块的 DAO 都需要改,改完了还要测试。这样的技术升级成本极高,风险极大,需要我们认真去思考解决方案。

图片1.png

总之,老系统技术架构升级成本极高的根源,在于业务代码与底层技术框架的耦合。因此,解决思路就是对它们进行解耦。如何解耦呢?就是在上层业务代码与底层技术框架之间建立“接口层”。

图片2.png

DDD 11–金句.png

如何在业务代码与底层框架之间建立“接口层”呢?如上图所示,上层业务代码在进行持久化时,各个模块的 DAO 不再去调用底层框架,而是对接口层的 DaoSupport 进行调用。DaoSupport 接口是我们自己设计的,它应当满足上层的所有业务需求,比如各种类型的 insert、 update、delete、get、load、find,并让这个接口保持稳定。上层业务代码的设计实现都依赖于 DaoSupport 接口,只要它稳定了,上层业务代码就稳定了。

接着,在 DaoSupport 接口的基础上编写实现类,由实现类去调用底层技术框架,实现真正的持久化。

  • 起初使用 Hibernate2 作为底层框架,所以为 Hibernate2 编写了一个实现类。
  • 当 Hibernate2 升级成 Hibernate3 时,为 Hibernate3 写一个实现类。
  • 当底层框架要升级成MyBatis 时,再为 MyBatis 写一个实现类。

这样的设计,当系统进行技术架构升级时,其影响就不再扩展到业务层代码,而仅仅局限于调整接口层的实现类,技术升级的成本将得到大幅度的降低。

整洁架构的设计

图片3.png

通过前面对问题的分析与接口层的设计,可以得出一个非常重要的结论:如何既能轻松地实现技术架构演化,又能保证开发团队的快速交付呢,关键的思路是将业务代码与技术框架解耦。如上图所示,在系统分层时,基于领域驱动的设计,将业务代码都整合在业务领域层中去实现。这里的业务领域层包括了 BUS 层中的 Service,以及与它们相关的业务实体与值对象。

业务领域层设计的实质,就是将领域模型通过贫血模型与充血模型的设计最终落实到对代码的设计。在此基础上,通过分层将业务领域层与其他各个层次的技术框架进行解耦,这就是“整洁架构”的核心设计思路。

图片1.png

整洁架构(The Clean Architecture)是 Robot C. Martin 在《架构整洁之道》中提出来的架构设计思想。如上图所示,它以圆环的形式把系统分成了几个不同的层次,因此又称为“洋葱头架构(The Onion Architecture)”。在整洁架构的中心是业务实体(黄色部分)与业务应用(红色部分),业务实体就是那些核心业务逻辑,而业务应用就是面向用户的那些服务(Service)。它们合起来组成了业务领域层,也就是通过领域模型形成的业务代码的实现。

整洁架构的最外层是各种技术框架,包括:

  • 与用户 UI 的交互;
  • 客户端与服务器的网络交互;
  • 与硬件设备和数据库的交互;
  • 与其他外部系统的交互。

整洁架构的精华在于其中间的适配器层,它通过适配器将核心的业务代码,与外围的技术框架进行解耦。因此,如何设计适配层,让业务代码与技术框架解耦,让业务开发团队与技术架构团队各自独立地工作,成了整洁架构落地的核心。

Drawing 4.png

整洁架构设计的细化图,图片来自《软件架构编年史》

如图,进一步细化整洁架构,将其划分为 2 个部分:主动适配器被动适配器

  • 主动适配器,又称为“北向适配器”,就是由前端用户以不同的形式发起业务请求,然后交由应用层去接收请求,交由领域层去处理业务。用户可以用浏览器、客户端、移动 App、微信端、物联网专用设备等各种不同形式发起请求。然而,通过北向适配器,最后以同样的形式调用应用层。
  • 被动适配器,又称为“南向适配器”,就是在业务领域层完成各种业务处理以后,以某种形式持久化存储最终的结果数据。最终的数据可以存储到关系型数据库、NoSQL 数据库、NewSQL 数据库、Redis 缓存中,或者以消息队列的形式发送给其他应用系统。但不论采用什么形式,业务领域层只有一套,但持久化存储可以有各种不同形式。南向适配器将业务逻辑与存储技术解耦

整洁架构的落地

image

按照整洁架构的思想如何落地架构设计呢?如上图所示,在这个架构中,将适配器层通过数据接入层、数据访问层与接口层等几个部分的设计,实现与业务的解耦。

首先,用户可以用浏览器、客户端、移动 App、微信端、物联网专用设备等不同的前端形式,多渠道地接入到系统中,不同的渠道的接入形式是不同的。通过数据接入层进行解耦,然后以同样的方式去调用上层业务代码,就能将前端的多渠道接入,与后台的业务逻辑实现了解耦。这样,前端不管怎么变,有多少种渠道形式,后台业务只需要编写一套,维护成本将大幅度降低。

接着,通过数据访问层将业务逻辑与数据库解耦。前面说了,在未来三五年时间里,我们又将经历一轮大数据转型。转型成大数据以后,数据存储的设计可能不再仅限于关系型数据库与 3NF的思路设计,而是通过 JSON、增加冗余、设计宽表等设计思路,将其存储到 NoSQL 数据库中,设计思想将发生巨大的转变。但无论怎么转变,都只是存储形式的转变,不变的是业务逻辑层中的业务实体。因此,通过数据访问层的解耦,今后系统向大数据转型的时候,业务逻辑层不需要做任何修改,只需要重新编写数据访问层的实现,就可以转型成大数据技术。转型成本将大大降低,转型将更加容易。

最后,就是底层的技术架构。现在我们谈架构,越来越多地是在谈架构演化,也就是底层技术架构要不断地随着市场和技术的更迭而更迭。但是,话虽如此,很多系统的技术架构更迭,是一个非常痛苦的过程。为什么呢?究其原因,是软件在设计时,将太多业务代码与底层框架耦合,底层框架一旦变更,就会导致大量业务代码的变更,各个业务模块的都要更迭,导致架构调整的成本巨大、风险高昂。

既然这里的问题是耦合,解决的思路就是解耦。在平台建设的过程中,除了通过技术选型将各种技术整合到系统中以外,还应通过封装,在其上建立接口层。通过接口层的封装,封装许多技术的实现,以更加简便的接口开放给上层的业务开发人员。这样,既可以降低业务开发的技术门槛,让他们更加专注于业务,提高开发速度,又让业务代码与技术框架解耦。有了这种解耦,就使得未来可以用更低的成本技术更迭,加速技术架构演进,跟上这个快速变化的时代。

总结

整洁架构的中心是基于 DDD 的业务实现,即那些通过领域模型指导设计与开发的 Service、Entity 与 Value Object。整洁架构的最外层是各种硬件、设备与技术框架。而整洁架构最核心的思想,是通过适配器层,将业务实现与技术框架解耦,这也是 DDD 落地到架构设计的最佳实践。

因此,支持 DDD 与微服务的技术中台,就是基于整洁架构的思想,将 DDD 底层的那些烦琐的聚合操作、仓库与工厂的设计,与微服务的技术框架,以及整洁架构中的适配器,统统封装在技术中台中。有了这个技术中台,就能让上层的业务开发人员,更加轻松地运用 DDD 的思想,更加快捷地更迭与交付用户需求,从而在激烈的市场竞争中获得优势。

下一讲将进一步讲解这样的技术中台是如何设计的。

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/DDD%20%e5%be%ae%e6%9c%8d%e5%8a%a1%e8%90%bd%e5%9c%b0%e5%ae%9e%e6%88%98/11%20%20%e8%a7%a3%e5%86%b3%e6%8a%80%e6%9c%af%e6%94%b9%e9%80%a0%e5%9b%b0%e5%b1%80%e7%9a%84%e9%92%a5%e5%8c%99%ef%bc%9a%e6%95%b4%e6%b4%81%e6%9e%b6%e6%9e%84.md