[213] 該死的範例碼之爭,卷二

論斷是非必須考量當下的情境;保持開放才是正確的求知心態。

[213] 該死的範例碼之爭,卷二

卷一說明範例碼之所以被稱為範例碼是有原因的。然後「複製貼上」範例碼到專案用的傢伙,首犯警告,再犯永不錄用。

再舉個例子。底下影片旨在說明 std::thread 的基本用法。影片裡用了全域變數來控制執行緒結束的時機。實務上,全域變數會讓程式碼變得難改、難測,應盡量避免。那麼以這支主要目的是介紹 std::thread 的影片來提問:

  1. 你會因為用了全域變數就說這是作者平常的撰碼習慣嗎?
  2. 你會因此認定作者頻道上所有影片的示例都是糟糕的嗎?
  3. 你會因為用了全域變數而認定該影片是錯誤示範嗎?

上述提問,我的回答都是:不會。你呢?

其實這篇原稿有許多沉不住氣的反諷最後改掉了。沉不住氣的原因是看了一些令人不知該哭還是笑的留言。一起來瞧瞧。

後山小門處有大便一坨 這佛寺裡肯定大便滿窩

有人說:

不是 legacy code 問題,而是 多層 if then else, 連一個 example 都寫這樣,可想他們內部必然是這種 Style...

這麼肯定?以微軟這種規模的軟體公司每個人的能力都會在同一個水平?Windows Core 核心成員也是這樣寫程式?拿一個範例碼來論斷一間超大型軟體公司的軟工素質,這邏輯太過偏差,不矯正恐怕不適合從事軟體工程。

其實微軟開源的專案數老早就是 GitHub 的前段班,是不是每個專案都寫得很糟(Nested-if style)?隨便挑幾個專案來看就知道。

無法順應時勢做出改變,遲早被淘汏。微軟變了,你變了沒?

又有人說:

如果是一個沒經驗的人寫出來,沒有問題的,但我針對是一間大公司出品,無論 Google , Facebok, Apple 都一定有 Coding Style, 在任何一方面一定要跟從,無論Demo Code , Sample, Tutorial

嚴格要求旗下軟體團隊撰寫程式碼時遵守官定的 Coding Style,這個觀念沒問題。但是,這樣的標準及不及於文件上的範例碼,尚有討論空間。把範例碼與 Production Code 混為一談帶來的壞處多於好處。範例碼可能為了配合文件說明樣式而在撰碼風格上「被迫」使用與官定 Coding Style 不同的寫法,這麼做錯了嗎?我不這麼認為。再一次強調,Nested-if 是不好的寫法,實務上有很多更好的解法。蛋,這可是範例碼呀。

論斷是非必須考量當下的情境;保持開放才是正確的求知心態。

市值站上千億的軟體公司從此不再擔心開發資源?

從一個簡單Demo就知道一間公司文化,如果你是一間小公司大家不會怪你,但一間環球公司,你試想一下你的Android電話的代碼有這樣Style,你會不會擔心?大公司應該更加有資料有財力去做好每一件事。

請問市值超過多少金額的軟體公司,其開發資源會變得無窮大?請告訴我,我會好好筆記下來。

迷思:「因為是大公司,所以有用不完的資源」。資源再多,使用時也要有優先順序,一個已經達到目的範例碼,儘管不完美,將其優化的效益有多大?把資源用在效益更大的工作上不是更好嗎?

以前有個客戶,跟我們對口的部門老闆對著我說:「發現是韌體的問題不準你們軟體做 Workaround,韌體的問題韌體自己解決。」,長官不知道的是,他說的豪氣干雲,底下的兵是臉色鐵青。軟體沒幫忙做 Workaround,產品何時能出貨還說不準咧。實務上為了讓產品能出貨,執行任務時,「妥協」是必須的。

每個人都想寫出乾淨無蟲的軟體,但理想與現實終有差距。我認為應該懂得取捨,適時妥協,拉住底線,該執著時不放手,該放鬆時轉個念頭。

離題太遠,拉回來看原 Po 的佳作(回黃保翕):

最初你說沒法不用nested-if來寫,我已經證明了不是了。

這是放在MSDN的教學source code,可以預期大量新手會閉上眼睛copy-and-paste到自己的專案直接拿來用的。

所以你是覺得:
1 多層nested-if是沒問題的
還是
2 MSDN的demo code是絕對不能拿來用的,用了而專案變爛,後果自負!

身為微軟MVP的你,是以上那種看法?

真是標準不負責任的嘴泡(炮)。明知道那是範例碼,不是要(也不可以)用在真實產品上的,這種說法難道是要幫「複製貼上大法」開脫?以個案來看,我不知道 BasicFileOpen 那段要怎麼 Copy-and-Paste 來用?真有人直接把這範例碼用在公司專案,把他砍死,我不會出面制止。

沒人說 Nested-if 在所有情境下都沒問題,曲解別人的意思來發戰帖,難以服人。當過兵的人肯定聽過「演習視同作戰」,但演習時槍裡會擺實彈讓兩邊互開嗎?演習時炮彈會對著紅方的真人區打下去嗎?我沒參加過旅對抗或大型演習,不過我大膽假設應該不至於玩那麼大吧?

不懂老實承認 好過假裝很會

原 Po 提供了一個,據說是比較好的寫法。不看還好,一看蝦小?

如果C++沒有Defer這種語法,不就是:

int sucuessfulStep = 0;

if (sucuessfulStep == 0 && SUCCEEDED(hr)) {
//perform step0 action
sucuessfulStep = 1;
}

if (sucuessfulStep == 1 && SUCCEEDED(hr)) {
//perform step1 action
sucuessfulStep = 2;
}

......

if (sucuessfulStep >= 8) {
//perform Step8 clean up action
}

if (sucuessfulStep >= 7) {
//perform Step7 clean up action
}

為了消滅 Nested-if 而用了我認為更糟糕的寫法,sucuessfulStep 危險又多餘,而且把 if 判斷式複雜化了。 if (sucuessfulStep == 1 && SUCCEEDED(hr)) 確定這樣有比較好?

不懂別硬撐,讓專業的來。與其堅持函數只能有一個「出口」,不如使用 Return-early 的技巧,一旦往下執行的條件不成立就直接離開函數,更加美觀大方。

還有一個很狂超狂的小白二號,狂到我不敢引用他的原話,怕髒了我的地盤。「小白二號」就是我說的「開源碼死士」,認為全世界只有某技術或某作法才是唯一真理,其他都是屁。這種人擁有超強戰力,戰信仰、戰田地,偏偏就踏馬的不照照鏡子看看自己,究竟嘴巴吐出來是什麼東西。

卷二完,待續。


《大山姆的機機車車》電子報

我是山姆。2018 年初我發行了個人電子報,提供軟體開發資訊與學習資源,還有軟體工具介紹及使用技巧,其中包含了我在 WorkFlowy Tips 上發佈的最新文章。如果你跟我一樣求知若渴,又不想花太多時間「過濾」資料,每月兩期,著重在 C++ 與軟體開發議題的《大山姆的機機車車》電子報。資訊充滿,垃圾沒有,歡迎訂閱。