摘要:前面一段時(shí)間對(duì)和兩者的關(guān)系感到比較困惑我使用的動(dòng)態(tài)語(yǔ)言揉合太多范式在這一點(diǎn)上很難做出明確透徹的區(qū)分不過(guò)經(jīng)過(guò)這段時(shí)間琢磨相對(duì)之前感覺(jué)要好一些了有了一些自己的想法后面自己的部分會(huì)有不少?zèng)]有驗(yàn)證的地方所以應(yīng)該當(dāng)成感想來(lái)看需要說(shuō)明我的經(jīng)驗(yàn)來(lái)自動(dòng)態(tài)語(yǔ)
前面一段時(shí)間對(duì) FP 和 OOP 兩者的關(guān)系感到比較困惑
我使用的動(dòng)態(tài)語(yǔ)言揉合太多范式, 在這一點(diǎn)上很難做出明確透徹的區(qū)分
不過(guò)經(jīng)過(guò)這段時(shí)間琢磨相對(duì)之前感覺(jué)要好一些了, 有了一些自己的想法
后面自己的部分會(huì)有不少?zèng)]有驗(yàn)證的地方, 所以應(yīng)該當(dāng)成感想來(lái)看
需要說(shuō)明, 我的經(jīng)驗(yàn)來(lái)自動(dòng)態(tài)語(yǔ)言(JavaScript), 相對(duì)靜態(tài)語(yǔ)言會(huì)有很多紕漏
當(dāng)然這種事情先 Google 是必需的, 我當(dāng)時(shí)微博標(biāo)記了兩份比較在意的說(shuō)明:
Functional programming vs Object Oriented programming
我摘錄的原文部分應(yīng)該很有建設(shè)性, 就不翻譯了:
When you anticipate a different kind of software evolution:
Object-oriented languages are good when you have a fixed set of operations on things, and as your code evolves, you primarily add new things. This can be accomplished by adding new classes which implement existing methods, and the existing classes are left alone.
Functional languages are good when you have a fixed set of things, and as your code evolves, you primarily add new operations on existing things. This can be accomplished by adding new functions which compute with existing data types, and the existing functions are left alone.
When evolution goes the wrong way, you have problems:
Adding a new operation to an object-oriented program may require editing many class definitions to add a new method.
Adding a new kind of thing to a functional program may require editing many function definitions to add a new case.
根據(jù)估計(jì)的未來(lái)代碼中是數(shù)據(jù)或者是操作為主, 會(huì)有一定的區(qū)分
面向?qū)ο筮m合在新系統(tǒng)中接入新的數(shù)據(jù), 函數(shù)式適合在原有代碼上增加新的方法
我覺(jué)得上邊說(shuō)的 functional 和純函數(shù)的編程可能還有差別..
另一份實(shí)在 Haskell 的 Wiki 上,
The Monad.Reader/Issue3/Functional Programming vs Object Oriented Programming
這里摘錄的是在文章當(dāng)中的一個(gè)引用:
To quote:
"The functional approach to programming is to ask "how is data constructed?". This leads to a style of programming where the data constructors are considered primitive, and where data-consuming code accordingly is defined by pattern-matching over these constructors. The object-oriented programmer instead starts out by asking "what can we do with the data?", which fosters the view that it is the data selectors that should be seen as foundational, and that the code of a data-producer consequently should be defined as an enumeration of implementations for these selectors."
What"s telling is the description of the effects (local and non-local) of different types of modification to the program:
"The functional style ensures that adding another data-consumer (a function) is a strictly local change, whereas adding a new data-producer requires extending a datatype with a new constructor, and thus a major overhaul of every pattern-matching function definition. Likewise, in object-oriented programming the addition of a new data-producer (a new class) is a cinch, while the introduction of another data-consumer means the extension of a record type with a new selector, a global undertaking with implications to potentially all existing classes."
不是完全理解, 大義應(yīng)該有很多相似的地方,
FP 中數(shù)據(jù)類型是根基, 很容易增加數(shù)據(jù)操作, 增加數(shù)據(jù)類型需要大范圍調(diào)整
面向?qū)ο螽?dāng)中定義數(shù)據(jù)應(yīng)有的操作, 增加操作會(huì)影響到大量數(shù)據(jù)擁有的方法(?)
麻煩的是在動(dòng)態(tài)語(yǔ)言當(dāng)中沒(méi)有 Java 也沒(méi)有 Haskell 那么多限制, 并不明確
所以看了上邊的解釋, 我其實(shí)還是有些糊涂, 雖然是我看到最明確的版本了
不過(guò), immutable 那些特性可不是在這里邊講的,
Functional Programming Patterns (BuildStuff "14)
另外還有一份 FP 的資料, 只看到 slide, 沒(méi)找到視頻
其中一張挺有意思, 就是 OOP 里各種范式, FP 都用函數(shù)解決掉了
我想說(shuō)是的, 困惑我的, 是 FP 和 OOP 在思維方式上的巨大差別
而隱藏在后邊的 immutable 特性, 在開(kāi)始的時(shí)候更讓我困惑
后面就開(kāi)始說(shuō)我的困惑和理解吧(確實(shí)網(wǎng)上的內(nèi)容我沒(méi)有理解透徹)
FP 和 OOP 不是截然對(duì)立的思維, 在編寫(xiě)中實(shí)際上和經(jīng)常相互滲透
OOP 當(dāng)中, 比如動(dòng)態(tài)語(yǔ)言隨時(shí)可能插入 FP 的 List 操作方法
而 FP 當(dāng)中, 也可能模擬 OOP 對(duì)數(shù)據(jù)封裝和抽象(網(wǎng)上看到 Scheme 有例子, 不熟悉)
在 FP 當(dāng)中, 很重要的概念是 Composable 和 Purity(可復(fù)合, 沒(méi)有副作用)
但 OOP 當(dāng)中并不是不允許組合操作和避免副作用, 同時(shí)這些是編程貫穿的主題
Node 腳本的代碼, 模塊化, 減少依賴, 建立在 OOP 之上, 說(shuō)法和 FP 并沒(méi)有太大區(qū)別
所以單純?cè)谟梅ㄉ系膮^(qū)別, 我任務(wù)應(yīng)該是由更為基本的規(guī)則引起的
加上排除語(yǔ)法, 排除類型, 我還是覺(jué)得 immutability 是最為重要的差別
換句話說(shuō), 一個(gè)名字, 或者參數(shù)一致的函數(shù), 每次調(diào)用的結(jié)果是否完全一樣
FP 做了這樣的限定, 導(dǎo)致編碼的難度上升, 需要模擬每次操作后狀態(tài)的改變
在 FP 中, 就是生成一份新的數(shù)據(jù), 通過(guò)高階函數(shù), 模擬對(duì)同一個(gè)名字進(jìn)行操作
但是首先, 共享變量名來(lái)進(jìn)行消息傳遞這一點(diǎn)變得挺困難(或者說(shuō)特殊)了
在 OOP 當(dāng)中, 我們期待把大的問(wèn)題拆解成幾個(gè)小的模塊分別解決
比如說(shuō), 為每個(gè)過(guò)程設(shè)定一些數(shù)據(jù), 封裝然后暴露一些接口, 出來(lái)
最終模塊直接通過(guò)調(diào)用接口, 相互發(fā)送接受消息獨(dú)立完成工作, 完成整個(gè)任務(wù)
考慮數(shù)據(jù) immutable 的話, 每個(gè)模塊內(nèi)部狀態(tài)就不能實(shí)現(xiàn)了
那么這部分狀態(tài)將被提取出來(lái)放到全局, 再作為參數(shù)傳回到模塊當(dāng)中
這時(shí)的模塊更像是 pipe 的概念, 整個(gè)程序的運(yùn)行就是在管道當(dāng)中流動(dòng)
一個(gè)好處是數(shù)據(jù)不再像 OOP 那樣存在多份, 需要設(shè)計(jì)機(jī)制去同步
后面是最近我在思考 Cumulo 實(shí)現(xiàn)的過(guò)程考慮到的和想到的問(wèn)題
這是我第一次拋開(kāi)框架寫(xiě)后端代碼, 剛一開(kāi)始被怎樣組織代碼所困擾
困擾之后我還是用 mutable 數(shù)據(jù)還消息來(lái)勾勒整個(gè)消息傳播的方案
嘗試之后我采用一個(gè)架構(gòu)圖描繪了數(shù)據(jù)怎樣在這個(gè)程序當(dāng)中流動(dòng)
也許我可以這樣思考程序, 將程序劃分為幾塊, 分別對(duì)應(yīng)功能:
數(shù)據(jù)結(jié)構(gòu), 初始的資源和狀態(tài) --> 這是一個(gè)適合機(jī)器的形態(tài)
交互的界面 --> 數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為適合人類編寫(xiě), 調(diào)試, 查看, 交互的形態(tài)
業(yè)務(wù)邏輯 --> 決定數(shù)據(jù)怎樣改變的操作的規(guī)則
架構(gòu) --> 操作或者事件, 怎樣正確有效更新整個(gè)程序范圍的資源和狀態(tài)
程序越大, 思考架構(gòu)越發(fā)困難, 特別是要照顧好多的細(xì)節(jié), 細(xì)節(jié)相互沖突
簡(jiǎn)化來(lái)說(shuō), OOP 似乎很容易想采用消息, 讓每個(gè)模塊以監(jiān)聽(tīng)的方式更新和同步
而在 FP, 沒(méi)有消息, 轉(zhuǎn)而采用定向的數(shù)據(jù)流動(dòng), 逐個(gè)地想做系統(tǒng)狀態(tài)進(jìn)行更新
現(xiàn)在我了解的, OOP 操作簡(jiǎn)單, 可是當(dāng)模塊繁多, 容易造成節(jié)奏紊亂, 難于調(diào)試
FP 則是不容易設(shè)計(jì)實(shí)現(xiàn), 現(xiàn)實(shí)世界狀態(tài)凌亂, 難以符合單向流的形式
另外我也注意到, 就是在微博上發(fā)的那條感想:
最近想起王垠那個(gè)比喻, 可變數(shù)據(jù)像 WIFI, 不可變數(shù)據(jù)像線, WIFI 方便多了. 可是從另一個(gè)角度看 WIFI 是短距離穩(wěn)定, 遠(yuǎn)了信號(hào)差, 線麻煩是麻煩, 遠(yuǎn)距離傳輸損耗小(也不能普通網(wǎng)線...). 可變數(shù)據(jù)不用面向?qū)ο竽菢臃庋b在局部進(jìn)行控制, 變量多了真心容易亂. 不可變數(shù)據(jù)呢門(mén)檻又高..
mutable 數(shù)據(jù), 如果被反復(fù)轉(zhuǎn)發(fā)傳送, 很可能會(huì)在某些操作當(dāng)中被更改
當(dāng)數(shù)據(jù)容易發(fā)生難以預(yù)料的更改, 構(gòu)建大程序也就成了麻煩了
因此對(duì)于 mutable 數(shù)據(jù), 在本地進(jìn)行封裝, 不直接對(duì)外暴露, 是極為合理的做法
這在 JavaScript 當(dāng)中, 對(duì)象被不斷引用共享, 直到出現(xiàn) bug, 是很可能發(fā)生的事情
那么思考大程序的話, mutable 數(shù)據(jù)是應(yīng)該盡量減少的方案
到目前為止, 我所能相對(duì)的構(gòu)建程序最讓我覺(jué)得建設(shè)性的是這個(gè)架構(gòu)圖
即便真心寫(xiě)到?jīng)]思路了, 好歹還能照著圖用拙劣的代碼補(bǔ)上一些功能上去
對(duì)著 FP 和 OOP 這些爭(zhēng)論了許久的功能思考不清楚, 只能按著圖上瞎寫(xiě)
希望能早點(diǎn)走出這篇迷霧吧..
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/11706.html
摘要:避免脆弱的基類問(wèn)題。紅牌警告沒(méi)有提到上述任何問(wèn)題。單向數(shù)據(jù)流意味著模型是單一的事實(shí)來(lái)源。單向數(shù)據(jù)流是確定性的,而雙向綁定可能導(dǎo)致更難以遵循和理解的副作用。原文地址 1. 你能說(shuō)出兩種對(duì) JavaScript 應(yīng)用開(kāi)發(fā)者而言的編程范式嗎? 希望聽(tīng)到: 2. 什么是函數(shù)編程? 希望聽(tīng)到: 3. 類繼承和原型繼承的不同? 希望聽(tīng)到 4. 函數(shù)式編程和面向?qū)ο缶幊痰膬?yōu)缺點(diǎn)? ...
摘要:前言最近花了不少時(shí)間接觸學(xué)習(xí)的函數(shù)式的編程方式,而后為了加深理解,又去折騰。不過(guò)幸運(yùn)的是,天生具備了函數(shù)式編程的基本元素,所以學(xué)習(xí)的起點(diǎn)不會(huì)太低。初接觸第一個(gè)實(shí)例,函數(shù)式編程是如何做一個(gè)番茄炒雞蛋的。 前言 最近花了不少時(shí)間接觸學(xué)習(xí)javascript的函數(shù)式的編程方式,而后為了加深理解,又去折騰haskell。 不同于人們比較熟悉的命令式編程,如面向?qū)ο缶幊蹋╫op),函數(shù)式編程(f...
摘要:我們作為前端開(kāi)發(fā),都應(yīng)該具有這樣的能力。那么如何才能降低業(yè)務(wù)開(kāi)發(fā)的復(fù)雜度呢細(xì)分組件都說(shuō)模塊化開(kāi)發(fā),其實(shí)在,這些思想規(guī)范之前就已經(jīng)有模塊化開(kāi)發(fā)的規(guī)范了,雖然標(biāo)準(zhǔn)從然后隔了年才有了,在那年基本都是函數(shù)式開(kāi)發(fā),一切皆函數(shù)。 優(yōu)秀的程序員總是能優(yōu)雅的組織自己的代碼,清晰的編寫(xiě)思路,合理的組織結(jié)構(gòu)劃分,從小的功能組件,到大的模塊結(jié)構(gòu),都能通過(guò)合理的巧妙的搭配,不僅能化復(fù)雜為簡(jiǎn)單,更能提升代碼運(yùn)行...
摘要:我們作為前端開(kāi)發(fā),都應(yīng)該具有這樣的能力。那么如何才能降低業(yè)務(wù)開(kāi)發(fā)的復(fù)雜度呢細(xì)分組件都說(shuō)模塊化開(kāi)發(fā),其實(shí)在,這些思想規(guī)范之前就已經(jīng)有模塊化開(kāi)發(fā)的規(guī)范了,雖然標(biāo)準(zhǔn)從然后隔了年才有了,在那年基本都是函數(shù)式開(kāi)發(fā),一切皆函數(shù)。 優(yōu)秀的程序員總是能優(yōu)雅的組織自己的代碼,清晰的編寫(xiě)思路,合理的組織結(jié)構(gòu)劃分,從小的功能組件,到大的模塊結(jié)構(gòu),都能通過(guò)合理的巧妙的搭配,不僅能化復(fù)雜為簡(jiǎn)單,更能提升代碼運(yùn)行...
摘要:我們作為前端開(kāi)發(fā),都應(yīng)該具有這樣的能力。那么如何才能降低業(yè)務(wù)開(kāi)發(fā)的復(fù)雜度呢細(xì)分組件都說(shuō)模塊化開(kāi)發(fā),其實(shí)在,這些思想規(guī)范之前就已經(jīng)有模塊化開(kāi)發(fā)的規(guī)范了,雖然標(biāo)準(zhǔn)從然后隔了年才有了,在那年基本都是函數(shù)式開(kāi)發(fā),一切皆函數(shù)。 優(yōu)秀的程序員總是能優(yōu)雅的組織自己的代碼,清晰的編寫(xiě)思路,合理的組織結(jié)構(gòu)劃分,從小的功能組件,到大的模塊結(jié)構(gòu),都能通過(guò)合理的巧妙的搭配,不僅能化復(fù)雜為簡(jiǎn)單,更能提升代碼運(yùn)行...
閱讀 2243·2019-08-30 10:51
閱讀 796·2019-08-30 10:50
閱讀 1479·2019-08-30 10:49
閱讀 3140·2019-08-26 13:55
閱讀 1608·2019-08-26 11:39
閱讀 3424·2019-08-26 11:34
閱讀 1952·2019-08-23 18:30
閱讀 3390·2019-08-23 18:22