软件设计和软件实践的方法都是有成本的,在很多技术实践都需要做的情况下,如何对局势和形势作出一个判断和把握,找到恰当的时机进行重构,从而获得较佳的性价比呢?老乐尝试对这个问题给出一些建议。
重构系列谈(一)重构时机的把握
重构是一种在不改变软件系统外在行为的前提下,优化代码内部质量的方法,使得代码易于复用、易于理解、减少冗余,从而使软件实现的复杂度逼近于软件要解决问题的复杂度,降低理解和维护成本。
重构的时机一般从以下两个角度考虑:
1、 缺失 clean code
软件是对业务逻辑的一种表述,代码中的变量、类型、函数等所有代码元素都应该能够显式的、合理的表达业务逻辑,代码中如果出现了晦涩的命名、无序的排版、超高的圈复杂度、高低不平的语义(概要和细节不合理的同时存在,代码应该像英文的文章一样,按topic、brief、detail逐步展开,而不是三者无序混合杂乱,造成粗细粒度的语句杂乱无章的堆砌)、以及常提的22种坏味道等,这些都是要进行clean code层级的重构,增加代码的可理解性,降低维护成本。
2、 需求变化方向变化
在新的需求变化方向出现时,这里请大家注意,需求 变化 和需求 变化方向的变化 是不同的两个概念,举个例子,一个度量系统,刚开始支持英制单位的 feet、inch, 后来需求变了,还要支持yard,mile,这就是需求发生了变更,但需求变化方向没有变更;如果新需求要求增加公制单位的cm、mm、m等,这就是需求变化方向发生了变化。
当需求变化方向发生变化时,就会导致系统原来的架构与新需求变化方向不匹配,这时候如果不能及时重构系统架构,开发人员往往通过大锤 +铁钉
( if else套if else等)的方式,强行把新功能加上去,副作用就是功能正常了,但这些功能的代码出现在不该出现的位置上,久而久之系统架构就会被需求方向变化冲击的七零八落,造成系统的逐步腐化,形成一团乱麻。
但是这里又面临了一个新的问题,那就是对于预测到需求方向要不要做架构(OCP)上的应对呢?如果提前应对了,需求没有往这个方向变化,或者的确变化了,但变化的角度不同了,这不造成了过度设计了吗?
所谓的架构应对一般是指对OCP(开闭原则)的应用,把稳定部分和变化部分相分离,稳定部分复用,变化部分通过扩展来实现。
其实,提前预测需求变化方向并做架构(OCP)上的应对,是会在未来需求变化时带来一些收益,但是我们往往发现,我们预测的变化往往很长时间都不变化,或者即使变化,变化的角度也和之前的预先设计不同,原来的设计还是要做大的调整,反而往往增加了重构的复杂度。这样总体看,提前设计往往都带来更多的浪费。
不做预先设计,往往在需求方向真的变化的时候,会损失一点收益,但是如果我们具备很好的重构的意识和架构能力,加上由于前面没有过多设计的羁縻,能够快速适应需求的变化,反而更快更有效,成本更低。
如何均衡设计和需求方向的变化呢?这里老乐推荐 0/1/N原则。
如果预测到需求变化的方向,但是这时候需求还没有真正发生,这时候就是 0,除非实现已有需求的时候顺带能够实现一些未来需求,比如有个核心业务数据类型目前是int,未来有可能演变为double,那现在是否要使用double处理呢?
答案是 no,double的处理比int复杂的多,而且这个需求变化什么时候来还是未知的,这时候除了通过typedef int TYPE来稍微应对下未来,因为这个数据类型可能要暴露给用户,其他都要按照int处理,这就是 0 。
如果需求变化方向出现了第一次,这时候不要做过多的 架构( OCP) 设计,仅仅一般实现就可以了,这个需求变化方向还不明显,因此过多的架构一定会带来理解性和维护性的成本,这就是 1。
如果需求在这个方向上变化了第二次,这个时候就不能仅仅实现一个 2, 而应该做架构( OCP)设计,使这个设计能够应对2,3,4...N,能够应对这个需求变化方向上所有的变化。因为这个时候需求方向已经明确,后续变化概率会较大,而且已经有两次变化了,此时做架构(OCP)去应对是值得的了, 这就是 N。
以上是一些老乐重构中常用的思路,希望能够给大家一些借鉴。土鳖扛铁牛(待续)
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。