認識與避免非預期的Side effects
在開發程式的時候,有時候我們會寫出一些連自己都不知道在寫什麼的程式,特別是如果自己都不知道自己在寫什麼的話,更不用說和你一起協作開發的夥伴了,因此下面將會帶大家了解Side-effects與非預期的Side-effects是什麼。
Pure function
Pure function就像他本身的意思一樣,表示乾淨的函數。你可以很清楚且直覺地知道這個function做什麼事情,通常Pure function的輸入和輸出的參數都會是一致的,並且可以預期輸出的結果會長什麼樣子。
舉例
以下的函數可以視為Pure function,用來產生身分證字好的function:
1 | generateId = (id) => { |
但是以下並非是Pure function,你知道為什麼嗎?
1 | generateId = (id) => { |
關鍵在於你能不能輕鬆得知格式一定長什麼樣子
例如:
1 | const myId = generateId(‘1000400321’); |
如果你使用第一個function,你可以用想的馬上知道他會變成TW-1000400321-01
如果你是用第二個function,因為是使用亂入產生換發時間,所以你無法確定他最後輸出的模樣。
因此,第一個function可以視為一種Pure function。
但是,這不代表第二個function這樣寫就一定不好,只是如果讓程式能夠盡量Pure,會讓開發的效率提升。
試著讓你的function Pure
以上的例子可以歸類出一些特點:
- 相同的Input,通常會有相似的輸出
- 沒有Side effects
在開發程式的時候,盡量讓程式的Side effects降到最低,這個時候就來到重點啦~什麼是Side effects?
認識Side effects
讓我們先來看以下的程式,createUser產生一個使用者並且回傳他,是一個標準的Pure function:
1 | createUser = (account, password) => { |
但是一旦我加入一行程式之後,一切就會大不同了:
1 | createUser = (account, password) => { |
一旦excuteSession被執行,這個動作很有可能會改變程式的狀態,甚至是整個專案。
excuteSession並非僅僅是在這個function執行動作而已,他很有可能會帶動整個程式巨量的改變,例如:改變外部的變數。
僅管這個function輸入和輸出都是一致,可預期輸出的值是什麼,但是因為會造成Side effects,因此不能視為一種Pure function。
Side effects好不好
以上面的例子來看,也許你會認為Side effects並不是一件好事?
但是並非如此,這樣看你所開發的專案或是程式是什麼而定。
Side effects無所不在
有很多Side effects的程式是必須執行的,例如:啟動session, 傳送http請求, 登入系統, 顯示訊息……
這些都是常見經典的Side effects,因為改變了使用者使用這個系統的狀態。
因此Side effects無所不在,甚至在你目前所持有的專案幾乎每個都有Side effects。
講到這裡看起來…Side effects好像也沒有想像中的那麼糟?
那麼…到底需要注意哪部分呢?
要注意的地方
Side effects比較不好的地方,其實是無法預期的Side effects。
以createUser的例子為例,你其實很難從createUser看出excuteSession主要是在做什麼,例如:可能會存取資料庫。
一旦createUser的程式大起來,事實上很難理解執行了createUser,到底會改變什麼。
以下再來看一個經典的例子:
1 | let lastGeneratedId = null; |
從這個例子可以看出function並非單純的執行generateId,也會改寫外部的變數。
避免非預期的Side effects
要避免無法預期的Side effects其實不難,通常只要盡量保持你的程式clean code,注意與制定協作的naming convention,就能盡量預期Side effects會造成什麼變化。
我們來做個小測驗吧!
(一)多選題 100%
- 以下哪些function會發生Side effects?
A.saveUser(…) B.isValid(…) C.showMessage(…) D.createUser(…)
答案是ACD,你100分了嗎?
處理Side effects
以上的重點為:盡量讓你的專案不要出現非預期的Side effects
如果你的專案必須或需要Side effects的話
應該盡量:
- 從命名展示出可能發生Side effects
- 將會發生Side effects的部分,移動到其他function或是其他片段
結論
clean code原則可以讓你在開發程式時,減少出錯的時機,你也會發現clean code並沒有絕對的好或是絕對得不好,只有建議怎麼樣會比較好。因為clean code理論上雖然可以做到,但實際開發會遇到種種狀況導致無法如預期上的那樣完美,例如:程式中出現無法馬上移除,且很重要的程式片段。