SOFA 应用架构

向作者提问
2007年计算机硕士毕业,分别在Apple,eBay担任过Staff Engineer的职位,目前在阿里巴巴担任高级技术专家职位,是JCP的正式会员,因为对社区的贡献,去年获得阿里巴巴《ATA年度技术小二》称号。
查看本场Chat

前言

从业这么多年,接触过银行的应用,Apple 的应用,eBay 的应用和现在阿里的应用,虽然分属于不同的公司,使用了不同的架构,但有一个共同点就是都很复杂。导致复杂性的原因有很多,如果从架构的层面看,主要有两点,一个是架构设计过于复杂,层次太多能把人绕晕。另一个是根本就没架构,ServiceImpl 作为上帝类包揽一切,一杆捅到 DAO(就简单场景而言,这种Transaction Script也还凑合,至少实现上手都快),这种人为的复杂性导致系统越来越臃肿,越来越难维护,酱缸的老代码发出一阵阵恶臭,新来的同学,往往要捂着鼻子抠几天甚至几个月,才能理清系统和业务脉络,然后又一头扎进各种 bug fix,业务修补的恶性循环中,暗无天日!

image.png

CRM 作为阿里最老的应用系统,自然也逃不过这样的宿命。不甘如此的我们开始反思到底是什么造成了系统复杂性? 我们到底能不能通过架构来治理这种复杂性?基于这个出发点,我们团队开始了一段非常有意义的架构重构之旅(Redefine the Arch),期间我们参考了 SalesForce、TMF2.0、汇金和盒马的架构,从他们那里汲取了很多有价值的输入,再结合我们自己的思考最终形成了我们自己现在的基于扩展点 + 元数据 + CQRS + DDD 的应用架构。该架构的特点是可扩展性好,很好的贯彻了 OO 思想,有一套完整的规范标准,并采用了 CQRS 和领域建模技术,在很大程度上可以降低应用的复杂度。本文主要阐述了我们的思考过程和架构实现,希望能对在路上的你有所帮助。

复杂性来自哪里

经过我们分析、讨论,发现造成现在系统异常复杂的罪魁祸首主要来自以下四个方面:

可扩展性差

对于只有一个业务的简单场景,并不需要扩展,问题也不突出,这也是为什么这个点经常被忽略的原因,因为我们大部分的系统都是从单一业务开始的。但是随着支持的业务越来越多,代码里面开始出现大量的 if-else 逻辑,这个时候代码开始有坏味道,没闻到的同学就这么继续往上堆,闻到的同学会重构一下,但因为系统没有统一的可扩展架构,重构的技法也各不相同,这种代码的不一致性也是一种理解上的复杂度。

久而久之,系统就变得复杂难维护。像我们 CRM 应用,有 N 个业务方,每个业务方又有 N 个租户,如果都要用 if-else 判断业务差异,那简直就是惨绝人寰。其实这种扩展点(Extension Point),或者叫插件(Plug-in)的设计在架构设计中是非常普遍的。比较成功的案例有 Eclipse 的 plug-in 机制,集团的 TMF2.0 架构。还有一个扩展性需求就是字段扩展,这一点对 SaaS 应用尤为重要,因为有很多客户定制化需求,但是我们很多系统也没有统一的字段扩展方案。

面向过程

是的,不管你承认与否,很多时候,我们都是操着面向对象的语言干着面向过程的勾当。面向对象不仅是一个语言,更是一种思维方式。在我们追逐云计算、深度学习、区块链这些技术热点的时候,静下心来问问自己我们是不是真的掌握了 OOD;在我们强调工程师要具备业务 Sense,产品 Sense,数据 Sense,算法 Sense,XXSense 的时候,是不是忽略了对工程能力的要求。据我观察大部分工程师(包括我自己)的 OO 能力还远没有达到精通的程度,这种 OO 思想的缺乏主要体现在两个方面,一个是很多同学不了解 SOLID 原则,不懂设计模式,不会画 UML 图,或者只是知道,但从来不会运用到实践中;另一个是不会进行领域建模,关于领域建模争论已经很多了,我的观点是 DDD 很好,但不是银弹,用和不用取决于场景。但不管怎样,请你抛开偏见,好好的研读一下 Eric Evans 的《领域驱动设计》,如果有认知升级的感悟,恭喜你,你进阶了。我个人认为 DDD 最大的好处是将业务语义显现化,把原先晦涩难懂的业务算法逻辑,通过领域对象(Domain Object),统一语言(Ubiquitous Language)将领域概念清晰的显性化表达出来。相信我,这种表达带来的代码可读性的提升,会让接手你代码的人对你心怀感恩的。借用 Abelson 的一句话是:

橙子
建飞哥,之前在csdn上看过这篇文章了,现在又在gitchat在复习一遍。
微信扫描登录