《重构》再版,欲购从速
March 12th, 2010
首先,不要恐慌。这不是《重构》第二版。只是由于某种愚蠢的原因,从前的那个中文版已经买不到了。现在,它换了个书皮,让需要的人能买到。仅此而已。
刘江兄写了一个 煽情的宣传 。“从一个光荣的大学辍学少年(步乔布斯、盖茨后尘?)成长为ThoughtWorks的资深咨询师,Martin Fowler的同事。”嗯,很好的阶段性总结。
(有时候我很怀疑自己做的一切是否真的有意义。如果“大家”真的会学习的话,为什么《重构》出版那么多年以后还有那么多烂代码存在──当然,如果“大家”真的会学习的话,为什么还有战争?)
时间,才是最神奇的重构工具。这句话,也很好,很隽永。
Refactoring And Design, In A Real World
September 27th, 2009
Martin Fowler在《重构》里如是说:
如果你选择重构,问题的重点就转变了。你仍然做预先设计,但是不必一定找出正确的解决方案。此刻的你只需要得到一个足够合理的解决方案就够了。你很肯定地知道,在实现这个初始解决方案的时候,你对问题的理解也会逐渐加深,你可能会察觉最佳解决方案和你当初设想的有些不同。只要有重构这项武器在手,就不成问题,因为重构让日后的修改成本不再高昂。
如果做设计的人和写程序的人不是同一帮人,如果写程序的这帮人好不容易学会了写程序然后就会被拉到另一个再也不写程序的位置上,好吧,我们还怎么使用重构这把利器?
对此,我比较悲观。
对象健身操:拒绝else
July 7th, 2009
(摘自《 ThoughtWorks文集 》,第6章,“对象健身操”)
规则2. 拒绝else关键字
每个程序员都熟知if/else结构。几乎每种语言都支持if/esle。简单的条件判断对于任何人来说都不难理解。不过大多数程序员也见识过令人眩晕的层层嵌套的条件判断,以及连绵数页的case语句。更糟糕的是,在现有的判断条件上加一个新的分支通常是非常容易的,而将它重构为一个更好的方式的想法却罕有人去提及。条件判断结构通常还是重复代码的来源。例如,状态标识经常会带来这样的问题:
public static void endMe() {
if (status == DONE) {
doSomething();
} else {
// other code
}
}
你有很多种方式重写这段代码,去掉else关键字。例如下面的代码:
public static void endMe() {
if (status == DONE) {
doSomething();
return;
}
// other code
}
public static Node head() {
if (isAdvancing()) { return first; }
else { return last; }
}
public static Node head() {
return isAdvancing() ? first : last;
}
在上面的例子中,第二段代码由于使用了三元运算符,所以代码长度从四行压缩到了一行。需要小心的是,如果过度使用“提前返回”,代码的清晰度很快会降低。《设计模式》[GHJV95]一书中关于策略模式的部分里有一个实例,演示了如何使用多态避免根据状态进行分支选择的代码。如果这种根据状态进行分支选择的代码大量地重复,就应该考虑使用策略模式了。
面向对象编程语言给我们提供了一种更为强大的工具——多态。它能够处理更为复杂的条件判断。对于简单的条件判断,我们可以使用“卫语句”和“提前返回”替换它。而基于多态的设计则更容易阅读与维护,从而可以更清晰地表达代码的内在意图。但是,程序员要做出这样的转变并不是一帆风顺的。尤其是你的代码中可能早已充斥了else。所以,作为这个练习的一部分,你是不可以使用else的。在某些场景下可以使用 Null Object 模式,它会对你有所帮助。另外还有很多工具和技术都可以帮助你甩掉else。试一试,看你能提出多少种方案来?
重构是关于行为保持的技术
December 17th, 2008
重构首先是一个形式化的过程:如果必须把代码看懂了才能重构的话,那么你就会让自己陷入一个悖论,因为最需要重构的代码你是看不懂的
William Opdyke用他的博士论文奠定了重构技术的理论基础,而这篇博士论文的核心则是对“行为保持”的研究。简言之,在这篇论文中,William用数学方法证明,在满足特定条件的情况下,以特定形式进行的程序修改将不影响程序的行为(也即“行为保持”),并且行为保持的修改之间的组合也将继续是行为保持的。
精华在第4章。
重构模式:用异步计算替代长计算
September 23rd, 2008
问题
当一个JavaScript计算进程耗时太长,浏览器会弹出警告框,不仅烦人而且一不小心就会点错导致后面的程序不被执行。
很多这类长计算是由于操作大数组造成的。虽然每个元素的处理耗时很少,当数组有几百上千个元素时整个计算时间就会长到超时。由于数组元素数不确定,对单一元素操作调优仍然不能根本解决问题。
办法
把长计算拆解成多个异步的短计算。
即使计算所需的总时间并不缩短,将阻塞的长计算拆解成异步的短计算至少带来响应性的提升:在计算进行的同时用户还可以做其他操作,而不是眼看着整个浏览器失去响应。
在拆解的基础上可以改进任务分发机制以提升整体计算时间。
步骤
- 重构原来的长计算
- 把整个长计算抽取到一个方法中
- 重构该方法使之呈现以下结构:
function longCalculation() {
before();
var items = getItems();
items.each(handleSingleItem);
after();
}
- 把循环重构为递归
- 把“操作数组中所有元素”的逻辑抽取到一个递归调用的方法,使之呈现以下结构:
function handleItems(items, cur) {
if(cur == items.length - 1) {
after();
return;
}
var item = items[cur];
handleSingleItem(item);
handleItems(items, cur + 1);
}
function longCalculation() {
before();
var items = getItems();
handleItems(items, 0);
}
- 把针对每个元素的操作变成一个异步的计算进程──这一步很简单,只要在调用handleItems方法时始终加上delay就行。
以上。应该很容易写出一个类似于library的玩意来封装这个模式。太容易了以至于我不想写。
唯一值得重复的
September 11th, 2008
重复是软件开发中最大的阻力,没有之一。
重复是邪恶的。我是说,邪恶的!
永远不要为同一份信息保存两份拷贝。
DRY 是写出良好代码的根本原则。
(如果这个世界上有一些信息值得被重复的话,就是这些。)
好的设计从哪里来
July 19th, 2008
河里的青蛙从哪里来,是从那水田向河里游来。
这样的设计调整 遇到过多少次?
基本上,每个项目都有,一年两三次吧。
下次做复杂的功能之前多做点设计吧,免得还有类似这样的调整。
好的设计真的不是做出来的。它是长出来的。
测试驱动出来的高质量的代码基础就像土壤,平时的持续集成和重构就像精耕细作。播下问题的种子,你就看着它长出来。有时候自然长出来的设计不对,于是你调整它。好的设计就在不断不断的调整当中浮现出来了。
(所以,一开始的设计是好的固然好,但更重要的是调整的能力。有些项目,好的设计会慢慢浮现出来。有些项目,好的设计也会慢慢腐化。)
可是,什么时候该忍着,什么时候才该动手调整?
不知道。不过,程序员的鼻子(和胃)知道。所以,别烦他们,别拿进度之类的玩意吓唬他们。给他们轻松,他们就会做出正确的事。
不然,反正你也没办法知道什么是正确的事。
重构?重写?
May 23rd, 2008
InfoQ: 争论:是否应该避免架构重写?
Joel认为在许多案例中做出需要重写软件的判断带有一定的主观性,其往往是由重用代码时遇到困难造成的。…即使旧的代码集就架构而言真的很糟糕,也应该努力清理代码、重构、修改接口,而不是进行全面的重写。
一种常见的担心是重构需要的成本不比重写来得小。第一,这是真的。基于一些真实的大规模重构得到的经验,重构遗留系统和重写需要的开发工作量基本上正好相等。不过第二,如果选择重构而不重写,可以确保原来的功能不被破坏。其实真实的担心往往并不是成本,而是效果:如果重构做到一半做不下去了再开始重写,那才是最坏的情况。所以真正解决这个问题需要切实可行的重构策略和手段,例如我在 这篇文章 里介绍的方法。
有很多这样的案例:面对着一堆遗留代码,人们说“那就既往不咎从头来过吧”。但事实证明从头设计一个优雅的架构于是软件就可以在将来的五年十年中保持良好的扩展性这样美好的愿望从来就没有实现过。因为,软件技术的发展是很快的,代码质量的腐化是很快的。良好的扩展性只有靠持续不断强力有效的质量保证才能做到。至于起点,重构还是重写,影响并不大──如果不介意重写的大风险的话。
在大型遗留系统基础上运作重构项目
April 4th, 2008
http://blog.csdn.net/gigix/archive/2008/04/04/2249120.aspx
本文以ThoughtWorks中国公司与客户合作的咨询项目为背景,为读者介绍如何在一个大型遗留系统的基础上组织和运作重构项目,从而切实有效地改善系统质量。eMAN是客户的一个核心业务平台。该产品采用了典型的C/S结构,负责处理大量请求和计算的后台部分采用C++开发,负责响应用户操作和处理业务逻辑的前台部分采用Java开发;此外该产品还计划在新版本中提供基于Web的前台,这部分也采用Java开发。
在ThoughtWorks为该产品的开发团队提供咨询时,eMAN产品已经发布了十多个版本,最新版本代码量超过40万行,其中15万行是Java代码。一次又一次的赶工给它留下了大量的“技术债”:系统缺乏测试,代码质量低劣,“copy & paste”的痕迹比比皆是,维护和新功能开发举步维艰。我们这个咨询项目的主要目标之一就是为这个产品找出重构的办法。
对遗留系统组织重构项目
February 25th, 2008
全文发布在CSDN:http://blog.csdn.net/gigix/archive/2008/02/25/2118896.aspx
为了保留并最大化软件资产的价值,适应新的需求变更,老系统总会面对维护和升级。当维护和升级的困难达到一定程度时,很多IT组织就会决定投入一整块资源和时间来改善这些老系统的技术质量,以便将来的维护升级能顺利进行。这样的做法通常被称为“重构项目”。根据我们的经验,很多重构项目在目标管理、任务划分和质量保证等方面存在比较严重的问题,这些问题导致重构项目不能充分发挥价值。
在重构项目的组织、管理、质量保证和实施技术等方面,ThoughtWorks具有无可比拟的能力和经验。我们曾为一些生命周期长至数年、规模大至上百万行代码的遗留系统进行过重构项目,并取得了良好的效果。
更完整的、包含实际案例的版本将在《程序员》杂志发表。




