专栏:代码之丑(四)——代码找茬游戏

  • 郑晔

2010 年 11 月 25 日

话题:Java.NETRuby架构语言 & 开发文化 & 方法

这是一个找茬的游戏,下面三段代码的差别在哪:

if (1 == insertFlag) {
    retList.insert(i, newCatalog);
  } else {
    retList.add(newCatalog);
  }
if (1 == insertFlag) {
    retList.insert(m, newCatalog);
  } else {
    retList.add(newCatalog);
  }
if (1 == insertFlag) {
    retList.insert(j, newPrivNode);
  } else {
    retList.add(newPrivNode);
  }

答案时间:除了用到变量之外,完全相同。我想说的是,这是我从一个文件的一次 diff 中看到的。

不妨设想一下修改这些代码时的情形:费尽九牛二虎之力,我终于找到该在哪改动代码,然后改了。作为一个有职业操守的程序员,我知道别的地方也需要类似的修改。 于是,趁人不备,把刚做修改拷贝了一份,放到另外需要修改的地方。修改了几个变量,编译通过了。世界应该就此清净,至少问题解决了。

好吧!虽然这个程序员有职业操守的程序员,却缺少了些职业技能,至少在挥舞着“拷贝粘贴”的锤子时,他没有嗅到散发出的臭味。

只要意识到坏味道,修改是件很容易的事,提出一个新函数即可:

void AddNode(List& retList, int insertFlag, int pos, Node& node) {
    if (1 == insertFlag)    {
      retList.insert(pos, Node);
    } else {
      retList.add(node);
    }
  }

于是,原来那三段代码变成了三个调用:

AddNode(retList, insertFlag, i, newCatalog);
AddNode(retList, insertFlag, m, newCatalog);
AddNode(retList, insertFlag, j, newPrivNode);

当然,这种修改只是一个局部的微调,如果有更多的上下文信息,我们可以做得更好。

重复,是最为常见的坏味道。上面这种重复实际上是非常容易发现的,也是很容易修改。但所有这一切的前提是,发现坏味道。长时间生活在这种代码里面,我们会对坏味道失去嗅觉。更可怕的是,一个初来乍到的嗅觉尚灵敏的人意识到这个问题,那些失去嗅觉的人却告诫他,别乱动,这挺好。

趁嗅觉尚在,请坚持代码正义。

作者简介:

郑晔,ThoughtWorks 公司咨询师,拥有多年企业级软件开发经验,热衷于探索各种程序设计语言在真实软件开发中所能发挥的威力,致力于探寻合理的软件开发方式,加入 ThoughtWorks 公司后,投入到敏捷开发方法的实践之中,为其他公司提供敏捷开发方法方面的咨询服务。他的 blog 是梦想风暴

查看原文:代码之丑(四)

Java.NETRuby架构语言 & 开发文化 & 方法