随着业务发展,软件规模越来越大,各种各样的需求层出不穷,新业务的开发和老业务的维护会变得越来越艰难。成熟的软件系统总是趋向于增加复杂度,就像是熵只增不减一样,这是一个不可逆的过程。
正如人月神话中所说,软件的扩展并非相同元素的重复添加,而且这些元素之间的交互又以非线性的方式持续增长。通常情况下,单纯增加人力投入并不能取得同等的线性效果,复杂业务的开发面临很多挑战。
分布式和微服务是软件系统解耦的常用方案。通过一定程度的拆分,达到各个部分之间进行接口调用,只关注接口定义,不再关心接口的具体实现,进而实现软件系统多个部分之间的解耦。
解耦之后,不同部分由不同的团队维护,实现代码上的隔离,降低复杂度。同时,基于接口定义的调用,还能显著提高软件的复用度,把不同业务方的多种需求实现统一。目前已经有非常成熟的分布式方案 HSF、dubbo、spring cloud 和微服务方案 REST 被广泛应用。
在分布式的基础上,进一步抽象可以在软件架构上进行分层来降低复杂度。以淘宝的一个系统为例,如下图所示,总体上可以分为业务系统、核心业务服务、基础业务服务、持久层四个层次,在每个层次中又有多个子系统。
每个层次的子系统都可以被上一层的多个子系统复用,通过 hsf 提供服务有效地屏蔽了本层次的业务实现,并且,通过天梭、鹰眼、红警等监控工具可以有效地追踪一个请求在多个子系统之间的传递。
业务分层带来的是软件复杂度的极大降低,使得整个架构易于理解,每个部门和团队都可以集中精力在自己负责的层次和子系统上,形成工业流水线的工程效果。
具体到一个子系统的实现上,需要进一步进行模块划分。划分模块的基本原则是高内聚低耦合。划分模块形成黑盒效果,能够有效降低复杂度,提高开发效率。
模块化的经典案例是 spring 的架构设计。在 spring 中 Core 提供了最基本的 IOC 服务和各种工具类,Context 提供了上下文服务,AOP 模块专注于面向切面编程的实现,Web、Web MVC 专注于 Web 应用的开发。各个模块各司其职互不干扰,模块内部聚焦于模块功能的实现,模块间存在调用关系但并不关心具体实现。
在软件的设计中,需要把尽量多的配置内容剥离出来,形成配置文件。代码本身只实现业务的流程,关注业务的逻辑。而配置文件中的各种配置,用于控制业务的流动。在开发中,既要充分利用 spring 等开源框架的配置文件,也要考虑软件自身业务形成配置文件,提高代码的复用度和灵活性。
在阿里,为了便于配置文件的管理,已经形成了专门管理配置的 diamond 服务。diamond 提供配置的持久化,客户端通过订阅配置来获取配置内容,能够在运行时感知 diamond 配置变化实现更新。有了 diamond 管理配置,程序员可以专注于业务逻辑的梳理和实现,开发出通用性更好的程序代码。
每周 3 篇学习笔记或技术总结,面向有一定基础的 Java 程序员,内容涉及 Java 进阶、虚拟机、MySQL、NoSQL、分布式计算、开源框架等多个领域。关注作者或微信公众号 后端开发那点事儿 第一时间获取最新内容。