如何避免过早优化

Premature optimization is the root of all evils.


这是计算机科学家高德纳说过的一句话,

过早的优化是万恶之源。


我们对这句话很容易心领神会,

每当看到别人在进行自己不认同的优化之时,

就会拿这句话取笑他。


但是回到自身,作为一个有坚持有原则有追求的程序员,

又总是会有,无法遏制进行优化的时候,

因为这句话没有告诉我们,到底何时才能进行优化。


当工作落到我们自己身上时,这句话就不起作用了,

我们希望每走一步都是考虑好的,最优的,

写代码难道不应该坚持持续重构么?


其实过分的追求代码形式,也是有问题的。

下面且听我细细道来。


正确的优化

其实,避免过早优化的目的,并不是不进行优化,

也不是简单的做事优先级问题,

而是避免自己进行不正确的优化。


这里从修改代码,把代码改成自认为更好的写法来看优化。


通常项目的早期随着代码量的增加,

我们会发现一些重复的代码

能嗅出代码坏味的我们,肯定会竭力避免这样的代码出现。


于是我们会对代码进行修改,以消除重复,

做的更多的是对代码进行重新组织

我们认为这样做消除了重复代码,去除了代码坏味,一定是正确的做法了。


其实未必。

不正确的优化比过早优化更糟糕。


理论假设

一般情况下,通过对现象进行观察,

我们的大脑中会形成一种自己的认识,或者称这是一种理论假设


例如,亚里士多德观察到羽毛比铁球轻,

而羽毛比铁球落地速度慢,

于是就给出了自己的认识,较轻的物体下落速度更慢。


后来伽利略在比萨斜塔,用实验否证了这种认识。


像这种从特殊到一般的推理方式,称为归纳法

值得一提的,这种通过观察得到一般性结论的归纳法,是不可靠的,

只要有一个证据出现,就可以否认它。


因此,这种归纳法也称为不完全归纳法


在现实生活中,我们经常采用不完全归纳推理,

所以有时候发现的规律,可能是有问题的。

这时候就应该努力保持清醒,时刻更新自己的认识。


可复用是个骗局

编写出高度可复用的代码,可能是每个有理想程序员的追求,

但是,这可能是一个骗局。


因为把重复代码提取出来,在多个地方进行调用,这并不是可复用。

这只是减少了一定量的重复,并没有让公共部分变得可复用


相反,减少重复是有代价的,

它让代码之间的依赖程度增强了,变得更加脆弱


因此,到底是减少重复,还是让代码更脆弱,

应该是一个折中后的选择,

本没有不付出代价的优化选择。


那么如何做到可复用呢?


做到可复用仅仅提取公共模块是不行的,

更重要的是站在用户角度看待问题,

用户的共同需求是什么,怎样满足这类共同需求?


哪有自己代码提取的公共部分,刚好是用户的公共需求这样巧合的事情。

所以,一般我们认为可复用代码,也就只会自己用罢了。


什么时候进行优化

在项目早期,嗅到了代码坏味,立即就着手修改,

我认为这样的优化可能是不正确的

因为这时候代码量还很少,我们对这些代码所反映出来的规律没有清晰的认识。


如果某些现象只出现一次两次,我们就认为它具有一般性,

这样的认识就很容易产生偏差。


更好的做法是,让代码总是能保持一定的冗余,

以正确反映出重复代码接下来的演化路径,

耐心的找出规律。


经验表明,代码库中出现两次的情况非常之多,

但是出现三次以上的重复代码就会很罕见了。


通过对现有的代码库进行分析,我们还发现,

真正重复的代码,反而会出现几百次以上却无人问津。


大部分人在出现两次的时候就进行了优化,

而导致这些提取出去的公共部分,只有这两个场景中会用到。

这两个场景于是就互相制约,稍有不同,就造成了过度设计


代码的真实演变路径

一个效率比较高的办法是,在一个功能完成之后,再着手对代码进行重组,

这时候可以对一些关键点增加一些注释

也可以编写一些文档,以便与该功能相关的一些知识,可以留存下来。


即,先完成功能,再着手进行优化。


编写一段真正重复的代码,并不会浪费多少时间,

维护这样的代码耗费时间。


在现有的项目中,在功能的开发阶段,一般是由同一个人来完成的,

整个功能也不会超过一周就会完成,

因此,提前优化,可能会导致代码被频繁修改,也无法避免最终交付前的那次修改。


我们需要提高交付质量,而不必时刻保持桌面干净。


结语

在一线开发这些年,我曾有不止一次的,在研发阶段频繁的修改代码

我希望它能时刻的保持整洁,没有任何代码坏味,

这曾经消耗了我大量宝贵的开发时间。


后来我幡然醒悟了,

避免过早优化,实际上是避免进行不正确的优化,

而不是不要优化。


进行了不正确的优化,并非先做了优先级较低的任务,

而是做了一件错事


频繁的修改代码,正是不断返工的写照。


因此,在面对脏乱差的代码库,忍不住要动手收拾的时候,

不妨先问自己一句,我这样的整理方式对么


毕竟,向不正确的方向越努力,就会离正确的目标越远。


如果你太在乎别人的评价,就没办法坚持做正确的事情。


参考

Premature Optimization