写在前面:
工作中,前前后后参与和主导的项目重构已经有几次了,在这里将一些想法总结起来,一方面作为自己的经验积累,供后续参考,一方面希望能跟大家一起交流总结。能力有限,若是不对之处,还望读者指出。
要开始一个项目的重构,准备工作必不可少,本文没有写具体的技术实现,而是从更高的角度,总结一个项目的重构需要做哪些准备,可以从哪几个方面入口。
1. 跟做事要有目标一样,重构时先确定目标
主要包括以下几种情况:
- 是原有代码臃肿,想优化项目架构;
- 原有代码执行性能低,进行性能优化;
- 或者是技术迭代,需要更换技术栈
2. 阅读代码,了解业务功能点和现有架构实现方式
这一步主要是为了了解现有业务特点,分析现有的不足,然后为后面的新的架构设计做准备,既要了解大局架构上的情况,也要对细节业务逻辑处理有所了解。主要包括以下三个方面:
- (1)分析业务逻辑的特点;
- (2)搞清楚现有架构的不足,痛点在哪里;
- (3)搞清楚现有的不足,不是说是整体的不足,而是每个模块功能模块的具体不足。 搞清楚哪些部分是可以保留复用的,哪些部分是需要推翻重写的。
3. 特点分析
从业务和技术两个方面入手,业务上主要分析业务逻辑的复杂度和数据处理的特点;技术上,主要分析所采用技术站的特性。从而选择合适的架构
4. 设计合适的架构
-
设计架构时,先确定数据处理的主要方式是什么,这是架构的核心
比如,采用了react native和mobx,那么处理数据的主要方式是响应式的MVVM。然后再根据此核心,依据OCP原则(开闭原则),进行纵向层次和横向模块划分,识别每个模块的扩展点。
-
纵向层次划分
是指:从用户接触的最顶端的视图,然后到用于视图显示的数据,处理数据的业务逻辑,与下游和外部的逻辑部分等,从上—->下的层次划分。保证每个层次的职责单一,且符合OCP原则。
-
横向模块划分
是指:在每一层中根据业务功能,采用模块化的思想,划分出不同的模块,保证每个模块的功能单一。
-
依赖关系处理
划分之后,纵向层次之间的依赖方式和横向模块之间关联关系的处理,则是项目架构的关键,也可以说是架构的灵魂。
纵向层次之间的依赖,要考虑层次之间是单向调用,还是双向调用,是多层次均可调用某一层次,还是只有A层能调用B层次。
横向模块之间关联关系需要思考,是集中管理呢?还是去中心化分散到每个模块管理呢?关联关系是主动触发呢?还是被动触发呢?
5. 确定项目架构之后,需要进行关键点的架构设计
比如:
- 若项目中有个核心逻辑,其他部分均依赖此逻辑,则可将此部分先设计各雏形出来,方便后续重构的开展。
- 若是项目中业务逻辑均衡,不存在核心,则可将一个功能点用此架构进行初步实现,一方面可以验证架构的可用性,一方面可以作为其他模块的参考。
6. 重构不仅仅是写代码,还要考虑保证代码质量的方式和测试方式
如何保障代码质量估计是作为开发者一直纠结的难题了,通常可以采用工具+人工双重保障方式。
- 静态代码检查工具eslint;
- 阶段性人工review code
对于测试方式,一个项目的推翻重构,涉及到的所有业务逻辑都得进行测试,所以在步骤2中的梳理业务逻辑就变得很重要了,否则会造成业务功能的遗漏,通常采用功能测试为主,一些测试工具为辅的方式。
- 单元测试Jest;
- 功能测试;
- 等等
7. 仅仅保证质量还是不够的,性能才是终极目标
重构之后可交付的是供用户使用的软件,性能流畅才是终极目标。所以要考虑验证性能的方式,保证性能的策略,以及性能要达到的指标。
在重构之前,先确认之前的性能指标是什么水平,重构之后要达到什么水平。 验证性能的方式,根据项目实际情况,可采集渲染帧率、渲染耗时、逻辑处理复杂度等。
重构之前,阅读老代码,识别影响性能的环节,制定提高性能的策略和方式;阶段性验证性能是否符合指标要求。