Functional Programming簡介

雜談

Hi,我是PK還在廢,因為工作的關係這邊接觸到Functional Programming (FP)的Programming Paradigm,聽說以前大家都是寫Object Oriented Programming (OOP),那為何要轉為使用FP呢?,由於覺得很新奇,決定來花時間記錄一下學習過程。

在接觸FP前,由於不是資工相關背景出身的,其實對Programming Paradigm沒有很在意,畢竟多數做的是一人專案,只要能動就好(X。不過開始工作後,變為多人團隊開發,因此對於統一的Programming Paradigm有較高的要求,方便提升程式可讀性與持續維護能力。

什麼是Functional Programming?

Function is the first-class citizen in FP

First-class citizen這個概念在Programming領域可以理解為做為一個參數傳入,或可以儲存為一個變數,所以可以理解為FP可以把Function作為變數儲存,並且可以傳遞至下一層繼續進行運算。但這樣有有什麼好處呢? 別急,後面會慢慢說明。

當一個Function的參數也包含一個Function時,我們稱這個Function為High Order Function,這種類型的Function充斥於FP內,是實現FP的基礎核心概念,以下來個簡單的範例。

// return a function
const add = (firstNumber: number) => (secondNumber: number):number {
    return (firstNumber + secondNumber)
}

// store function as const
const addOne = add(1)
const addFive = add(5)

console.log(addOne(5)) // output: 6
console.log(addFive(5)) // output: 10

那將Function的作為參數代入有什麼好處呢? 簡單來說就是模組化設計,透過將重複的Function包裝,可以在需要時重新組合成新的功能,這使得程式的設計更加彈性,且易於擴展。

Side Effect

FP還有一個很重要的概念,那就是Immutable,目的是為了避免參數、變數等等的狀態改變造成的Side Effect。

Side Effect是程式開發非常忌畏的影響,因為當程式結構一大,你會搞不清楚哪邊造成了狀態變動,導致錯誤排除困難。在JavaScript中常見的Side Effect有以下幾種 :

  • 更改外部變數與物件屬性 (例如: Global or Parent Variable)
  • 將值寫入consolo.log或檔案內
  • 觸發外部流程 (multi thread, API)
  • 呼叫任何有Side Effect的Function

FP的一大優勢就是避免Side Effect發生,而當Function沒有Side Effect,我們會稱之它為Pure Function ,當你輸入相同的Input,那你會獲得相同的Output。

和Object Oriented Programming的差異?

其實兩種模式各有優缺,且兩種模式要共用也是可行的,因此直接拿兩者比較並沒有太大的意義。OOP如果參照Don’t Repeat Yourself (DRY)原則也是可以寫出類似FP效果,差異在於FP的Immutable有強制性規範,而OOP對此較為寬容。

此外,對於OOP而言,將Class作為基本單元來管理程式,而FP則是以Function為基本單元來管理,所以可以依據你們團隊的開發偏好來選擇適當的Programming Paradigm。

有興趣可以參考這篇文章下面的留言,應該會有近一步的認識 :

為什麼要學 Functional Programming? – iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
What’s Functional Programming A programming paradigm where programs are constructed by applying and…
ithelp.ithome.com.tw

Declarative & Imperative Paradigm

在談到FP和OOP時,會提到Declarative (宣告式) Imperative (命令式) 這兩種模式 :

  • Declarative Paradigm : 告訴用戶What to do,用戶可以透過自然語言理解現在這個階段在執行什麼操作,常見的有 : SQL, HTML等語法,FP也是屬於這種類型。
  • Imperative Paradigm : 告訴用戶How to do,用戶主要透過State來判斷如何操作,一般我們寫程式用到 for, switch, while, if…else 就是屬於這類,多數程式語言屬於此類,也因此會有OOP是此類的說法。
const arr: number[] = [3, 2, 1]

// Declarative paradigm
const add5forArrayDeclarative = (array: number[]): number[] => 
    array.map((element: number) => element + 5)

// Imperative paradigm
const add5forArrayImperative = (array: number[]): number[] => {
    const newArray: number[] = []
		for(var i=0; i < array.length; i++) {
		    newArray.push(array[i] + 5)
		}
    return newArray
}

console.log(add5forArrayDeclarative(arr)) // output: [8, 7, 6]
console.log(add5forArrayImperative(arr)) // output: [8, 7, 6]

Declarative較依賴Expression (可以直接理解為Function),Expression是一種單純的運算式,上面使用的map就是一種,並且這種運算式一定會回傳值,讓我們可以把回傳值送至下個階段進行運算,所以也可以說是Data Flow的控制。

透過這種特性,我們可以將多個Expression串接,構建複雜的Function,並且由於不會有Side Effect,因此程式複雜度不會上升太多,這也是FP的一大優勢。不過這邊也可以很明顯看出FP的導入困難之處,那就是學習曲線。

Functional Programming Learning Curve
From the amazing Mostly Adequate FP Guide

要熟習使用FP需要找到相對的套件,並且熟悉裡面提供的Expression,才有辦法發揮100% FP的優勢。這也是多數公司沒有導入FP的原因之一,專案交付看不懂那不是更麻煩嗎?
(ಠ益ಠ)

Conclusion

今天先簡單帶過Functional Programming的基礎概念,方便大家後面理解,也同時提供大家分析看看究竟是FP還是OOP更加適合現在的團隊開發。這個答案沒有絕對,也不是誰好誰壞的二元題目,唯有選擇適合自己團隊的開發模式,才能維持好的專案品質( • ̀ω•́ )。

下篇預計會介紹如何實現FP,以及FP中常常被使用到的概念與Expression,敬請期待。

Reference

2020 IT 鐵人賽之 — 開始用 javaScript 學 Functional Programming 囉 | by Hannah Lin | Hannah Lin | Medium
我懶得把 30 天文章都般來這,但 medium 又只允許放一個外部連結,只好多發一篇文把目錄都放在這. “2020 IT 鐵人賽之 — 開始用 javaScript 學 Functional Programming 囉” is published by Hannah Lin in Hannah Lin.
medium.com
JavaScript: Functional Programming 函式編程概念 | by Po-Ching Liu | Medium
函式編程(Functional Programming,以下簡稱FP)是眾多程式設計(Programming Paradigm)方式的其中一種,有別於老早就大紅大紫的物件導向編成(object-oriented Programming,OOP)方式(OO還衍伸出許多設計模式(Design Patterns)),FP則是近年來較為熱門的程式設計方式。像是 React 這套 JavaScript…
totoroliu.medium.com
Introduction – mostly-adequate-guide
mostly-adequate.gitbook.io

Leave a Reply

Your email address will not be published. Required fields are marked *