寫出易懂的程式
軟體工程界喜歡搞出一大堆名詞,可讀性、設計模式、clean code/architecture、SOLID,什麼玩意兒之類的一大堆,但是聽久了實在有點受不了,今天我不創造任何新的名詞告訴你如何寫出易懂的程序。
簡單說其實就是你要能替換自己目前的腦袋,想像你是第一次看到這段程式,去思考你可能會怎麼解讀這段程式。
- 讀懂這段程式需要多少前置知識
- 理解這段程式,需要使用多少的記憶/計算
第一點正是我不喜歡設計模式的原因,首先設計模式畢竟不是為了解決你手邊的問題而出現的,往往是為了把你手上的問題套入設計模式來解決而實現的,這就有點像是一個熟練的工程師能自在的使用程式語言的語法來解決問題,而新人工程師卻會為了使用某些新語法新功能而拼命把邏輯套進語法,一個是你能用錘子解決問題,一個是你拿著錘子所有問題都變成釘子。
至於自家的商業邏輯有多複雜當然也是一個問題,不過這是取決於環境,所以無需多談。
我自己會說一句話,「一個寫的好的函式不在於他做了多少事,而是他隱藏了多少細節。」
第二點我們來看幾個程式
(啊哈哈寫ruby也挺有意思,不過我目前用比較多的是js,應該普及度最廣的也是js,所以就寫js吧)
console.log(1)
console.log(2)
console.log(3)
for(let i=1;i<4;i++)
console.log(i)
這兩段是在「行為」上等價的程式,但是理解兩者需要消耗的腦力顯然是不同的,只要你是程式員應該都能理解我的意思。
一般來講都會說前者的複製貼上寫法是不好的,但是我要告訴你,當你覺得這樣寫比較好的時候就這麼做吧,複製貼上會比較好的時候是存在的,比方說一個新功能開發出來,還不太明確未來會怎麼發展的時候,我就建議不要花太多時間去把程式的結構提取出來,因為你不知道以後會怎麼改。
再看以下這段
function get_nums(){
return [1,2,3,4]
}
for(let i of get_nums())
console.log(i)
看來起是不是結構又更完整了,但是請注意,現實中你的get_nums可不會那麼單純回傳一個字面數值,也許要經過一連串的計算或者存取db才能得到,所以從(2)上來說他無疑是更高的,這並不是說他就是壞事,如果你要處理的問題確實很複雜,那麼進行複雜的運算無可厚非,但是如果你面臨的問題很簡單,請你用簡單的方法來解決他吧。
有些人是以寫出複雜艱澀難懂的程式為榮,我是以寫出笨蛋都能懂的程式為榮,至於你是哪一派人,這是由你自己來決定的。
剛剛提到了「行為」,那就順便來說說「語義」
let x = 15
let x = 3 * 5
同樣的以上是兩段行為相等的程式,但是「語義」卻是不同的,某些人可能會告訴你寫前面那樣效能比較好,我會請他吃*,這邊給你一個準則,如果你覺得這是一個編譯器優化能解決的優化,就千萬不要手動去做他,不過實務上我根本不會在乎這種問題,哪怕我用的不是編譯式語言,因為電腦的效能已經高到不行,而且每年都會越來越快,所以維護軟體的成本是高於計算成本的,假設你的演算法資料結構有做到一個至少合理的程度的話。
也許下次開一篇談談什麼是「合理的程度」。
變數名稱、註解什麼的各位應該聽很多人講過了,我隨便說個想到的就好了。
// do job here
function do_job(data){
}
你他媽的不要把變數名稱叫做data,任何變數都是一個data,這是沒有意義的名稱,還有這個註解也是沒有意義的註解,因為我看函式名稱就應該知道了。
我以前的想法是不需要寫註解,寫好的程式應該能解釋自己,只有在為了解決一些bug而需要做一些hack時才需要註解。
現在再稍微補充一件事,可以在函式中註明前置條件、或是「不要」如何修改程式,這來自於我在多人團隊中工作的經驗,有些我開出來的函式一年以後我都不認得了,出於維護目的寫一些註解指導別人如何使用是有意義的。