论坛首页 入门技术论坛

【转】Bad Smell重构和设计的标准

浏览 10941 次
该帖已经被评为新手帖
作者 正文
   发表时间:2006-10-28  
原文网址:http://blog.csdn.net/shendl/archive/2005/10/19/509556.aspx


-------“与其无尽的等待完美的设计,不如立刻着手实现可行的设计,然后再在设计出现臭味的时候重构实现!”



引言


今天,一位初学编程的朋友对我说,他写的类要么是数据类,要么是操作类。似乎写得不太好。于是,我看了他写的代码。他的类虽然编得不怎么样,但是放在他的小项目中,并没有发出多浓的bad smell。所以,我告诉他,他的类写得不错,并无不妥。

在回家的路上,我回想起这个他的这个问题,觉得有必要好好探讨一番,遂作此文。



正文



以前有一位朋友,让我给他的代码排错,我打开他发过来的代码,一股浓烈的臭味扑面而来----他居然使用中文作为变量和方法、类的名字!

我差点被这个臭味熏死!我问他,怎么可以使用中文作为变量名。他说,java用中文作变量名没问题的,是他的老师告诉他们这样子做的。

天呢!看来又是一个拿到毕业证书又立刻回到课堂教书的家伙!真是误人子弟呀!



Kent beck用bad smell来表示重构的适当时机,真是一语道破真谛!

Bad smell是代码好与不好的最天然的分界线!

一、        bad smell与代码的优劣

食品有做得好不好之分。其中一个重要的指标就是保质期。好的食品,保质期就长,坏的食品保质期就短。

对于代码来说也一样。也有一个保质能力的问题。好的代码,入口芬芳。坏的代码早早就变质了,而且随着时间的推移越来越臭,直到最后,我们只好把它扔掉----虽然它也曾经是我们花钱买来的。

对于食品来说,当然是保质期越久的食品越好。而对于代码也一样,我们都希望自己的代码持久芬芳。但是,保质期久的食品,制造成本自然会增加,而也许我们只需要这袋食品保质7天就成了,而保质1年对于生产来说实在是太大的浪费。同样,如果我们的代码只要保质3个月就可以了,我们如果执着的提高质量,让它可以保质3年,也是浪费了Money。

二、

这个世界上又终极完美的东西吗?没有,绝对没有!

以前,我们的数学、物理,还有哲学,逻辑学等等,总是追求完美的公式演绎,精确的度量,“最科学的…人类社会的最高阶段…”,最佳决策等等。

但是,追求完美的结果却总是惨痛的失败!、

“上帝不会让人类看穿整个世界”!

今天,已经有很多学者明白了这个道理。

“与其无尽的等待完美的设计,不如立刻着手实现可行的设计,然后再在设计出现臭味的时候重构实现!”

数学中出现了模糊数学。虽然我们无法精确的知道到底是多少,但是我们知道它会在什么之间。也就是说,我们知道“香well-smell和臭bad-smell”之间的分界。这就足够了!

物理学家们也明白了粒子测不准原理。这个世界上有很多东西是绝对随机的。也明白了夸克的内部我们永远无法认识。因为打碎夸克所需的力量大于整个宇宙的能量之和。“君子有所为,有所不为”!不要去做得不偿失的事情!“追求完美”就像是夸父追日,愚不可及!

“少谈点主义,多干点实事”胡适语。哲学家们业务实起来了。邓公的“实事求是”把中国人从哲学的虚妄追求(实际是空想)中解脱了出来。20多年里,抛弃理想(实际是空想)的中国人富了起来!中国人上天了!

逻辑学以前研究最佳决策。此外,管理学,军事指挥学等等的教授们也钻研与此。但是,今天,这些社会科学家们也明白了“完美是虚妄的”这个道理。现在MBA,工程硕士,工程博士,案例教学这些实际的东西大行其道。逻辑学现在也转而研究“较优决策”。



好了,说了这么多,似乎有些跑题了。以上这些其它专业的科学的发展经历,都无一例外的证明了“完美的虚妄”。我们做任何事情,都要有“先干起来再说的精神”。“瞻前顾后”“唯唯诺诺”者必将一事无成。

“与其无尽的等待完美的设计,不如立刻着手实现可行的设计,然后再在设计出现臭味的时候重构实现!”

比如说,我们接到一个项目,我们经过思考,获得了一个可行的设计方案,然后着手实现。此时,可能有一个小功能。我们是使用GOF23个设计模式,用n个类实现呢,还是立刻用10来行代码解决呢?我们应该选择“可到达目标的简单方案”。这是XP方法的一大原则。现在,这一段代码散发着well-smell。

过了几天,我们又增加几项功能。再看到这段代码时,它已经散发出bad smell了。

也许是因为,我们的代码大大增加了,一段语意含混不清的代码,让阅读者头晕。也许是因为,出现了大量代码的重复,或者是我们这一段不太“香”的代码被很多代码所调用。



为什么同一段代码,一会儿挺香的,不需要改进;一会儿又很臭,急需重构呢?答案是Context上下文,或者说是“环境”。



还记得以前学习语文和英语的时候,最强调的就是“语境”了。同样一句话,放在名著里,就是经典,放在我们的作文里就是败笔。

其实,代码的好坏,和语文的语言的好坏是最最类似的。一个软件就和一篇文章一样。

1,            软件的语言,用的是编程语言,有着特殊的语法;

而一般的文章,用的是汉语、英语、法语等等。

2,            软件的读者是程序员,他们学会了编程语言,如java;

文章的读者也一样是人,他们会文章的语言,如中文。

当然,也有不同。软件除了人可以看之外,还可以被编译器执行;

而我们一般的文章就不行了。

但是,软件实现的好坏,bad smell,well smell的判断者是人,而不是编译器。Well smell的代码常常比bad smell的代码更加低效。

因为,在软件的两个读者中,程序员是远远比编译器重要的读者。因为程序员的小时薪可是比电脑每小时运行的费用贵多了!

如果,建筑图纸是清晰的,那么工程师们建造房子,修改房子就容易多了。如果建筑图纸杂乱无章,那么新来的工程师要开展工作就需要更多时间的学习。对于通常是很复杂的软件来说,也许理解代码的工作量会大的不如重新编写代码!

软件代码,就如一篇说明文。

如果这篇说明文简单易懂,那么这篇文章就是散发着“诱人芬芳”的文章。

如果这篇说明文晦涩难懂,那么这篇文章就是散发着“恶臭”的文章。



同样的代码放在这篇软件里,它散发着“诱人芬芳”;放在另一篇软件里,它散发着“恶臭”。

因为,对于不同规模的软件,对于不同复杂度的软件,“简单易懂”是一个不同等级的要求。

对于大规模,高复杂度的软件。“简单易懂”意味着精巧的设计和实现。

而对于简单的软件,“简单易懂”意味着直白的,教科书式的实现即可。

当我们的软件逐渐向大规模,高复杂度进化的时候,我们的代码段也需要进化。进化成精巧的设计----面向接口编程,OOP的高级原则,设计模式,面向方面等都可能会用上。



所以,对于一个有经验的程序员来说,我们尽管率性而为,设计和实现软件。我们的决定往往是比较正确的。当我们看不顺眼某一段代码的时候,闻到令我很不爽的Bad Smell的时候,那么,我就会操起刀,给它们开一刀,令它们重新“简单易懂”。

Bad Smell,看不惯,看不懂,不清楚,不简洁,总之,不管怎么说,就是令我很不爽的时候,我就要重构它,或者重新设计它。

那么,我们重构的目标在哪里呢?OOP的一些高级原则怎么样?面向接口编程怎么样?GOF的23个设计模式用用的话会不会好一些呢?面向方面编程AOP,分离横切关注点怎么样?等等这些好的原理、技术都可能是我们重构的方向。或者,仅仅是Martin Fowler的那些个“重构手法”就管用了!





n        结语



“我不是什么伟大的程序员,我只是一个有着很多好习惯的程序员”Kent Beck语。这句话至今记忆犹新!这个世界上有很多伟大的程序员,但我只佩服那些“有着很多好习惯的程序员”!因为,我是一个只崇拜技术的程序员。我只崇拜那些编程高手,而所谓的编程高手就是那些“有着很多好习惯的程序员”。



我也明白高手之道,但我却一直没有养成高手的习惯。所以至今还是一个平凡的程序员,伟大的理想迟迟不能实施。当我闻到浓烈的“bad smell”的时候,我常常未能像Martin Fowle那样去重构,因为节点就在眼前!


希望这篇文章能够让你明白我们应该怎样编写程序,何时重构,何时重新设计。希望你也能养成kent beck那样的好习惯。

曾经,我也追逐完美,渴望卓越,渴望一步登天,一举成为顶尖高手。但这一切都是空想,都是“水中望月”。就算强悍如Rod Johnson,Kent beck等人,也仍在学习,仍在重构自己的代码,写出的代码,编出的软件也仍在被人批评!

“千里之行,始于足下”,让我们这些菜鸟开始编程吧!当我们闻到bad smell的时候再重构吧!我们将改变这个世界,也许有一天我也会成为人人景仰的英雄,大师。成为万千程序员的偶像!

“与其无尽的等待完美的设计,不如立刻着手实现可行的设计,然后再在设计出现臭味的时候重构实现!”

-----------------------------------
很值得思考的一篇文章,开发中我总是去想更好的结构和设计,因此浪费了时间和精力。
为什么不等代码的臭味来了再重构呢?
-----------------------------
   发表时间:2006-10-28  
这样的善于思考的人不愁不成为软件开发的中坚。 

不过:

Bad smell,Bad smell,Bad smell,Bad smell.

Good smell,Good smell,Good smell,Good smell.

不知道Good Smell为何物,再谈Bad Smell也多是纸上谈兵。

这些东西多半是靠经验积累的,多看看好的代码,多写写坏的代码也无妨, 重要的 是“做之后的想” 。

0 请登录后投票
   发表时间:2006-10-28  
bad smell的标准?是不是做的项目的类型和问题域是什么决定什么样才是bad smell?
0 请登录后投票
   发表时间:2006-10-29  
phpxer 写道


食品有做得好不好之分。其中一个重要的指标就是保质期。好的食品,保质期就长,坏的食品保质期就短。

对于代码来说也一样。也有一个保质能力的问题。好的代码,入口芬芳。坏的代码早早就变质了,而且随着时间的推移越来越臭,直到最后,我们只好把它扔掉----虽然它也曾经是我们花钱买来的。

对于食品来说,当然是保质期越久的食品越好。而对于代码也一样,我们都希望自己的代码持久芬芳。但是,保质期久的食品,制造成本自然会增加,而也许我们只需要这袋食品保质7天就成了,而保质1年对于生产来说实在是太大的浪费。同样,如果我们的代码只要保质3个月就可以了,我们如果执着的提高质量,让它可以保质3年,也是浪费了Money。


食品做得好不好,凭借保质期来判断当然是错误的,酸奶的保质期就很短暂,难道能说酸奶这种食物就不好吗?

现在很多判断代码的bad smell大多都是依靠感觉,只有不断的积累才能总结出一些经验作为判断bad smell的标准。如同设计模式一般,也是在实际操作过程中才能积累出来的。
0 请登录后投票
   发表时间:2006-10-29  
这段时间,我主动邀请同事阅读代码,如果他觉得容易读懂,那就说明味道好,如果他读的过程有疑问,那么就有一些不好的味道。简直跟白居易写诗一样了。
0 请登录后投票
   发表时间:2006-10-30  
有一点就是,如果我的同事基本上不清楚 设计模式的话,可能不容易读懂 我的代码。我碰到过这样的情况。
其实我用 一个模式名称就可以表达的话,但是我的同事她并不明白其中的含义,所以代码变得难懂的情况,并因此而对我的代码产生抱怨---难懂。 另外,我的代码经过多次重构以后,大约9000行的样子。

大家有没有碰到这种情况?我是个新兵,所以没得说,照着改呗。。。。
0 请登录后投票
   发表时间:2006-10-30  
phpxer 写道
有一点就是,如果我的同事基本上不清楚 设计模式的话,可能不容易读懂 我的代码。我碰到过这样的情况。
其实我用 一个模式名称就可以表达的话,但是我的同事她并不明白其中的含义,所以代码变得难懂的情况,并因此而对我的代码产生抱怨---难懂。 另外,我的代码经过多次重构以后,大约9000行的样子。

大家有没有碰到这种情况?我是个新兵,所以没得说,照着改呗。。。。


注释多点会对代码的可看性提高很多
有时要找那种有OO习惯的人看你的代码
而不是死硬的过程者

PS:你是新人所以写9000行代码的理由么?(我只限于写过5000行的sql)
0 请登录后投票
   发表时间:2006-10-30  
引用
PS:你是新人所以写9000行代码的理由么?(我只限于写过5000行的sql)


我的意思是说,给她看的那个程序,9000行代码的样子,不是很大,但是被抱怨。

因为我是新人,所以按照他们的意思改。通常而言,他们可能更有经验,而且,这是尊重同事的必要。
0 请登录后投票
   发表时间:2006-10-30  
居然精华了。
0 请登录后投票
   发表时间:2006-10-30  
这个帖子的被隐藏然后又被精华,觉得会有两个效果:
1. 就帖子内容而言,一篇绝大部分在无病呻吟的重复真理的酸文,在一个技术板块被评为精华,这个舆论导向最终会使javaeye逐渐csdn化。
2. 就帖子性质而言。一篇全文转贴的文章被隐藏后旋被质疑http://www.iteye.com/topic/31101,而后又奇迹般的取消隐藏而最终成为精华。能够做的判断,要么是技术故障导致,要么是管理团队在提倡全文转贴这类做法. 但这显然是极其危险的。一方面会导致大量全文转贴现象的出现(毕竟网上真正的好文不计其数),另一方面会出现微妙的发布权问题.
hehe.拭目以待巴
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics