iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0

在介紹本篇我們先來複習一下先前在 pure function 那章提過的一些名詞

  • Side Effect: 當呼叫函式時,此函式會改變外部物件的狀態,則稱這個函式有 Side Effect.
  • Pure function: 給定相同的輸入,一定會得到相同的輸出。並且不會產生任何 Side Effect.

但在現實開發中則無法避免這些 Side Effect 的操作,舉幾個例子,

  • 讀取 / 寫入 localStorage,
  • 將訊息寫入 console,
  • 取得時間 (new Date),
  • 產生亂數 (Math.random),

所以今天就要講講在 Functional Programming 中,如何去處理這些 side effect

dependency injection

example

在還沒開始介紹 IO 前,先來看看原本我們是如何寫出 pure function, 沒錯,就是 dependency injection.

假設現在有一個函式,其功用是要取得 document.body 的高度,

function getBodyOffsetHeight() {
	return document.querySelector('body').offsetHeight;
}

const offSetHeight = getBodyOffsetHeight(); 

可以看到 getBodyOffsetHeight 是一個 impure function,因為 DOM 有可能隨時改變,會使得每次呼叫 getBodyOffsetHeight 結果有可能會不一樣,要如何把它變成 pure function 呢?

function getBodyOffsetHeightFromDOM($) {
	return $('body').offsetHeight;
}

const qs = document.querySelector.bind(document);

const offSetHeight = getBodyOffsetHeightFromDOM(qs); 

沒錯,可以直接把 document 直接當參數進行傳入,這樣就可以確保給定一樣的輸入就會有得到相同的輸出,這樣不就是一個 pure function 了嘛!!

advantage

這種方法的好處是讓我們在進行 unit test 時,可以不用模擬一個專門測試的 DOM (ex: JSDOM),也就是讓程式可可測試性增加。

const mockQS = () => ({ offsetHeight: 1000 });

const offSetHeight = getUserNameFromDOM(mockQS);

assert.strictEqual(offSetHeight, 1000, true)

disadvantage

雖然我們確保了函式是 pure function 跟可測試,但當我們是開發一個大型的 App,則導致 App 非常難以維護及閱讀。

舉例來說,由於函式要 pure, 所以我們在最外層的 function 注入所有需要的的 dependency,但如果這個函式裡面是非常深層的,就必須要將參數不斷傳遞,這將會導致我們的程式碼非常難以維護。

const App = ($, localStorage, date, config, ... ) => {
    /** prop drilling */
}

小結

今天因為考駕照太忙了/images/emoticon/emoticon02.gif所以將原訂計畫稍加更改,明天將來介紹 IO Monad 是如何處理 Side Effect 的!

感謝大家閱讀!

NEXT: Handle Side Effect - IO Monad


上一篇
Day 20 - Maybe Monad II (Piping)
下一篇
Day 22 - IO Monad
系列文
Functional Programming For Everyone30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言