本文是我在團隊內部分享的ppt中摘出來的,所以可能節奏有點快。
用了Swift很久也沒有踏入POP的大門
並且充滿了誤解
- POP是Swift提出的一個全新理念
- POP就是狂用Protocol
- POP站在OOP的鄙視鏈上游
從電視劇的最後一集開始看,所以看不懂
之後改變了學習策略
- 【溯源】程式設計正規化發展歷史(電視劇的第一集)
- 【橫評】別的語言也有相似概念
- 【解構】分析Swift原始碼的設計
最初的程式設計正規化—結構化程式設計
最初的語言充滿了goto,goto是強大的,但是代價是巨大的
最初的程式設計正規化—結構化程式設計
直到有人提出結構化程式設計,來限制goto的權力
這幾個基本的控制流奠定了後世各種語言的基調
但是結構化程式設計只解決了函式執行的複雜度,而資料還是亂的不行
這促使一個新的理念誕生了:Object-Oriented Programming
一個偉大思想的誕生
物件導向有三個特性解決過去混亂不堪的資料存放,也被稱為OOP三原則:
-
資料抽象 Abstraction
資料封裝提供了一個資訊隱藏的機制,讓一個類黑盒化,這種設計減少了人們理解一塊程式碼的難度。 -
繼承 Inheritance
繼承提供了共享程式碼的方式,不同於另一個世界線的原型鏈。 -
多型性 Polymorphism
多型提供了針對父類的演算法可以直接應用到子類上。
過去的資料存放雖然混亂,但是非常靈活,OOP則對這種能力加以限制(如同控制流對goto的限制)
簡單和靈活的辯證關係
成也繼承,敗也繼承
OOP在蓬勃發展之後,出現了兩個分支,單一繼承和多繼承。前者代表是JAVA,後者是C++。
多繼承首先暴露出很嚴重的問題:著名的The Diamond Problem
其次,多繼承會讓你的程式碼結構混亂不堪
單一繼承雖然避免了這個問題,但是他引起另一個問題:不夠用!從多個類共享程式碼是一個鋼需!
一般的單一繼承語言只好選擇組合(composition),但是組合引起不必要的層級和依賴。主要是用起來很麻煩。
所以Java在第8版的時候選擇一條少有人走的路,Mix-in正規化,Java裡叫介面擴充套件(interface extension)。
Mix-IN是何方神聖?
Mix-in也是比較古老的正規化,它是被近代的Ruby(1995)發揚光大。
Mix-in的解決思路是:既然多繼承不好,但是想共享程式碼,那麼就用重重約束允許某種受限的多繼承存在。
於是簡單和自由的取捨又出現了
Mix-in一般分為traits和介面擴充套件兩個流派,Ruby選擇是前者,而Java選擇加強他本來就有的pure interface,讓介面可以提供預設的方法實現,來完成和traits一樣的功能性。(這一點和Swift的發展路線是一致的)
實現Mix-in只需要這一個小小的改動,但是對整個軟體設計模式都產生了深遠影響。
Mix-IN加入後的新世界
因為Mix-in提供了功能實現,這些程式碼就可以當做一種元件,組合到任意的類裡,從而實現了類似多繼承的程式碼複用。
軟體架構不再是一塵不變的繼承+類組合,從此有了新的樣貌:
重點來了
Swift的POP就是Mix-in -> Java interface extension的延續,只不過改了名字叫protocol extension。
那充其量也就是Java的那種樣貌,怎麼能上升到Oriented的程度?
答案都在Swift的原始碼中。
Swift的野望
我們來看一下Swift對Int的實現
你沒看錯,除了Int本人是一個struct(甚至不是class)其它全都是Protocol! 誰還敢說不是Protocol-Oriented
歸根結底:Swift的POP到底是在說什麼?
Mix-in既然已經被證實是OOP的一個好的發展方向,Swift不但選擇引入Mix-in,並且把它提高到核心教義,並且用這個思想搭建起Swift語言本身。
可以說Swift不是Java那樣覺得Mix-in是OOP的補充,而是試圖證明Mix-in可以代替Class Inheritance成為優選的正規化。
連名字都改了不是嗎,OOP都不要了。
消除誤解
-
POP是Swift提出的一個全新理念
不是,他是古老的Mix-in,並且是被很多現代語言應用。 -
POP就是狂用Protocol
不是,重點在於繼承架構是否是圍繞Protocol設計的。 -
POP站在OOP的鄙視鏈上游
POP本身就是OOP的演化,只是在OOP(99%)的基礎上又邁進了一小步(1%)。
Swift走出的新路:POP之後的mix-in
通過Swift原始碼結構可以看出一個POP的軟體產生了大量的元件
具體型別(class/struct/enum)用來組合各種元件
甚至核心邏輯也是某一級的Protocol來組合,而具體型別只是一個能new出來的門面。
軟體設計的重心不再是建模物件,而是劃分能力。
POP符合程式語言的發展趨勢
父類和協議是OOP能提供的最高階抽象。他們是類的元型別。
POP提倡的就是在更高抽象層級上程式設計。
畢竟,越遠離goto,程式碼就越簡單。