告別相殺!面向對象和函數式編程共存

作為結構化編程的一種,函數式編程正受到越來越多的重視。而作為常用的一種程序開發方法,面向對象編程為程序設計帶來了更強的靈活性和可維護性。那麼兩者相較而言,究竟有著什麼樣的區別?應用場景又有何不同?

告別相殺!面向對象和函數式編程共存

作者 | Reginald Braithwaite

譯者 | 彼得

責編 | 屠敏

出品 | CSDN(ID:CSDNnews)

簡單來說,函數式編程(“FP”)和麵向對象編程(“OOP”)具有相似的表達能力和封裝能力,它們都可以將程序封裝成可以自由組合的較小部分。

但是這兩個“思想流派”之間的還是存在著很多區別。其中最大的差別在於對數據和數據操作之間關係的不同處理。

FP 和 OOP 的區別

面向對象編程的核心思想是將數據和對數據的操作進行緊密耦合:一個對象除了擁有自己的數據,還擁有對數據操作的實現。這些對象對外隱藏這些具體的信息。它們通過接口,進行響應的方法或消息來和其它對象交互。 因此,在面向對象編程中,抽象的核心是數據,這些數據通過接口等API對外展示。

在面向對象編程中,人們所作的主要工作就是創建新對象或者通過增加新方法來擴展現有對象。

函數式編程的核心原則是數據只與功能進行鬆散的耦合。你可以對同一個數據結構定義不同的操作。在這裡,抽象的核心是函數,而不是數據結構。函數隱藏了它們的具體實現、編程語言的抽象以及函數之間進行組合或表達的方式,例如泛型函數或組合函數。

在函數式編程裡,人們的主要工作就是編寫新函數。

在自然界中,如果熊和鱷魚之間爆發衝突,地形會決定雙方爭鬥的結果。

對於函數式編程和麵向對象編程來講,它們在什麼情況下,其中的一個比另一個更合適呢? 因為這是一個實用的博客,所以,我將忽略所有理論上的考慮因素,例如機械地推理代碼的能力和實施項目時的限制條件,比如資源不足,時間不足等。

在實際的環境中,你認為這兩者中的任何一個會是壓倒性的“贏家”嗎?這個可能得花些時間好好想想。在你思考的時候,我會先享受一杯濃咖啡...

告別相殺!面向對象和函數式編程共存

何時使用 FP?何時使用 OOP?

當然,答案是,業務編程主要是由功能模型,而不是面向對象模型進行控制的。 這是一個讓你覺得驚訝的答案嗎?如果你的頭腦裡只考慮Java,C ++,C#和Ruby,也許這個答案會令你覺得奇怪。

你知道,所有的面向對象通常都是對訪問各種支持 SQL 的數據庫的模擬。 SQL是一種非常實用的數據庫操作的腳本語言。你可以對數據庫進行設定,使得對它所有表格的訪問都是通過PL/SQL的存儲過程完成的,但是因為這樣會產生嚴重的編程問題,所以,實際中很少這樣做。

關係型數據庫的主要好處是它可以滿足未來的需求。如果你需要新的報告,那隨時可以創建它們。許多不同的應用程序可以與同一個數據庫進行通信。這些程序之間的數據一致性可以通過數據庫的約束條件來強制實現。

如果你仔細研究一下,就會發現數據庫本身其實就是一個大的數據結構,而應用程序則是對數據庫中的數據進行的操作。幾乎每個商務應用的核心都是一個大的功能性的數據庫,也就是一個數據結構和一系列對數據進行的操作。

OOP 使用場景

但是,我們在應用程序中包含對象只是為了符合潮流嗎? 或者說,我們在編寫應用程序時做的事情和創建數據庫時做的事情有什麼本質上的不同嗎?

這個問題答案就在於面向對象和使用數據庫各自有什麼好處。

一個精心設計的面向對象的架構可以輕鬆改變對象的組合方式。 隱藏實現和解耦使您可以輕鬆地更改對象之間的關係。使用面向對象本身,並不會使添加新的操作變得更容易。如果在代碼中發現雙重調度和訪問的問題,你就能夠真正地感受到這一點。

但是,假如有一個訂單處理系統,如果你的業務規則發生了變化,需要相應地修改訂單的處理流程,你就會發現面向對象的優勢。 那些不受這些變化影響的對象和受影響的對象是互相隔離的。

另一方面,精心設計的數據庫會使添加新查詢和操作變得很容易。如果你需要以新的方式查看現有的數據或者如果您需要向數據添加新的更新類型,它都能夠很好地處理。 客戶端應用程序在邏輯上與提高性能的索引等問題互相隔離。

這樣做並不會使改變關係變得更容易。如果更改管理結構,使報表和管理器的關係從一對一變為多對多的矩陣管理結構,那麼這種更改將破壞許多應用程序。

因此,如果我們記錄了所有在商業軟件中需要實現的內容,我們需要把那些代表長期的、相對不變的關係的東西放在數據庫中保存,把那些代表短期操作、隨著時間的推移而發展和變化的內容,在應用程序中實現。

應用程序的堆棧通常比數據庫的堆棧高四倍,這很正常。事情確實發生了變化,企業也應該不斷地學習、成長和發展。

FP 的應用場景

那麼,我們通常所說的函數式編程,也就是用多範式語言中的函數式編寫的代碼怎麼做?我們可以簡單地將面向對象程序改寫為作用於相對靜態的數據結構上的操作集合嗎?

通常來說,這樣都是可以的。但同時必須優先考慮這種關係的相對壽命。那些本身不太可能改變,但是被經常改變的實體所操作的內容應該以一種函數式編程來實現,而那些相對經常改變的東西可以用面向對象的風格來實現。

如果每個管理器都有一個或多個報表,並且每個報表都只有一個管理器,那麼將這種關係通過API進行隱藏就幾乎沒有什麼好處了,因為在API中,管理器對象以隱含的方式來委託操作。對於這種關係,最好的處理方式是先構造數據,然後對數據進行操作。

但是關於運輸成本的規則很可能會改變,所以,最好你把它封裝起來,以便程序的其它部分不被將來可能的變化所影響。

因為好的軟件需要滿足不止一種需求,所以,它們一般都包含這兩種風格。

原文: http://raganwald.com/2013/04/08/functional-vs-OOP.html

作者簡介: Reginald Braithwaite,他的興趣包括構造超現實數字,析構空值,以及慶祝編程的樂趣。他是JavaScript Allongé、CoffeeScript Ristretto和raganwald.com的作者。他在pagerduty開發用戶體驗.

本文為 CSDN 翻譯,如需轉載,請註明來源出處。

相關推薦

推薦中...