不要if else的程式設計
本文作者介紹
Michael Feathers
Michael Feathers是Object Mentor International公司的技術顧問。他的工作不僅是技術開發,他還參與對世界各地技術團隊進行培訓、指導等工作。他曾開發了將JUnit遷移到C++的CppUnit的初始部分,還有FitCpp——一個C++版的FIT基礎測試框架。他是《Working Effectively with Legacy Code》一書的作者。
條件控制是程式設計中與生俱來的一種結構,但對於我來說,除了給我帶來麻煩外,沒有發現任何的用處。一次又一次,我不斷髮現,越少的if語句,越少的switch語句,越少的迴圈,就會是越好的程式碼。通常這其中的原因是程式設計師用程式語言實現了更好的抽象歸納。他們並不是有意識的避免使用控制結構。但他們確實做到了這些。
如果是使用一種物件導向程式語言,我們可以用多型(polymorphism)來代替switch。同樣的技巧也能用在if語句上,但如果邏輯太簡單,這樣做就有點得不償失。當使用一種有函式式特徵的程式語言時,大部分的迴圈執行任務我們都可以用map,filter,fold等實現。控制結構最終從程式碼中消失,這是對程式碼大有好處的事。
條件控制結構的問題是,它很容易導致你把程式碼修改的亂七八糟。讓我們看看下面一個簡單的if語句:
if ... ... else ... end
程式碼中所有打省略號的地方都是你可以不斷新增程式碼的地方。這些地方可以訪問if外面的變數。這很容易造成高耦合。更糟糕的是,人們會習慣性的在條件控制裡巢狀條件。我見過的最糟糕的程式碼,裡面的巢狀之深的就像是噩夢裡的無底洞。我想,條件控制結構的真正問題所在是,它把各種任務混合到了一起。我相信,你能從某種角度上看出,它是和任務單一程式設計原則相沖突的。
我們該怎麼做?我們可不可以完全不要控制結構?我想不行,但我們可以做一些實驗來看看如何能減少對它們的使用。通常這樣做會讓我們從中學到一些新技巧,讓我們的程式碼更整潔。
不久前,我開發了一些Ruby程式,我需要寫一個‘take’函式,用它從一個陣列裡取出一些元素。Ruby裡有一些針對Enumerable的這樣的函式,但我需要一些特殊的功能。如果我需要的陣列的大小超出了目標陣列的大小,需要把多餘的陣列空間都置為0。
這看起來可以用簡單的if語句實現:
def padded_take ary, n if n <= ary.length ary.take(n) else ary + [0] * (n - ary.length) end end
讓我們認真的看一看這段程式碼。它沒有向我們顯示任何填充動作的資訊,沒有顯示陣列跟填充的關係。如果認真看,可以看出其中的邏輯,但我們看不出這段程式碼的意圖。
我們引入一些函式來讓這段程式碼更清楚些,使用guard語句來簡化if語句:
def padded_take ary, n return ary.take(n) unless needs_padding?(ary, n) ary + pad(ary, n) end
這個短小精悍,但不是更簡單——我們可以使用一個null物件來去掉條件語句。空的陣列就是很好的null物件。讓我們在來一次。
我們不需要用一個條件語句來計算填充的長度。這個長度我們可以取兩個陣列中的最大值,如果我們想要的長度超出了陣列的長度,填充的長度就是它們的差值:
pad_length = [0, n - ary.length].max
有了這個長度,我們可以先填充陣列,然後取出我們想要的元素:
def pad ary, n pad_length = [0, n - ary.length].max ary + [0] * pad_length end
於是,我們可以這樣定義取出動作:
def padded_take ary, n pad(ary, n).take(n) end
我們通過先進行填充從而避免了使用if語句。當然,有時候填充的是一個空陣列。
我不想去爭論這樣的寫法是否比最初的if-then-else程式碼更簡單,但現在的程式碼的意圖更清晰了,而且我不認為這種策略在這種程式碼裡使用是過度技術化。
從提取歸納的層面看,程式碼經過處理後的好處是明顯的。當遇到更復雜問題時,它帶來的益處將會更明顯。
相關文章
- 不要現場程式設計程式設計
- 不要陷入極限程式設計的陷阱程式設計
- 不要逼我結對程式設計程式設計
- 程式設計師永遠不要再犯的5個程式設計bug程式設計師
- 技術卡片 - 不要使用 else
- 不要做一個浮躁的程式設計師程式設計師
- 程式設計師,請你不要在坑程式設計師了?程式設計師
- 程式設計師,千萬不要重寫程式碼程式設計師
- 做個清醒的程式設計師之要不要做程式設計師程式設計師
- 程式設計師不要成為工具的奴隸程式設計師
- 程式設計師,你的職業不要固步自封程式設計師
- 程式設計師們,千萬不要接私活程式設計師
- 不要用物件導向程式設計分散新手程式設計師的注意力物件程式設計師
- 如何用設計模式替代if else設計模式
- 不要相信程式設計師在加班時間寫的程式碼程式設計師
- 記:那一個臭不要臉的程式設計師程式設計師
- 不要忽視Web程式設計中的小細節Web程式設計
- 不要讓其他程式設計師修補自己的BUG程式設計師
- 請不要再責怪你的程式設計師“太慢”程式設計師
- 永遠不要再犯的 5 個程式設計錯誤程式設計
- 如何讓你的程式設計師不要厭倦工作?程式設計師
- 程式設計師到底要不要接外包?程式設計師
- 程式設計師千萬不要學演算法!程式設計師演算法
- 程式設計師一定不要固步自封程式設計師
- 請不要說自己是Java程式設計師Java程式設計師
- 請不要說自己是 Java 程式設計師Java程式設計師
- 不要將Actors用於併發程式設計程式設計
- 沒搞懂背後原因,不要盲目程式設計程式設計
- 關於用設計模式代替if else的迷惑設計模式
- 程式設計師到底是幹什麼的?請不要再黑程式設計師了程式設計師
- 千萬不要相信程式設計師在加班時間寫的程式碼!程式設計師
- 幽默:不要相信 10 倍程式設計師/設計師/領導者!程式設計師
- 我為什麼不要30歲以上的程式設計師?程式設計師
- 不要讓經驗禁錮你的程式設計思維程式設計
- Java程式設計師不要錯過的7款新工具Java程式設計師
- 論跟程式設計師談話的技巧:千萬不要跟程式設計師說,你的程式碼有bug程式設計師
- 為什麼程式設計師千萬不要重寫程式碼?程式設計師
- 程式設計師為什麼千萬不要瞎努力?程式設計師