许式伟的架构课Day24架构老化与重构

130 阅读6分钟

架构的老化

架构的功夫全在平常.

架构老化源于什么?

在我们不断给系统添加各种新功能的时候, 往往会遇到功能需求的实现方式不在构设定的范围之内, 于是很多功能代码译出框架的范围之外.

这些散落在各处的代码, 把系统绞得支离破碎. 久而久之, 代码就出现老化, 散发出臭味.

代码老化的标志, 是添加功能越来越难, 迭代效率降低, 问题却是持续不断, 解决一个问题却又由此生出好几个新问题.

在理想的情况下, 如果我们坚持以“最小化的核心系统 + 多个相互正交的周边系统” 这个指导思想来构建应用, 那么代码就很难出现老化.

但现实情况下, 很多原因会导致架构老化难以避免, 比如:

  • 软件工程师的技术能力不行, 以功能完成为先, 不考虑项目的长期维护成本.
  • 公司缺乏架构评审环节, 系统的代码质量缺乏持续有效的关注.
  • 需求理解不深刻, 最初架构设计无法满足迭代发展的需求.
  • 架构迭代不及时, 大量因为赶时间而诞生的布丁式代码.
  • ...

那么, 怎么应对架构老化?

这个问题可以从两个视角来看:

  • 该怎么重构系统, 才能让我们的软件重新恢复活力?
  • 在重构系统之前, 我们应该如何进行局部改善, 如果增加新功能又应该如何考虑?

老系统怎么添加新功能

先说如何添加新功能.

正常来说, 我们添加功能时, 尤其是自己加入项目组较晚, 已经有大量历史代码沉淀在那里们应该把自己要添加的功能定位为周边功能. 对于周边功能, 往往考虑最多的是 如何少给核心系统添加麻烦, 能够少改就少改.

但是这样是不够的了. 我们把视角放在周边系统, 其实它本身也该被看作独立业务系统. 这样我们自然会有新的要求: 如何让新功能的代码与既有系统解耦, 能够不依赖尽量不依赖.

做新功能的思路: 尽可能与既有系统剥离, 从独立业务视角去实现业务, 抽象对环境的依赖. 最后, 用最少量的对接代码把整个系统串起来.

架构的局部优化

局部调整, 目标是优化某个功能与核心系统的耦合关系.

局部调整看似收效甚微, 但是它的好处是可以快速推动. 而且, 日拱一卒, 如果我们能够坚持下来, 最后的效果远比你想象得好.

它有两种做法.

一种是重写, 或者叫做局部重构. 它相当于从系统中彻底移除的代码者重新写一份新的.

但是我们不能太热衷于做局部重构. 局部重构一定要发生在你对这块代码的业务比较了解的情形, 比如你已经维护过它一阵子了.

另一种是依赖优化. 它关注的重心不是某项功能本身的实现, 而是它与系统之间的关系.

依赖优化整体上做的是代码的搬运工. 怎么搬代码?和删除代码类似,我们要找到和该功能相关的所有代码。但是我们做的不是删除,而是将散落在系统中的代码集中起来。

如果伤害值不大, 代表耦合在合理范围, 做到这一步暂时不再往下走时可接受的. 如果耦合过多, 那就意味着我们需要站在这个功能本身的业务视角看依赖的合理性了. 如果不合理, 可以考虑推动局部重构.

依赖优化的好处比较明显. 其一, 工作量小, 做的是代码搬运, 不改变任何业务逻辑. 其二, 可以不必深入功能的细节, 只需要找到该功能的相关代码, 这是难点, 然后把它们集中起来.

尽可能把我们认为非核心系统的功能, 都基于依赖优化的方式独立出去. 这样核心系统与周边系统的耦合就理清楚了.

依赖优化, 可以把周边系统对核心系统的代码注入, 整理得清清楚楚. 这也是事件机制的需求来源.

核心系统的重构

对于一个积弊已久的系统, 要想成功完成整体的重构是非常艰难的.

如果一上来就去重构核心系统, 风险太高. 其一, 牵一发而动全身, 我们无法保证工程的交付周期. 另一方面, 没有谁对全局有足够的了解, 重构会过于盲目, 项目的执行风险难以把控.

确定要对核心系统进行重构, 那么最高优先级是确定它的边界, 也就是适用界面(接口)

周边系统对核心系统的依赖无非两类: 一是核心系统的功能, 表现为它提供的DOM接口; 二是核心系统提供的事件, 让周边系统能够介入它的业务流程.

对所有周边模块进行依赖优化整理, 细加分析后可以初步确定核心系统需要暴露的事件集合.

进一步要做的事情就是把核心系统的DOM接口也抽象出来. 这一步比较复杂. 它包含两件事:

  • 让周边系统对它的依赖, 变成依赖接口, 而非依赖实现.
  • 审视核心系统功能的DOM接口的合理性, 明确出我们期望的接口设计.

接下来, 最重要的就是, 我们需要对核心系统的接口进行重新设计, 这一步难点在于:

第一, 我们对业务的理解又了长足的进步. 我们抽象的接口又了更加精炼符合业务本质的表达方式.

第二, 对周边系统切换到新接口的成本有充足的预计.

完成了接口改造, 剩下来就简单了. 核心系统, 每一个周拜年系统, 彼此完全独立, 可以单独调整和优化.

这不像那些系统边界分解得不清不楚的业务系统. 要改核心系统的代码? 不要命了么?

结语

重构工作是很有技巧性的, 很能培养一个人的架构能力. 做多了, 我们可以建立对代码耦合的条件反射, 看一眼就知道架构是否合理.

从实现难度来看, 重构比实现一个全新的架构过程要难得多. 重构, 不只是一个架构的合理性. 它包含了架构合理性的考量, 因为我们需要知道未来在哪里, 我们迭代方向在哪里.

此文章为3月Day24习笔记, 内容来源于极客时间《许式伟的架构课》, 强烈推荐该课