物件導向程式設計 ( OO ) 透過「封裝」活動零件、部件 (指程式碼片段),使程式碼更容易理解。
函數式程式設計 ( FP ) 透過「最小化」活動零件、部件 (指程式碼片段),使程式碼更容易理解。Michael Feathers — Working Effectively with Legacy Code 的作者
(來源出處:https://twitter.com/mfeathers/status/29581296216)
大師說過 OOP 藉由「封裝」、FP 藉由「最小化」來強化我們的程式碼,但現在看起來有點無感!
首先就讓我們來看看 OOP 及 FP 各自的模樣,再來進行討論吧!
舉例1( OOP ):假設我們需要創作一個角色扮演的電腦遊戲 ( RPG ) ,我們的會希望玩家進入遊戲時,會創角色輸入一些基本資訊、接著再選職業。
以 OOP 的觀點是,我們的角色人物是一種 Object、職業是一種 Object。透過Object的封裝,使我們
- 不同的方法(eg 技能:砍擊、火球)不會被不相干的程式碼誤用
> 你說說哪有騎士狂噴小火球的道理 XD?!魔法師能狂暴砍擊的 - 透過繼承,使我們能抽象出 Object 共用的特性,降低重複的程式碼
> 每個職業都會有的基本資料:名稱、性別,我們把它放進角色裡。 - 我們也得以將每個角色的狀態也能透過 Object 儲存起來
> 因為物件的特性,等級、經驗值、血量、魔力值等,這些數據可儲存記憶起來。 - OOP 以更直觀、更貼近世界的方式,撰寫程式
物件導向 OOP 開發風格有以下 4 大特性:封裝、繼承、抽象、多型
在這邊不多做解釋,詳閱其他 OOP 強者大大們的文章。
舉例2( FP ):當我們想烹煮一道美味的牛排,從生牛排到擺上餐桌之前,我們會經過一道道工序,到最後可以上桌大快朵頤。
以 FP 的觀點是,我們不會像下面的 function 一以概之,而是將烹飪牛排這個重大的任務拆解成許多細小的子任務。每個子任務都專注在一件事情上。之後再將這些小任務組合起來。
function serveSteak(ingredients, pan) { // 調味
// 擦拭
// 煎、烤
// 切片
// 擺盤
return readyToEatSteak}
// No~~~~~~~~~~~~~~~~~~~~~~~
function 調味(ingredients){
// 進行調味...
return seasonedFood
}
function 擦拭(wetIngredient){
// 擦拭食材...
return driedIngredient
}
function 預熱(pan){
// 預熱平底鍋...
return preHeatedPan
}
function 烤、煎(rawFood,preHeatedPan){
// 烤、煎...
return grilledFood
}
function 切(food){
// 切食物...
return slicedFood
}
function 擺盤(food){
// 擺盤...
return lovelyAndDeliciousFood
}// 此處的 useWith, pipe 為 ramda 提供 API
// pipe 也是 FP 重要的觀念,會在之後介紹。const 烹煮牛排 = useWith(烤、煎, [pipe(調味,擦拭),預熱])const 提供牛排餐點 = pipe(烹煮牛排,切,擺盤)const myLovelySteak =
提供牛排餐點(['生牛排','大蒜','玫瑰鹽','奶油'])('平底鍋')
// yes ~~~~~~~~~~~~~~~~~~~~~~~~
透過拆解問題的方式,我們將每個 function 的功能拆得很小很細,當這些小 function 被拆分到很細微時。
- 程式碼「共用性」被提升了
切食物 function,可以不被侷限在切牛排還是切青菜
預熱鍋子 function,也可以在其他地方被重複使用
2. 程式碼「可讀性」增加了,由上面範例中,我們非常專注在拆解、描述這個任務的一系列操作,而底層、具體的實作則被封裝進 function 裡面。
想要吃牛排,我只需要知道呼叫「提供牛排餐點」 serveSteak([‘生牛排’,’大蒜’,’玫瑰鹽’,’奶油’])(‘鍋子’)即可。想知道牛排的製作過程,const cookSteak(烹煮牛排) = useWith(煎/烤, [pipe(調味,擦拭食材),預熱鍋子])我也大致知道其字面上的意義,當我有需要了解底層實作時,再進去看這些function 各自的定義即可。
我們平常寫程式時,能解決問題、程式碼會跑就可以了,為什麼我們還要特別學 FP / OOP 啊?學習這些程式碼典範,都是在約束我們寫程式QwQ。
因為有了這些規則的約束跟封印,才能避免我們的程式碼暴走,就像鳴人體內封印著九尾一樣,尾獸擁有過於強大的力量,能導致村莊被破壞、對人類造成威脅,只有像火影這些大神們才得以駕馭這些力量!可惜我們都是凡人,為了保護自己、保護他人,我們要好好認識這些規則的存在及其背後的緣由。
小結:我們希望能使程式碼能更容易被理解、預測,不論與其他工程師合作,或是與過去、未來的我們合作,所以我們持續學習!
註:以前剛開始寫程式時的印象很深刻,時常寫了一段程式,過幾小時、過幾天回去看就看不懂了QwQ,隨著知識、經驗的提升才知道越來越多適當的表示與撰寫方法來盡量提升程式碼的可讀性。
OOP v.s. FP
那既然我們對 FP / OOP 有初步的理解後,我們便能來對兩者稍做比較了。
來源出處:https://sdacademy.dev/difference-between-functional-programming-and-object-oriented-programming/
或許讀者現在觀看上方的表格,會有些疑惑、無感的地方,Ken 也是隨著使用 FP 逐漸對此有感,也希望讀者未來更認識 FP 後,再回來閱讀,肯定能有新的一番體驗。
未來對於 FP 理解更多後,我們也能更針對 FP / OOP各自的優缺點下去分析。
既然說到函數式程式設計 ( FP ) 透過「最小化」來增進程式碼的可讀性。我也將在下篇文章探討,身為最小單位的 function 需要具備什麼特性。
如果這篇文章對你有幫助,請幫我拍手一下
你的拍手及分享是對我最大鼓勵與書寫下篇文章的動力!
如果文章有錯誤或表達不好的地方,也請多多指教,我會儘速改進、修正。
1下 閱。
5–10下 你認為這篇文章還不錯。
11–20下 你認為這篇貼文對你很有幫助。
21–40下 你非常喜歡這篇貼文,覺得實用。
40–50下 希望我可以多分享關於前端工程相關的文章。
參考資料
大家好!
我是 Ken,一位前端經歷約2年的前端工程師,請多多指教。
拙作:關於React,那些我不知道的 系列
第一次參與鐵人,咬牙撐完30天,歡迎大家指教,未來我也會回去重新編排、整理。