子不语

你了解手里的锤子吗?

Consulting

hammer

一次代码评审

  在一个风和日丽的下午,团队正在进行每日代码评审。小 A 对着大屏幕上的代码说了句:“稍微停下, 我们这里是不是应该把if改写成守卫语句的方式?”。

// 示意代码
public List<String> doStuff(String input) {
    if( someCheck(input) ) {
        operation1(input);
        operation2(input);
        operation3(input);
    }   
}

  这是一个很简短的方法,方法体除去if外,只有 3 行业务逻辑,貌似的确没有重构的必要。“就一个 5 行的方法,这样修改有什么意义呢?”,小 C 疑惑的问起来。

  “这样写,未来如果再添加新的if判断,会形成if嵌套循环的时候,造成代码不好阅读,还是使用守卫语句比较好,这也是《重构》那本书里推荐的处理方法。” 小 A坚持着自己的建议。

  “但这个方法并没有嵌套呀,也不影响阅读,现在进行这个改动,不是很有价值吧”,小 C 不太不赞同这个改动。

  类似这样的对话在日常的代码评审中经常会出现,可能是在这里建议我们提取一个工具方法以方便未来使用,或者是在那里建议使用某个设计模式。但他们都有相似点,这些建议本身都没有错,而且在某些场景下是非常有必要的,只是在当下这个场景却有些不合时宜,也没有太大价值。

哪一把的锤子

   在多年的工作中,我们学习到了很多编程技巧、业界最佳实践,以及模式等,并在不经意间就凭直觉应用在每个功能中,或者作为建议输出在代码评审中。 这些动作就像我们下意识的呼吸、或者开车时踩油门和刹车一样,不用经过大脑的过多思考。但就像上面发生在上面代码评审中的一样,场景不同,一个本来正确的做法可能就变成了正确但无价值的建议。

   不同的重构技巧是在解决不同的代码坏味道,不同的架构风格是在解决不同场景下的问题。那怎么知道哪个锤子对应在哪个钉子上呢? 这就需要拨开重重表象迷雾,回归到问题的根源,也就是想马斯克一样,使用第一性原理从源头思考问题。

   以上面代码评审的为例子:如何评价一段代码的优劣呢? 我们可以遵循下面的原则:

当我们以这样的原则去审视上面的代码时,发现它的确没有重构的必要。

当我们采用某个实践、工具时,总是应该思考背后要遵循的原则,要达到的目的,以及最初的需求。

结局

   “我理解你的意思,防卫语句在解决嵌套if的场景下,的确比较有价值,能让代码更容易阅读和维护。但是在这个方法里,的确没有必要,因为方法本身比较短小,功能正确,实现也清晰明了,建议目前保存现状。如果这个方法下次被改动,并且有出现if嵌套时,再修改为防卫语句吧。” 小 C 总结道。