> For the complete documentation index, see [llms.txt](https://xiaobaiha.gitbook.io/tech-share/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaobaiha.gitbook.io/tech-share/engineering/qian-duan-zhong-gou.md).

# 前端重构

工作中偶尔会有一些需要重构代码的情况，根据仅有的几次带着同事一起重构的经验，来简单谈一谈我对前端重构的看法。

## 重构的内容

* 工程级别：对于Vue项目来说，模块化程度是很高的，工程级别的重构，就是对工程目录进行调整，保证业务界面、公共组件的目录位置与命名都能充分反应其功能，让项目组所有的开发人员都能够一目了然。
* 代码级别：这里说的代码级别需要与代码逻辑区分。代码级别代指模块结构，就是对代码进行拆分与合并，抽象出能够公用的业务组件(component)或是混入(mixin)，做好核心业务代码的注释，减少单个Vue文件的代码行数，来让代码与功能模块更好的对应，整体设计上更为合理。当然拆分与合并也需要适度合理，像如代码混入如果使用不得到，在代码维护中会成为一个灾难。
* 逻辑级别：上两个级别的改动，做的工作更多的可能只是代码的移动。到了代码逻辑的级别，就是简化重复逻辑、减少无用逻辑、降低代码复杂度。代码逻辑级别的重构是效果最明显的，但也是风险最大的，一旦存在某个逻辑分支细节的遗漏，可能就会引入更多新的bug。

## 重构的时点

代码其实仅仅对开发人员而言是一个白盒，对其他岗位的人而言都是一个黑盒。我们能看到这个盒子内的齿轮哪里生锈哪里可能会有坏味道，在别人看来盒子还是在正常运行的，只是偶尔会有些问题。

好的重构，在投入很多时间完成之后，在别人看来，盒子依旧在正常运行。不好的重构，那就是在经过你手之后，盒子出现了更多的问题。所以重构代码其实是一个很吃力不讨好的活，也因此并不是任何时候都能挽起袖子重构代码。

个人推荐在需求比较少，岁月静好的时期进行重构，就好比非战争时期对装备进行休整。另外一点就是需要争得上级同意，虽然代码重构都是处于对项目负责的态度提出并开展的，但往往并不会计入个人绩效，存在的问题是否值得投入资源进行重构，更需要上级进行评估。

## 重构的原因

既然重构难度大，收效低，那么为什么还是需要重构？正如上文所说，重构代码的初衷，还是本着对项目负责的态度，我们能够看到白盒内那些会在未来某个时候影响盒子正常运行的问题，那就要想办法去解决这些问题。这些问题包括：

1. 项目工程初期在设计上有所遗漏，导致代码目录杂乱，后续新增的代码如同贴膏药一般，使代码结构更为混乱。混乱将直接导致代码维护难度加大，开发效率降低。
2. 项目迭代会导致的原有功能需要改动，而现有代码的扩展性较差，逐步新增的功能会在某个时刻爆发而要投入极大的人力。
3. 项目构成日趋复杂，其中包括的组件、混入、工具类方法、公共常量不断累计，没有进行分类，导致新人的上手难度大，成本高。

只有解决问题，才能让产品在不断的迭代中，不考虑市场、业务等其他因素的影响，至少在软件层面能可持续的发展下去。

## 重构的原则

* `功能不变`。重构代码最需要保证的内容，不可改坏原有功能。
* `项目适用`。我个人作为一个开发人员，时常会有一种技术优先的心态。会满腔热血地吐槽工作项目中还在使用某些老旧的技术内容，从而跟组长说为什么我们不用这个，为什么不用那个。一旦有机会重构代码，就能够放开手脚开干，尝试把某个新的架构或者依赖加入到某次项目迭代中。但使用之后往往并没有想象中那么大的成效。反之，增加了后续的维护成本，也需要其他同事投入学习。所以如果重构中需要引入新的技术内容，首先需要适用。没有做过充足的市场调研，没有进行过充分的学习就直接使用某些不成熟或者上手成本高的技术内容，往往并不能在工作项目中发生奇妙的反应。
* `重构不等于重写`。有时会吐槽某些已经离职，还是转技术栈后写前端的同事的代码，为什么代码会写成这样，主管也觉得这个模块bug过多，然后一拍即合开始重构，但重构完成后bug依旧没有减少。在业务场景十分复杂的项目工程中，重构代码并没有像开发新需求业务时，有那么多的时间来给你研究需求与设计文档。现有的大部分代码逻辑都有其存在的道理，看上去不合理的设计，可能只是对代码阅读的还不够充分。一旦推翻重写，就约等于抛弃了原来的一切，那么就要做好承担后续可能遇到的风险。如果没法承担风险，那就忠于原有代码，减少bug，增加改动前后的可测性。
* `渐进式重构`。与重构不等于重写相类似，整个重构过程是逐步完成的，整体上做好一个大致的推进计划。这个“逐步”，可能只是每天抽出一两个小时的时间，在晚上静静地坐在工位上，看了重构模块某一部分的内容，然后优化了十行不到的代码。也可能是阅读了一遍设计文档，在页面上进行实操，学习其中的业务逻辑。对整个过程进行拆分，根本目的是降低重构后带来的风险，

## 重构的实施

* 人员配置：对某个业务模块进行重构，根据业务复杂程度确定投入人力，一般两三人即可，人太多会使重构难以组织，沟通上会变的困难。人太少，比如就一个人进行重构，会缺少互相之间的代码审核而引入风险。且投入的人力需要对该业务某块有一定程度的熟悉。
* 制定计划：在重构前与上级进行沟通，对需要重构的部分进行评估，重构小组一起制定好不过于精细的计划，但一定需要尊从逐步完成，需要有阶段性的成果产出。可以先组织进行一个简单的业务学习会，再安排一人写好一个模版化的重构样例，然后分工好业务模块开始着手进行重构。
* 重构方向：按重构内容中的三个级别，由大到小对代码进行重构。先调整工程目录结构，再拆分整合解耦其中的组件与混入，重命名或是新增部分文件，最后通读代码内容，优化其中的逻辑。
* 代码规范：根据eslint、prettier为基础手段，在重构代码的同时也对代码规范进行合理化调整。增加阅读代码过程中必要的注释，尤其是对核心业务方法的注释，以及后续需要避免的问题，用`@TODO`、`@DESC`做好标记。
* 单元测试：在代码改动的同时进行仔细的单元测试，考虑用户可能存在的操作场景以及对应代码逻辑分支。做好前后对比测试，可以与UI同事沟通，进行一些交互上的优化，但业务功能一定需要保持不变。

## 总结

代码重构总的来看是一个难度大收效低的任务，也很难得到别人的认可。在重构任务中还是要保持自己重构的初心，勇于但不盲于担当改动后存在的风险，直面其中的bug，总结个中经验，强调重构带来的业务价值。
