天天看點

【轉】Bad Smell重構和設計的标準

原文網址: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的時候再重構吧!我們将改變這個世界,也許有一天我也會成為人人景仰的英雄,大師。成為萬千程式員的偶像!

“與其無盡的等待完美的設計,不如立刻着手實作可行的設計,然後再在設計出現臭味的時候重構實作!”

-----------------------------------

很值得思考的一篇文章,開發中我總是去想更好的結構和設計,是以浪費了時間和精力。

為什麼不等代碼的臭味來了再重構呢?

-----------------------------