你忘掉OOP的速度越快,你和你的軟體就越好
也許這只是我的經驗,但物件導向程式設計似乎是一種預設的,最常見的軟體工程範例。
我花了好幾年才打破它的咒語,並清楚地瞭解它是多麼可怕和為什麼。由於這種觀點,我堅信人們必須瞭解OOP的錯誤,以及他們應該做些什麼。
資料比程式碼更重要
所有軟體的核心都是關於操縱資料以實現某個目標。目標決定了資料的結構,資料結構決定了必要的程式碼。
這部分非常重要,所以我會再說一遍。goal -> data architecture -> code。一定不要在這裡改變順序!在設計軟體時,首先要弄清楚你想要實現什麼,然後至少大致考慮資料架構:資料結構和有效實現它所需的基礎架構。然後編寫程式碼以便在這種架構中工作。如果目標發生變化,請更改架構,然後更改程式碼。
根據我的經驗,OOP的最大問題是鼓勵忽略資料模型架構並應用無意識的模式將所有內容儲存在物件中,承諾一些模糊的好處。如果它看起來像一個Class的候選人,它就會進入一個Class。我有Customer嗎?它進入了class Customer。我有渲染上下文嗎?它進入了class RenderingContext。
開發人員的注意力不再是建立良好的資料架構,而是轉向發明“好”類Class,它們之間的關係,分類法,繼承層次結構等等。這不僅是一種無用的努力。這實際上是非常有害的。(banq注:資料型別比資料內容更重要,形式比內容更重要,形式邏輯減少人類的自身錯誤,不是所有東西必須實指到內容才有意義,羅素維根斯坦的貢獻在於此)
複雜性
OOP程式往往只會增長而不會縮減,因為OOP鼓勵它。而如果在明確設計資料架構時,目標通常是支援我們軟體目標的最小可行資料結構集。(banq注:複雜性不是個數多,而是個數之間千絲萬縷的關係複雜,個數複雜不可怕,可以透過增加人數對付,關係複雜,人數再多也沒用,作者在這裡沒有認識到複雜性起源於關係複雜,而是數量多少)
圖表無處不在
因為OOP需要在許多很小的封裝物件中散佈所有內容,所以對這些物件的引用數量也會爆炸。OOP需要在任何地方傳遞長引數列表或直接儲存對相關物件的引用以使其快捷。(banq注:DDD聚合正是解決這些數量多的小物件)
你class Customer有引用order,class Order反之亦然。class OrderManager持有對所有的引用Orders,從而間接引用所有人Customer。一切都傾向於指向其他一切,因為隨著時間的推移,程式碼中有越來越多的地方需要引用相關的物件。(banq注:作者這裡意識到關係複雜,但是沒有認識到透過分析需求找到聚合,找到整體與部分的關係,比如Order是一個聚合根,Customer也是聚合根,兩者不能直接引用,可透過值物件嵌入彼此,透過非同步事件更新同步)
你想要一個香蕉,但你得到的是一隻拿著香蕉和整個叢林的大猩猩。
OOP專案看起來像是一個巨大的義大利麵條圖,而不是一個設計良好的資料儲存,它們指向彼此的物件和採用長引數列表的方法。當您開始設計Context物件只是為了減少傳遞的引數數量時,您就知道您正在編寫真正的OOP企業級軟體。
(banq注:作者這裡把OOA OOD和OOP混為一談了)
跨領域的問題
一個簡單的資料轉換變成了一堆笨拙的,交織在一起的方法,除了封裝的OOP教條之外,它們無緣無故地相互呼叫。在混合中新增一些繼承為我們提供了一個很好的例子,說明了什麼是陳規定型的“企業”軟體。
物件封裝是精神分裂症
我們來看看封裝的定義:
封裝是一種物件導向的程式設計概念,它將運算元據的資料和功能繫結在一起,並保護其免受外部干擾和誤用。資料封裝導致了重要的OOP資料隱藏概念。
實際上,對物件或類的粒度進行封裝通常會導致程式碼試圖將所有內容與其他內容(來自自身)分開。它產生了大量的樣板:getters, setters, 多個構造器,奇怪的方法, 所有這些都試圖防止不太可能發生的錯誤,其規模太小而無法實現。我給出的比喻是在你的左口袋上放一個掛鎖,以確保你的右手不能從中取出任何東西。
不要誤解我的意思 - 強制執行約束,特別是在ADT上通常是一個好主意。但是在OOP中,所有物件的相互引用,封裝通常都沒有實現任何有用的東西,並且很難解決跨越許多類的約束。
在我看來,類和物件太過細化,而專注於隔離,API等的正確方式是“模組”/“元件”/“庫”邊界。根據我的經驗,OOP(Java / Scala)程式碼庫通常是不使用模組/庫的程式碼庫。開發人員專注於為每個類設定邊界,而不必過多考慮哪些類組合成一個獨立,可重用,一致的邏輯單元。
有多種方法可以檢視相同的資料
OOP需要一種不靈活的資料組織:將其分成許多邏輯物件,這些物件定義了一種資料體系結構:具有相關行為(方法)的物件圖。但是,有多種邏輯表達資料操作的方法通常很有用。
如果程式中的資料以表格、面向資料的形式儲存,則可以有兩個或更多模組,每個模組在相同的資料結構上執行,但是以不同的方式執行。如果使用方法將資料拆分為物件,則不再可能。
這也是物件關係阻抗不匹配的主要原因。雖然關係資料架構可能並不總是最好的,但它通常足夠靈活,能夠使用不同的範例以多種不同的方式對資料進行操作。但是,OOP資料組織的嚴格性導致與任何其他資料體系結構不相容。
表現不佳
在許多小物件之間分散的資料的組合,大量使用間接和指標以及首先缺乏正確的資料架構導致差的執行時效能。
該怎麼辦?
我認為沒有銀彈,所以我現在只描述它在我的程式碼中是如何工作的。
首先,資料考慮是第一位的。我分析了輸入和輸出,它們的格式,數量。如何在執行時儲存資料,以及如何保持資料:必須支援哪些操作,速度(吞吐量,延遲)等等。
通常,對於具有任何大量資料,設計是接近資料庫的。也就是說:會有一些像DataStoreAPI 這樣的物件暴露出查詢和儲存資料所需的所有操作。資料本身將採用ADT / PoD結構的形式,資料記錄之間的任何引用都將是ID(數字,uuid或確定性雜湊)的形式。在引擎蓋下,它通常非常類似於或實際上由關聯式資料庫支援:透過索引或ID儲存大量資料的Vectr或HashMaps,以及快速查詢等所需的“索引”的一些其他。其他資料結構如LRU快取記憶體等也放在那裡。
大部分實際程式邏輯引用這些DataStores,並對它們執行必要的操作。對於併發和多執行緒,我通常透過訊息傳遞,actor模式粘合不同的邏輯元件。actor的例子:stdin閱讀器,輸入資料處理器,信任管理器,遊戲狀態等。這樣的“actor”可以實現為執行緒池,管道元素等。如果需要,他們可以擁有自己的DataStore或與他人共享一個“演員”。
這樣的架構給了我很好的測試點:DataStores可以透過多型實現多個實現,透過訊息進行通訊的actor可以單獨例項化並透過訊息的測試序列來驅動。
重點是:因為我的軟體在具有如概念客戶和訂單的域中執行,但是並不意味著有任何Customer類,與其相關的方法。恰恰相反:Customer概念只是一個或多個表格中的一堆資料DataStore,“業務邏輯”程式碼直接運算元據。
軟體工程中對OOP的批評並不是一件簡單的事情。我可能無法明確闡述我的觀點和/或說服你。如果你仍然感興趣,這裡有一些連結給你:
- Brian Will的兩個影片:物件導向的程式設計是糟糕的,物件導向的程式設計是垃圾:3800 SLOC示例
- CppCon 2018:Stoyan Nikolov“OOP已死,面向資料的長期設計”,作者精美地介紹了一個示例OOP程式碼庫並指出了它的問題。
- 在wiki.c2.com上反對Oop的引數,以獲取針對OOP的常見引數列表。
- 物件導向程式設計是一項代價高昂的災難,必須由勞倫斯·克魯納(Lawrence Krubner)結束 - 這篇文章很長並且深入到許多想法中
banq注:OOP與OOA/OOD是不一樣的,總體來說OO是從便於人類的角度進行程式設計,適合以專案為主的工程,不一定適合產品級別。但是專案與產品的區別是:專案更加能夠跟隨需求變化,因為如果需求規範一旦不變,就如同水結成冰,走在冰上就很容易,如果你有微信這樣級別的產品經理,儘管微信連一個簡單首頁清屏的功能都沒有,照樣是顛覆一群人的革命級別產品,這樣強勢的產品只有客戶跟從你,但是更多情況下,我們做軟體的是要跟從客戶,客戶的需求說變就變,而物件化方法背後其實是維根斯坦的邏輯概念與邏輯分析在支撐,是基本的世界觀和方法論,模式也是可以使用數學來解釋。當然這樣從利於人的角度實現的程式碼不利於計算機執行,所以,在人和機器之間你得根據是專案還是產品進行傾斜。
相關文章
- 用了ZAP,你的軟體就安全了嗎?
- 滑鼠按鍵響應越快越好嗎?
- 勒索軟體進化:你敢不掏錢,就曝光你隱私
- 你知道和你不知道的選擇排序排序
- 你知道和你不知道的氣泡排序排序
- 你在過度測試你的軟體嗎?
- 10個你在讀軟體工程學位時就應該知道的祕密軟體工程
- 你的.vue檔案就已經是你的文件了Vue
- 防禦指南-當你得知你的軟體正在被除錯除錯
- 由軟體構造引申的OOP與POP的心得體會OOP
- 好用的爬蟲軟體?動態ip軟體告訴你爬蟲
- 讓你的軟體永生的7個規則
- 你應該知道的10種軟體工具
- 你還記得大明湖畔的oop原則嗎?OOP
- 當軟體更改的成本代價越來越低,你的產品就會越來越強!!!
- 你的軟體招人討厭的4大原因
- 學會以下幾個軟體你就會3D遊戲模型了3D遊戲模型
- 軟體之間有什麼關係?看完這個你就暈了
- 這樣設定你的蘋果筆記本,並撐握這些小技巧,讓你的MAC越來越好用蘋果筆記Mac
- 幾你需要熟練掌握的辦公軟體
- 六款你需要了解的實用軟體
- 釋出你的開源軟體到 Ubuntu PPAUbuntu
- 你不知道的軟體測試那些事?
- 分享5款有趣的軟體,你都知道嗎?
- 分享5款讓你工作事半功倍的軟體
- 使用 CDN 加速你的網站開啟速度網站
- DNS 是如何影響你衝浪速度的?DNS
- 設計的軟體測試用例是否越詳細越好?
- [軟體人生]如果你的領導比你能力差,你會怎麼辦?
- 做自媒體需要的軟體有哪些?這個軟體你肯定用過!
- 軟體開發!=軟體工程 你真的希望如此嗎?軟體工程
- 寫開源軟體之前請先確認你知道你的版權權利
- 軟體研發的這些誤區,你中了嗎?
- 你必須瞭解的大資料分析軟體大資料
- 這10款好用的Windows軟體,你必須知道!Windows
- 軟體測試的五個目的,你知道幾個?
- 你的Android裝置有惡意軟體嗎?Android
- 賀炘:你的軟體測試基因是什麼?