關於函式的撰寫原則,我們過去花了三天來學習,對於避免過多參數以及旗標參數的概念,這邊就不再多提。但在分享參數的文章,開頭有一個概念只簡單的帶過,就是:避免輸出型參數
。
為什麼呢?因為輸出型參數非常不直覺。我們很習慣也很自然地,會將參數解讀為輸入,當看到一個輸出型參數時,我們將很可能不得不再三思考或回去查看函式細節,而這將會中斷我們的思考。
此外,當我們看到已被遺棄的函式
時,應果斷地移除它。就如同註解時所說的概念,如果未來真有人需要它,版控系統會妥善地記住這些函式。
對原始碼來說,最理想的狀態是只擁有一種,而且是唯一的一種語言。
記得剛接觸前端程式語言時候,一開始我們會將 HTML、CSS、JavaScript 都寫在一份檔案中,隨著程式碼的增加,老師告訴我們要將檔案分開:HTML 一份,CSS 一份,JS 也自己一份。保持原始檔語言的單純,能避免讀者的困惑,同時也是一種關注點分離。
當然,在實務上我們可能還是會使用一種以上的語言,但我們仍然不能放棄,努力讓使用語言的數量減至最少。
遵循「最少驚奇原則」 (The Principle of Least Surprise) ,抑或「最少驚訝原則」 (The Principle of Least Astonishment),任何函式應當實現其他程式設計師合理預期該有的行為。
例如,有一個函式會將日期名稱轉換為代表該日子的列舉值 (enum):
Day day = DayDate.StringToDay(String dayName);
我們將期待字串 "Monday" 會被轉換為 Day.MONDAY,也會預期其他常用的星期縮寫可被翻譯,同時,也會設想函式能避免大小寫所帶來的影響。但當函式明顯該有的功能未被實現時,我們將失去對此函式的信任感,對於是否使用也會感到遲疑,或是我們必須回去查看程式碼的細節,好讓我們理解它究竟能做些什麼。
說穿了,這其實也是程式碼表達力的一環。當函式的名稱與實際功能不相符時,它很明顯已失去了明確表達意圖的能力。
程式設計師普遍都會認同「程式碼要有正確的行為」,但這並不容易。不要依賴直覺,我們應該要盡力查看以及撰寫測試程式,在各種邊界條件(我個人認為就是極端條件下),程式依然能夠正確運作。
多數的重大意外,都來自選擇跳過繁瑣的規範,因為規範使我們感到不便。
對於一個從 JaveScript 進入程式世界的我而言,剛開始對宣告型別完全沒有概念,也因此當我第一次被迫接觸 TypeScript 檔案時,實在不知道該怎麼去撰寫程式。簡單地說,就是怎麼寫怎麼錯,寫個三行可能就會編譯不過。
於是天才的我學會了一招,需要宣告型別時通通顯式定義 any,於是就能夠繼續快樂地寫程式了。當然,既然都被迫使用 TypeScript,還是認份地爬文、看官網去學習這門語言。那時有段話觸動我,而話的大意是說:「如果我們只想讓編譯通過,於是遇到型別報錯就給 any,那就失去了使用 TypeScript 的意義,不如不要用。」於是我才開始認真地宣告正確型別,來保護我的程式。
對於一個弱型別語言而言,開始定義型別是件麻煩事,但也避免程式曝露在不必要的風險中。直到現在,如果單寫 JaveScript 無法宣告型別,有時反倒還會感到不安與怪異。而我期待在未來的某天,當我沒有寫單元測試時,也會感到同樣的不安。
關閉某些編譯器的警告,也許能幫助你順利建立專案,但也付出了可能得進行無止盡除錯的風險。關閉失敗的測試,然後告訴自己,晚些時候你會使之全數通過,就像假裝信用卡不用付錢般糟糕。