每篇一名言:
宇宙的熵趋向一个最大值。
——鲁道夫·克劳修斯(德国数学家)
前言
大部分软件开发者都有这样的体会,一套代码本来是简洁而清晰的,可是如果没有专人审视代码质量,经过多位开发者无数次的修改以及交接以后,代码变得越来越难理解,以至于最后几乎无法正常维护了。这究竟是为什么呢?
熵增定律告诉我们,孤立系统总是趋向于熵增,最终达到熵的最大状态,也就是系统的最混乱无序状态。
那么代码质量是怎样变得越来越差的呢?本篇尝试从逆向选择的角度分析代码质量衰退的原因。
1. 逆向选择
逆向选择是金融学中的概念,指由交易双方信息不对称和市场价格下降产生的劣质品驱逐优质品,进而出现市场交易产品平均质量下降的现象。这个概念由乔治·阿克劳夫在他的论文《柠檬市场:质量不确定性和市场机制》中首次提出。“在旧车市场,卖者知道车的真实质量,而买者不知道。这样卖者就会以次充好,买者也不傻,尽管他们不能了解旧车的真实质量,只知道车的平均质量,愿平均质量出中等价格,这样一来,那些高于中等价的上等旧车就可能会退出市场。接下来的演绎是,由于上等车退出市场,买者会继续降低估价,次上等车会退出市场;演绎的最后结果是:市场上成了破烂车的展览馆,极端的情况一辆车都不成交。”(引号内容来自百度)
逆向选择本质上是由于信息不对称而导致的整体平均质量下降的现象。
2.软件协作开发中的逆向选择
开发者风格
我们姑且将开发者分为三种类型:
谨慎型:注重代码优雅,考虑周密,修改风格谨慎;
普通型:没有特别倾向,容易受别人的代码风格影响;
鲁莽型:注重开发速度,易投机,修改风格大胆;
逆向选择的过程
在软件协作开发过程中,同样存在信息不对称的问题。每一个开发者提交的代码质量和代码意图,其他开发者无法完全掌握。因而开发者容易采取投机的方式来写代码,以牺牲代码质量为代价换取开发速度。随着劣质代码增多,在开发者中出现了行为分化。
谨慎型:由于代码可读性健壮性等变差,谨慎型开发者变得保守,不愿或减少在劣质代码上的提交。
普通型:看到其他人写代码投机,自己也放松了要求。
鲁莽型:更多的投机。
随着劣质代码进一步增多,影响了开发效率。谨慎的开发者因无法再适应这种开发环境而选择退出(转到其他产品或其他模块);普通型开发者为了赶上软件进度,只能也用投机的方式写代码,因为只有这样才有“效率”。于是剩下的所有开发者都变成了鲁莽型。
在第三阶段,代码质量变得更差,以至于只能看懂自己写的代码,别人写的代码很难理解了。这个阶段的特征是:鄙视前任写的代码太糟糕,抱怨合作的开发者,代码中多处“temp fix”,“attention”字样。
直到最后有一天,某个开发者发现看不懂自己之前写的代码了,需要仔细研究自己的代码。至此宣告代码质量严重衰退。
一个简单例子:magic number
点击后刷新菜单:
boolean onClick{
...
menu.refresh();
return true;
}
因为菜单4出现显示不全,或者菜单4有特别的显示需求?某位开发者“直接修改”:
boolean onClick{
if(3 == menu.getIndex()){
specificRefreshMenu4();
}else{
menu.refresh();;
}
return true;
}
之后另一位开发者虽然不明白菜单4有何特别,但有样学样:
boolean onClick{
if(3 == menu.getIndex()){
if(menu.getData().equals("abc")){
setFontColor(menu.getString(),0xFFFFFFFF);
}else{
specificRefreshMenu4();
}
}else{
if(menu.getData().equals("abc")){
setFontColor(menu.getString(),0x687968FF);
}else{
menu.refresh();
}
}
return true;
}
随着类似的修改不断增加,代码越发难以阅读。