什么代码需要重构
- 难以阅读, 就是可读性差。
- 逻辑重复。
- 添加新的行为需要修改已有代码。可拓展性差。
- 带有复杂条件逻辑。
- 需要提高性能
- 开发效率低
- 不易测试
重构以后的代码需要达到的目标是:
- 提高可读性。
- 相同的逻辑只出现一次。
- 新的改动不会危及现有行为。提高可拓展性。
- 尽可能简单地表达条件逻辑。
- 能显著提高代码运行性能。
- 提高开发效率,改进软件设计和分层。与可读性有些差异。
- 能方便测试和查找bug。
何时重构
- 平时开发时: 重复性工作,既有的代码无法帮助你轻松添加新特性时
- code review: 可以让他人来复审代码检查是否具备可读性,可理解性
- 测试时: 修补bug时,排查逻辑困难
- 交接时: 连自己都无法快速理清代码逻辑
重构的衡量指标
- 数量: 代码的行数
- 质量: 代码复杂度,耦合度,可读性,架构依赖复杂度等
- 成本: 花费的时间
- 回报: 支持后续功能的快速叠加,解决现有因代码设计问题无法优化的矛盾, 提高了代码运行效率等
具体表现
- 随着业务需求的不断加入,代码随着时间的推移变得越来越糟。
- 这其中可能包括以下情况:
- 重复的代码
- 过长的函数
- 遵循一条原则: 每当感觉需要注释来说明什么的时候,可以尝试将需要说明的东西写进一个函数中
- 冗余的类
- 当子类没有做足够的工作的时候,或者说在可见的预期内,不会有新的情况出现,考虑将类内联化。
- 过长的类
- 这种情况容易出现冗余代码。比如如果类内出现了多个变量带有相同的前缀或者后缀,这意味着你可以考虑把他们提炼到某个组件内,或者考虑这个组件是否可以成为子类,使用提炼类的手法来重构。

实例
纯react项目重构为redux + immutable.js
为什么重构
props自顶向下传递, 层级过深时:
- 所有属性和回调重复编写在不相关的父层组件
- 容易理解, 但是可读性差, 寻找方法和属性比较费劲
- 定位错误不易, 调用链过长
- 耦合度过高, 不易调试bug和测试
- 性能较差, 不相关组件在别的组件状态刷新时也可能刷新, 只能手动用react生命周期去做优化
重构后的结果
改为redux + immutable.js后
- 提取大部分组件状态到store, 批量管理
- 提取操作状态的方法到reducer, 方便拓展, 易于追踪错误和测试
- 结合不可变数据, 更细粒度的控制每个组件刷新状态, 提高性能
- 方便了工作交接和统一开发规范
- 为以后的项目积累经验
有什么代价
- 花费时间多
- 分层提高了理解门槛
- 并不能完全重构, 不能重构的部分风格有差异
-
何时不该重构
如果代码过于混乱,甚至根本没有办法正常运行,这个时候与其花大力气重构,倒不如重写来的快。
- 一个折中的方法是,将大的软件系统拆成多个子模块或子系统,然后分别对这些子模块或子系统进行重构或重写。
- 还有一个情况是当项目工期临近终点的时候,如果时间来不及重构应该优先保证项目进度。
- 我们常常把待重构的任务称为“技术债务”。类比现实生活中的债务,一个公司难免会有债务,而债务是要偿还的。当一个公司财务状况良好的时候,应该让自己的债务保持在一个健康的水平。但是当一个公司陷入泥潭,需要资金救急的时候,如果它手里有一笔钱,相比于还债,这笔钱更应该花在保证公司生存的事务上。
demo: https://juejin.cn/post/6844903866254049293 参考: https://juejin.cn/post/6844904114946572302
