Functional Programming 函式编程
教学影片
什麽是 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