0%

寫程式的 6 招實用技巧

Coding 其實是有招式的,如果招式沒打好,除了效率打折,還會讓其他合作夥伴抱頭燒,所以好的開發習慣有必要好好養成。

此篇來自於「在地上滾的工程師 Nic」的 YouTube 頻道的「提升軟體開發品質! 寫程式的 6 招實用技巧」觀看後的筆記,因為覺得條條建議都很重要,又怕忘記,所以寫個筆記來記錄,希望自己可以把這些好習慣養成。同時也很推薦 Nic 的頻道,很多很受用的經驗分享,對於新手工程師而言,這些經驗是早知道的些好。很值得訂閱觀賞,當然也記得要好好的記住他分享的經驗,對往開發工程師的路上前行的人,一定會有幫助的!

他提到培養寫程式的好習慣有什麼好處?有三大好處:

  • 有效提升協做效率
  • 增加程式被測試的可能性
  • 建立一定的專頁度

通常專案都會有時程的的壓力與要求,一定有時間的壓力,必然會犧牲掉程式碼的品質,但如果程式碼的品質不夠好,接下來就有技術債的問題,然後新的功能越來越難增加,或是增加了,所許要付出的時間會更多。主要是程式碼不只是要會運作,也需要讓其他協做的工程式看得懂,所以如果能夠對自身有「寫好扣」的要求,對自己或是協作者而言,都可省不少力,如果想當一個好工程師,一定要把這些好習慣養成。

以下就是好習慣養成的六招

避免簡寫,使用有意義的命名

除了函式需要有意義的命名外,變數、參數都應該盡量避免使用簡寫,資料本身已經有型別的問題,如果參數、變數名語意不明。也不能直覺的知道是哪種型態的型別。如果寫簡寫,其他人甚至自己都有可能忘記代表其意義,然後還要花時間去猜,去看上下文,很花時間,更有可能猜錯。
多打幾個字不會花你很多時間,少打幾個字,會花掉無法想像的許多時間。

限制傳入參數的數量

因為需求增加,有可能在寫函式時會增加數個參數傳進函式裡處理,但是如果參數過多,很難定義這個函式要處理的邏輯,因為變因多也會很難做測試,讓函式變得複雜,且一次做太多事會很難拆解並降低函式的複用性,所以參數最好不要超過三個,如果超過三個,可試著再拆解出另一支函式,或是用 has 或 Object 的方式,把這些參數包成一個物件,直接傳進去函式。這樣其他人在看這支函式時,比較可以一目了然這支函式所要處理的邏輯與資料。

簡化條件的表達(判斷)式

可以試著把判斷式的結果直接回傳出去,試著避免撰寫多餘的部份。因為需要回傳的是 Boolean 值,只要把符合的條件以判斷的結果直接回傳就可做到。
以下例子是自己用 JS 改寫,可回去看 Nic 的影片例子會更精確。

1
2
3
4
5
6
7
8
9
10
11
12
// 是否有符合騎車資格,回傳值為 Boolean 
function canPersonRideMotorbike(person){
if(person.age >= 18 && person.has_rider_license){
return true
} else {
return false
}
}
// 建議寫成這樣:
function canPersonRideMotorbike(person){
return person.age >= 18 && person.has_rider_license
}

變數定義範圍的限制

盡量讓變數在函式裡面讀取的到就好(區域變數),也就是盡量避免使用全域的變數。現今 ES6 已有限制區域的 let 和 const ,最好棄用全域的 var ,除非變數有全域可存取的需求。
盡可能把一個變數的作用域限制在函式裡,只讓這個函式可以讀取或修改這個變數,在函式使用之後就丟棄此變數,才是比較好的方式。這樣才能避免全域變數污染與程式難以測試的問題。

一支程式只做一件事情

在封裝函式時,函式定義命名必須要和函式所處理的邏輯有一致的行為,不要在同一支函式裡,加入其他要處理的功能,這樣會造成其他工程師在閱讀與理解上,或是呼叫這支函式而造成無法想像的 effect。例如函式處理訂單總價,就不要夾雜打折或其他邏輯。
如果一定要把另一個行為包進去同一支函式裡,可以把函式取名為比較中性的名字,例如 xxxService,明確撰寫函式需要做什麼事、流程或邏輯,讓其他工程師在乎叫這支函式時,很明確知道這支函式的用途。或是,更改函式的命名,同時把兩個功能行為寫進命名裡,但這樣仍不是個好做法。

Early return (提前回傳)

當 if, else 超過兩層以上,會形成多層巢狀,結構會越來越複雜且難以閱讀,尤其要找出對應的條件更是困難。設計多條件判斷的邏輯時,可使用 Early return 技巧,讓程式盡可能提早結束,避免去執行到不該執行的部份,

改寫成 JS 的範例:
技巧:只要遇到不符合條件,就跳出函式這樣就可以讓程式盡可能保持一層的判斷,如果 if 條件有符合再繼續。
這種在相關的 Design pattern 也有提到,例如 fail fast, guard clause(改天找來看)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 錯誤示範
function returnStuff(argument1, argument2) {
if(argument1 === true){
if(argument2 === true){
let otherValue = getSomeStuff(argument1, argument2)

if(otherValue === true) return "Stuff"
else return "Error"
} else return "Error"
} else return "Error"
}
// 較理想的寫法
function returnStuff(argument1, argument2) {
if(argument1 !== true) return "Error"
if(argument2 !== true) return "Error"

let otherValue = getSomeStuff(argument1, argument2)

if(otherValue !== true) return return "Error"

return"Stuff"
}

再次感謝 Nic 提供實用的資訊與技巧,把這樣的習慣養成,應該可以提高可讀性,也可降低殘害合作同伴的可能。

補充:
關於命名,可參考有意義的命名 | Clean Code.