从现在开始尝试重构

118 阅读7分钟

重构是每个研发同学都无法回避的问题,每个人都有自己关于这个话题的见解和实践经验,今天来谈谈我的看法~

为什么需要重构?

熵增定律应该很多人都听过,熵指的是体系的混乱程度,在孤立的系统内,系统从有序向无序自发的过程中,熵总是增加的。当熵在体系内达到最大时,系统就进入寂灭。比如:房子如果一直不整理打扫,就会变得又乱又脏。

同样,熵增定律也适用于研发同学维护的代码本身。随着人员的变更、产品功能的迭代代码会变得越来越臃肿,尤其是秉着“能用就行”原则(现实中很多这样的开发)堆砌起来的代码可读性、扩展性非常差,从而导致整个服务变得难以维护,甚至成为“屎山”。

图片

抗熵增的过程被称为熵减,熵减的过程其实是反人性的。比如你每周都要花时间去整理打扫房间(你可能更想打游戏刷抖音),为了提高代码的可读性、健壮性、扩展性,需要花费大量的时间去设计、重写、测试之前的代码(熵增的方式可能仅仅只是加个if)。重构的本质就是熵减,对抗人性的过程是痛苦的,但只要坚持下来,就能取得不错的收益。

调整心态,准备出发

独立思考

如果你已经开始独立思考,你就成功了一半。独立思考意味着不盲从、不偏信,而是真正的弄明白为什么要这么做。

提升执行力

任何人都有变好的意愿,但可能缺乏执行力。主要原因有内在和外在:

  • 内在无法战胜自己的懒惰心理,比如一个需求轻松的做法五分钟搞定,要想做的漂亮可能要花一小时
  • 外在就是时间问题,比如需求倒排(国内很多公司都是这样)

克服的方法自己总结了一些,有以下几点:

  • 将大目标拆解为若干小目标,降低完成难度获得及时反馈,用奖励机制去帮助自己克服惰性
  • 保持专注,我们很容易被琐碎的事搞得心力交瘁,但绝大多数的事都没那么重要。可以尝试番茄工作法,让自己在一段时间内保持专注
  • 争取合理的开发时间,一个项目或者一个需求也是可以拆分为重要紧急的核心功能和重要不紧急的核心功能,以及不重要不紧急的非核心功能。在开发时间有限的情况下,可以与产品协商进行取舍(大部分情况都是 ok 的)

持续学习优秀的案例(最佳实践)

持续学习优秀的技术架构、代码案例是你重构的前提,也决定了代码质量的上限。学习的渠道有很多,技术领域的畅销书,大厂的技术公众号,技术论坛等,别忘了独立思考。

先盘点,再行动

一次性解决所有问题的想法是不现实的,也很难申请到资源专门立项做重构(除非是非常核心的服务,代码已经腐化到严重影响业务稳定性)。此时我们可以充分利用算法思维中的“分而治之”的思想,花一些时间去做一次服务的深度盘点,根据盘点结果罗列解决对应问题投入和产出,最终根据投产比(ROI)进行排序逐一解决。这里有几个关键点:

  • 需要有一个好用的产品化的盘点系统(或流程、最佳实践等)去做统一指导,做到尽量标准化盘点报告(降低对具体人的依赖,当然复杂问题还是需要依赖人为处理)
  • 需要培养ROI思维,人的精力是有限的,需要花到刀刃上,那些投入很高但收益很低的事项可以被忽略(做雪中送炭,而不是锦上添花)
  • 应用四象限法则,把待解决问题分轻重缓急,做好目标规划,形成及时反馈

避免陷入“完美主义”陷阱

“完美主义”又可以理解为强迫症,适当的“完美主义”是可取的,但极致的完美主义可能并不适用于重构这个场景。比如为了使某一项ROI很低的指标满足所谓的“完美”而投入大量的人力,实际回报非常低。在避免陷入“完美主义”陷阱时我们要考虑以下几个问题:

  • 求同存异,不要拘泥于不影响结果的细枝末节,把关注点放到解决性能、稳定性、扩展性等问题上来。有些人可能会有强迫症,比如订单对象符合自己习惯的命名叫 OrderDTO ,看到别人写成 OrderInfoDTO 就各种受不了,一定改掉,这种就是一种强迫症表现,要避免
  • 认清自身认知的局限性。比如什么是完美?你所认为的完美一定是完美吗?会不会是因为你的认知和眼界没有达到一定程度,导致产生了误会?

可以标准化的东西,提倡公司层面拟定标准,去统一开发的编码规范,通过IDE插件、CR阻塞等手段从 DevOps 流程上约束,但这个规范一定要与时俱进,以及结合自身特点定制,而不只是照搬照抄(相信很多同学被一刀切的规范搞的焦头烂额)

重构顶层设计

重构顶层设计,就是我们是否可以通过调整架构设计来根本性解决问题。比如 MySQL 无法解决的复杂查询性能问题,是否可以通过引入 es 来解决?当然,引入新的组件一定会提升系统复杂性,且需要谨慎的处理一致性问题,但如果能大幅提升用户体验,补全阉割的产品功能直接或间接给公司带来收益,就值得投入。总结几个关键点:

  • 有时我们需要从顶层设计上去解决问题,而不是陷在原有的设计里苦苦挣扎
  • 架构设计不是一成不变的,仍然需要不断重构。软件是生长出来的,而不是一开始就设计出来的
  • 用成熟稳定的组件,生产环境避免使用未大规模验证的产品
  • 具备成本思维,尤其要发掘隐形成本。比如应用了一个新的组件,那么公司是否有这方面专家?公司是否有对应的运维能力?

风险收益平衡

重构前你一定要明白并引起重视的问题是,重构是有风险的!尤其是没有单侧覆盖的分支逻辑异常复杂代码片段,好死不死的是国内绝大多数公司的业务代码都没有单侧覆盖或者单侧覆盖率很低🙁

通常,一段代码的分支逻辑异常复杂,连成一片让人很难读懂,基本圈复杂度都会很高,是 bad code。这类代码片段的高覆盖率的单侧也是异常难写,重构这类代码一定要小心谨慎。推荐的策略是:

  • 你一定读懂了这段代码,了解每个分支逻辑、边界场景,以及引用场景和其关联的产品功能
  • 不要直接修改原代码,用新的代码灰度替换掉原代码
  • 线上流量录制回放对比返回结果(录制旧代码流量回放到重构后的代码逻辑中)
  • 线上抽样对比(抽样到的请求执行完旧逻辑同时异步线程池执行新逻辑,并对比结果)

总之,重构时需要有“敬畏之心”,复杂逻辑重构切不可操之过急。但也不用过度焦虑,用对了方法就能事半功倍,心有猛虎,细嗅蔷薇。

欢迎关注微信公众号 码农丁丁,原文链接:从现在开始尝试重构 (qq.com)