星期三, 10月 30, 2013

預防笨錯誤? 尤達表示法 (Yoda Condition)

曾幾何時,在公司的程式碼看到一段code,以下為示意:
if (TRUE == isOilPoisonous)
{
  printf("It's Da Tung!");
}
產生很多問號,誰吃飽撐著把 TRUE 放在比較式的左邊呢?
是為了強調這段程式碼的意圖嗎?

事實似乎不是這麼一回事!

直到最近,才知道這東西叫做尤達表示法 (Yoda Condition)。
他存在的目的完全不是為了可讀性,相反的,這種風格使可讀性下降了。
那為什麼要付出代價維持這種風格呢?

原因如下。
看看這兩段程式碼,毫無疑問完全相同,只是條件順序對調了一下。

if (isOilPoisonous == TRUE)
{
  printf("It's Da Tung!");
}

if (TRUE == isOilPoisonous)
{
  printf("It's Da Tung!");
}

但是如果有人手抖把 "==" 敲成 "=" 的時候,你會發現,其中只有一種會compile error。
而另一個,會巧妙的隱藏,成功地編譯,變成很難發現的臭蟲。
日常生活中,手抖,手殘,以及少打一個等號這種事情,是絕對有可能發生的。
為了避免這種情況,只好犧牲一些可讀性,套用 Yoda Condition,來斃掉這種藏得很深的臭蟲。

事實上,現在的 compiler 可以讓你察覺這種手抖的情況。
用 gcc version 4.4.5 測試了一下,如果你有使用 "-Wall" 參數,
來編譯 "if (isOilPoisonous = TRUE && ...) ...",
你會得到這樣的警告訊息:
yoda.c:7: warning: suggest parentheses around assignment used as truth value
但如果進一步改寫成這樣 "if ((isOilPoisonous = TRUE) && ...) ...",就...

註:尤達大師講話愛用倒裝句。

參考:http://en.wikipedia.org/wiki/Yoda_conditions