千萬不要把bool當成函式引數

發表於2011-09-08

來源:酷殼 – 陳瑋泰

我們有很多Coding Style 或 程式碼規範。但這一條可能會經常被我們所遺忘,就是我們經常會在函式的引數裡使用bool引數,這會大大地降低程式碼的可讀性。不信?我們先來看看下面的程式碼。

當你讀到下面的程式碼,你會覺得這個程式碼是什麼意思?



是不要repaint嗎?還是別的什麼意思?看了文件後,我們才知道這個引數是immediate, 也就是說,false代表不立即重畫,true程式碼立即重畫。

Windows API中也有這樣一個函式:InvalidateRect,當你看到下面的程式碼,你會覺得是什麼意思?

我們先不說InvalidateRect這個函式名取得有多糟糕,我們先說一下那個false引數?invalidate意為“讓XXX無效”,false是什麼意思?雙重否定?是肯定的意思?如果你看到這樣的程式碼,你會相當的費解的。於是,你要去看一下文件,或是InvalidateRect的函式定義,你會看到那個引數是 BOOL bErase,意思是,是否要重畫背景。

這樣的事情有很多,再看下面的程式碼,想把str中的”%USER%”替換成真實的使用者名稱:

TN/ND,那個false是什麼意思?不替換嗎?還是別的什麼意思,看了文件才知道,false程式碼大小寫不敏感的替換。

其實,如果你使用列舉變數/常量,而不是bool變數,你會讓你的程式碼更易讀,如:

如果對這個事不以為然的話,我們再來看一些別的示例,你不妨猜猜看看下面的程式碼:

這什麼玩意兒啊?看了文件你才知道,這原來是 setCentered(centered, autoUpdate);

這又是什麼啊?看了文件才知道,這是建立一個文字框,第三個引數是是否要滾動條,第四個是是否要自動換行。TN/ND。

上面的情況還不算最差,看看下面的雙重否定。

再來一個,如果你讀到下面的程式碼,相信你會和我一樣,要麼石化了,要麼凌亂了。

看完這篇文章,我希望你再也不要把bool為作為函式引數了。除非兩個原因:

  1. 你100%確認不會帶來閱讀上的問題,比如Java的 setVisible (bool).
  2. 你100%確認你想去寫出無法維護很難閱讀的程式碼。

當然,別的引數也會有一樣的問題,比如:new Textbox(300, 100, false, true);中的300 和 100,不知道是座標還是長寬,只不過,一般長度或座標這樣的引數都不會被hard code,都會有變數名,而bool這種引數經常性地被傳成true 和 false。 bool參數列現得更為明顯一些罷了。

所以,程式中不要出現magic number,true/false 也是一種 magic number。但是,我想告訴大家,從API設計的角度來說,你無法強制呼叫者用常量來取代true/false,定義成列舉型別是最好的選擇

最後,如果你想設計一個好的API,強烈推薦你讀一下Nokia的Qt的《API Design Principles》,本文就是其中的“Boolean Trap”。

 

相關文章