原文地址 http://coolshell.cn/articles/5444.html
作者 陳皓
我們有很多Coding Style 或 代碼規範。但這一條可能會經常被我們所遺忘,就是我們經常會在函數的參數裏使用bool參數,這會大大地降低代碼的可讀性。不信?我們先來看看下面的代碼。
當你讀到下面的代碼,你會覺得這個代碼是什麼意思?
|
widget->repaint( false ); |
是不要repaint嗎?還是別的什麼意思?看了文檔後,我們才知道這個參數是immediate, 也就是說,false代表不立即重畫,true代碼立即重畫。
Windows API中也有這樣一個函數:InvalidateRect,當你看到下面的代碼,你會覺得是什麼意思?
|
InvalidateRect(hwnd, lpRect, false ); |
我們先不說InvalidateRect這個函數名取得有多糟糕,我們先說一下那個false參數?invalidate意爲“讓XXX無效”,false是什麼意思?雙重否定?是肯定的意思?如果你看到這樣的代碼,你會相當的費解的。於是,你要去看一下文檔,或是InvalidateRect的函數定義,你會看到那個參數是BOOL bErase,意思是,是否要重畫背景。
這樣的事情有很多,再看下面的代碼,想把str中的”%USER%”替換成真實的用戶名:
|
str.replace( "%USER%" , user, false ); //
Qt 3 |
TNND,那個false是什麼意思?不替換嗎?還是別的什麼意思,看了文檔才知道,false代碼大小寫不敏感的替換。
其實,如果你使用枚舉變量/常量,而不是bool變量,你會讓你的代碼更易讀,如:
|
widget->repaint(PAINT::immediate); widget->repaint(PAINT::deffer);
InvalidateRect(hwnd, lpRect, !RepantBackground);
str.replace( "%USER%" , user, Qt::CaseInsensitive); // Qt 4 |
如果對這個事不以爲然的話,我們再來看一些別的示例,你不妨猜猜看看下面的代碼:
|
component.setCentered( true , false ); |
這什麼玩意兒啊?看了文檔你才知道,這原來是 setCentered(centered, autoUpdate);
|
new
Textbox(300, 100, false , true ); |
這又是什麼啊?看了文檔才知道,這是創建一個文本框,第三個參數是是否要滾動條,第四個是是否要自動換行。TNND。
上面的情況還不算最差,看看下面的雙重否定。
|
component.setDisabled( false ); filter.setCaseInsensitive( false ) |
再來一個,如果你讀到下面的代碼,相信你會和我一樣,要麼石化了,要麼凌亂了。
|
event.initKeyEvent( "keypress" , true , true ,
null, null, false , false ,
false , false , 9, 0); |
看完這篇文章,我希望你再也不要把bool爲作爲函數參數了。除非兩個原因:
- 你100%確認不會帶來閱讀上的問題,比如Java的 setVisible (bool).
- 你100%確認你想去寫出無法維護很難閱讀的代碼。
【更新2011/9/8】當然,別的參數也會有一樣的問題,比如: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”。