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
>>可能很多人读此代码都有似曾相识之感,不错,我们身边不少程序员就是如此编程的。这段代码就是由于太多Repeat造成罗嗦难懂,结构复杂,维护困难。
记得早年刚入门的时候,我也觉得这种写法“罗嗦难懂,结构复杂,维护困难”,对书中精巧,和看似简洁的实现,非常崇拜。
以现在的眼光来看,这段代码的逻辑还算清晰,并不难懂,无明显缺陷。
现在最怕的是,在这种代码出现的地方,大肆用上”重构大法“和”面向对象大法“,折腾死人不偿命。
如果有那点功夫,有那点时间,出现问题时,随手重写一个就好了。
其实自己在编码过程中也知道去使用DRY原则,但是由于以前的代码本身缺乏OO的特性,里面有太多偶尔,需要使用到以前的部分代码的时候,就需要把以前代码重构,降低耦合度,才能提炼出来重用。往往在项目忙的时候,这些事情是没人做的,因为要用的代码可能是别人写的,自己都没看太明白,重构的过程往往有可能引入新的bug,就导致Repeat的代码出现了。
请问Tim,重构应该在什么情况下或者哪个时间段进行呢?
重构应该没有明确时间限制何时进行,发现不合理之处就可重构。
同样建议读读 重构ruby版和 rob大叔的clean code
Martin Fowler的 重构——改善既有代码的设计
必须的
我们要打破传统化结构思维,具体问题具体分析了
我有点看不懂,但是我知道这一定的篇好文章,有那么多人认同。
上面那个a+b的例子应该是数据类型的问题吧?如果是字符串类型就exit(1)了。
开发真是辛苦啊
I really appreciate your dedication to teaching others. contact us