• Feeds

  • 程序员修炼之道-DRY与巧合编程

    DRY(Don’t Repeat Yourself)是架构设计中经常用到的一句话,这一原则应用非常广泛,在程序设计中同样会用到,不少代码或许不知不觉中违反了这一定义,如《程序员修炼之道》一书中就有如下一题,重构下面一段代码

    if (state == TEXAS) {
            rate = TX_RATE;
            amt = base * TX_RATE;
            calc = 2 * basis(amt) + extra(amt) * 1.05;
    } else if ((state == OHIO || (state == MAINE)) {
            rate = ((state == OHIO) ? OH_RATE : ME_RATE);
            amt = base * rate;
            calc = 2 * basis(amt) + extra(amt) * 1.05;
            if (state == OHIO)
                    points = 2;
    } else {
            rate = 1;
            amt = base;
            calc = 2 * basis(amt) + extra(amt) * 1.05;
    }

    可能很多人读此代码都有似曾相识之感,不错,我们身边不少程序员就是如此编程的。这段代码就是由于太多Repeat造成罗嗦难懂,结构复杂,维护困难。大家可能都会迅速想到两点重构方法
    1. amt, calc 可以移出来
    2. 第2个if可以拆分

    但是这样就完美了吗?4个if/else是否让人闻到一股不对劲的气味?这段程序是否还是传统结构化编程思维?if条件中state再增多程序会怎样?因此虽然是一段很短的代码,但是重构优化实际是无止境的。

    再谈巧合编程(Don’t Programmer by Coincidence),在很多项目中其实也很常见,巧合编程就是有问题的代码在开发过程中恰好能运行通过,但是运行在别的环境很容易就出问题,比如下面的C++代码

            a = 2;
            b = 3;
            if (a + b != 5) exit(1);

    什么情况会exit(1)?

    传统智慧认为,项目一旦进入编码阶段,工作主要就是机械的把设计转换成可执行语句。这种态度是许多程序低效、不可维护的最大原因。

    我们大多数人都能够几乎自动地驾驶汽车,我们不用明确的命令我们的脚踩刹车,或是命令手动方向盘,我们只是想“减速并右转”。但是,可靠的司机会不断查看周围的情况,检查潜在的问题,并且让自己在万一发生意外时处在有利的位置上。编码也是这样。

    因此开发过程质量问题非常重要, 有经验的程序员懂得如何避开前进过程中的各种雷区。Code review就是在你的驾驶过程中,由另外一名有经验的驾驶员坐在副驾的座位上,帮你纠正各种危险的驾驶习惯,避免在当时或以后踏入各种已知的雷区。

    本文读后感已先前在新浪微博发出,收到过几十条转发及评论。微博的内容或许更有灵感并及时,欢迎关注http://t.sina.com.cn/timyang

    如想及时阅读Tim Yang的文章,可通过页面右上方扫码订阅最新更新。

    « | »

    9 Comments  »

    1. 魏中华

      >>可能很多人读此代码都有似曾相识之感,不错,我们身边不少程序员就是如此编程的。这段代码就是由于太多Repeat造成罗嗦难懂,结构复杂,维护困难。

      记得早年刚入门的时候,我也觉得这种写法“罗嗦难懂,结构复杂,维护困难”,对书中精巧,和看似简洁的实现,非常崇拜。

      以现在的眼光来看,这段代码的逻辑还算清晰,并不难懂,无明显缺陷。

      现在最怕的是,在这种代码出现的地方,大肆用上”重构大法“和”面向对象大法“,折腾死人不偿命。

      如果有那点功夫,有那点时间,出现问题时,随手重写一个就好了。

    2. Dan

      其实自己在编码过程中也知道去使用DRY原则,但是由于以前的代码本身缺乏OO的特性,里面有太多偶尔,需要使用到以前的部分代码的时候,就需要把以前代码重构,降低耦合度,才能提炼出来重用。往往在项目忙的时候,这些事情是没人做的,因为要用的代码可能是别人写的,自己都没看太明白,重构的过程往往有可能引入新的bug,就导致Repeat的代码出现了。
      请问Tim,重构应该在什么情况下或者哪个时间段进行呢?

    3. Tim

      重构应该没有明确时间限制何时进行,发现不合理之处就可重构。

    4. gakaki

      同样建议读读 重构ruby版和 rob大叔的clean code

    5. mysoko

      Martin Fowler的 重构——改善既有代码的设计
      必须的

    6. 我们要打破传统化结构思维,具体问题具体分析了

    7. 我有点看不懂,但是我知道这一定的篇好文章,有那么多人认同。

    8. 上面那个a+b的例子应该是数据类型的问题吧?如果是字符串类型就exit(1)了。

      开发真是辛苦啊

    9. Lhuna

      I really appreciate your dedication to teaching others. contact us

    Leave a Comment