Functional Programming 函式編程
Categories:
教學影片
什麼是 Functional Programming 函式編程?
Functional Programming 簡稱 FP
- a programming paradigm 程式規範
- Style / Pattern 一種撰寫風格
- Mindset 抽象式思維
所以不管是什麼程式語言,都可以用 Functional Programming
的方式去撰寫
案例
非 Functional Programming
所有變數都在外部可以隨意存取
所有變數都在外部可以隨意存取,所以這個不是 Functional Programming
// 非 Functional Programming
let name = `KJ`;
let greeting = `Hi, I'm`;
// Hi, I'm KJ
console.log(`${greeting} ${name}`);
外部變數與函式互相耦合
外部變數會影響到函式內部,所以這個不是 Functional Programming
// 非 Functional Programming
let name = `KJ`;
let greet = () => {
let greeting = `Hi, I'm`;
return `${greeting} ${name}`;
}
// Hi, I'm KJ
console.log(greet());
是 Functional Programming
沒有任何外部變數會影響到函式內部
整個函式的處理邏輯都包含在 Function 函式
中,然後沒有任何外部變數會影響到函式內部,所以只要傳入值相同,輸出的值也必定相同
// 是 Functional Programming
let greet = (name) => {
let greeting = `Hi, I'm`;
return `${greeting} ${name}`;
}
let name = `KJ`;
// Hi, I'm KJ
console.log(greet(name));
函式產生器
產生一個指定特性的函式,沒有任何外部變數會影響到內部,所以是 Functional Programming
// 是 Functional Programming
// 形容詞函式產生器
let makeAdjectifier = (adjective) => {
return (adjectiveTarget) => {
return `${adjective} ${adjectiveTarget}!!`;
}
}
let Coolifier = makeAdjectifier('Cool');
let Niceifier = makeAdjectifier('Nice');
let name = 'KJ';
// Cool KJ!!
console.log(Coolifier(name));
// Nice KJ!!
console.log(Niceifier(name));
如何寫出 Functional Programming 程式
避免讓變數 immutable (可變的)
,使用 immutability (不可變的)
的變數
使用 immutable (可變的) 方式導致變數被異動
變數被異動,會影響到所有使用者個變數的地方,所以會導致程式之間會相互影響,所以這個不是 Functional Programming
// 非 Functional Programming
let Employee = ['Kay', 'Jay', 'KJ'];
Employee[1] = 'Apple';
// [ 'Kay', 'Apple', 'KJ' ]
console.log(Employee);
使用 immutability (不可變的) 方式產生新的變數結構
因為 Array.map()
會根據邏輯產生一個新的陣列,這個陣列與原本的陣列變數是完全不一樣的資料
所以如果變數有做任何的修改,完全不會影響到彼此,所以可以保證函式出來的邏輯資料會一致
let Employee = ['Kay', 'Jay', 'KJ'];
let NewEmployee = Employee.map((currentValue) => {
if (currentValue == 'Jay') {
return 'Apple';
} else {
return currentValue;
}
});
// [ 'Kay', 'Jay', 'KJ' ]
console.log(Employee);
// [ 'Kay', 'Apple', 'KJ' ]
console.log(NewEmployee);
// ...
// doSomethineChangeEmployee(Employee);
// doSomethineChangeNewEmployee(Employee);
程式易讀性
撰寫邏輯時,會將所有條件寫在條件判斷式當中,一但判斷變多,邏輯變複雜,就變得難以閱讀,難以維護
let calculationBMI = (bmi) => {
if(bmi < 0) {
return '資料錯誤'
} else if(bmi < 18.5) {
return '過輕'
} else if(bmi >= 18.5 && bmi < 24) {
return '正常'
} else if(bmi >= 24 && bmi < 27) {
return '過重'
} else if(bmi >= 27 && bmi < 30) {
return '輕度肥胖'
} else if(bmi >= 30 && bmi < 35) {
return '中度肥胖'
} else{
return '重度肥胖'
}
}
// 正常
console.log(calculationBMI(20));
使用 Functional Programming 將運算邏輯使用函式的方式包裝
// match 函式先省略
const lessThan = x => bmi => bmi< x ;
const calculationBMI = BMI =>
match(BMI)
.on(lessThan(0), () => '資料錯誤')
.on(lessThan(18.5), () => '體重過輕')
.on(lessThan(24), () => '正常')
.on(lessThan(27), () => '過重')
.on(lessThan(30), () => '輕度肥胖')
.on(lessThan(35), () => '中度肥胖')
.otherwise(() => "重度肥胖")
// 正常
console.log(calculationBMI(20));
FP 使用大量的 Function,幾乎每個 Function 都可以由更小的 Function
組合出來,例如 lessThan,把邏輯寫在函式名稱當中,就算過了很久後回來看程式,也知道程式大概資料留在幹嘛,也容易維護除錯
這樣好處是可以減少程式碼的重複
,所以 FP 的寫法通常比較簡短跟容易。統整 FP 的好處就是容易理解
、容易改變
、容易除錯
和具有彈性
Functional Programming 優缺點
優點
特點 | 說明 |
---|---|
safer 安全 | 函式不會被外部影響導致發生意料外的結果 |
easier to debug 容易除錯 | 函式變數之間不會互相耦合影響,所以不會牽一髮動全身,導致很難追出錯誤問題,是被哪個函式影響到 |
easier to maintain 容易維護 | 函式變數之間不會互相耦合影響,所以不會牽一髮動全身,彼此修改的資料,互相影響彼此的邏輯 |
缺點
特點 | 說明 |
---|---|
儲存空間變大 | 變數資料為了彼此不會相互影響會複製一份完全新的資料,所以會需要佔比較大的記憶體空間 |
透過 Functional programming 的觀念可以幫助我們打造出更好理解及維護的程式,當然通常 Functional programming 的寫法效能會相對比較差
但在現今運算技術越來越強的情況下,很多時候這些差異是可以被忽略的 (0.03 秒執行時間是 0.01 秒的三倍,但通常是感覺不出來的),在沒有明顯效能的考量下,誠心建議也推廣大家使用這種 functional programming 的思考方式來寫程式,以寫出更加穩固的程式碼
常見問題
Functional Programming (FP) 函式編程 vs Object Oriented Programming (OOP) 物件導向編程
Functional Programming (FP) 函式編程
與 Object Oriented Programming (OOP) 物件導向編程
沒有哪一個一定是最好的,要根據不同的使用情境去決定要用哪一種寫法
可以盡量以 Functional Programming (FP) 函式編程
的方式去撰寫,因為
- 容易除錯
- 容易維護
- 函式之間不會互相影響
所以若是比較獨立性質的函式邏輯,可以拆分的邏輯,盡量以 Functional Programming (FP) 函式編程
去撰寫會比較適合
但如果遇到需要 類別 Class
繼承的特性,根據不同參數屬性,去延伸調整類別功能,那就適合使用 Object Oriented Programming (OOP) 物件導向編程
但是也可以盡量保持,不同的類別
彼此不要互相相依影響,除了 相互繼承的類別
不得不會因為參數的異動而相互影響外,讓 沒有相互繼承的類別
彼此不互相依賴耦合,維持像是 Functional Programming (FP) 函式編程
的特性彼此獨立
這樣在需要維護或是除錯時,可以將問題範圍,限制在關聯的物件 當中即可,避免出現改 A 壞 B,改 B 又壞 C