面向協議程式設計的一些思考

darrenzheng發表於2019-02-27

本文是我在團隊內部分享的ppt中摘出來的,所以可能節奏有點快。

用了Swift很久也沒有踏入POP的大門

並且充滿了誤解

  • POP是Swift提出的一個全新理念
  • POP就是狂用Protocol
  • POP站在OOP的鄙視鏈上游

從電視劇的最後一集開始看,所以看不懂

之後改變了學習策略

  • 【溯源】程式設計正規化發展歷史(電視劇的第一集)
  • 【橫評】別的語言也有相似概念
  • 【解構】分析Swift原始碼的設計

最初的程式設計正規化—結構化程式設計

最初的語言充滿了goto,goto是強大的,但是代價是巨大的

via http://ziogeek.com/wp-content/uploads/2013/07/spaghetti.jpg

最初的程式設計正規化—結構化程式設計

直到有人提出結構化程式設計,來限制goto的權力

面向協議程式設計的一些思考

這幾個基本的控制流奠定了後世各種語言的基調

但是結構化程式設計只解決了函式執行的複雜度,而資料還是亂的不行
這促使一個新的理念誕生了:Object-Oriented Programming

via http://www.kamyacademy.com/wp-content/uploads/2014/01/object-orientated-programming-langs.png

一個偉大思想的誕生

物件導向有三個特性解決過去混亂不堪的資料存放,也被稱為OOP三原則:

  • 資料抽象 Abstraction
    資料封裝提供了一個資訊隱藏的機制,讓一個類黑盒化,這種設計減少了人們理解一塊程式碼的難度。

  • 繼承 Inheritance
    繼承提供了共享程式碼的方式,不同於另一個世界線的原型鏈。

    JS原型鏈
  • 多型性 Polymorphism
    多型提供了針對父類的演算法可以直接應用到子類上。

過去的資料存放雖然混亂,但是非常靈活,OOP則對這種能力加以限制(如同控制流對goto的限制)

簡單和靈活的辯證關係

via https://www.success.com/sites/default/files/styles/article_main/public/main/articles/Find%20Balance.jpg?itok=pQrQxtxY

成也繼承,敗也繼承

OOP在蓬勃發展之後,出現了兩個分支,單一繼承和多繼承。前者代表是JAVA,後者是C++。
多繼承首先暴露出很嚴重的問題:著名的The Diamond Problem

via https://en.wikipedia.org/wiki/Multiple_inheritance

其次,多繼承會讓你的程式碼結構混亂不堪

via http://public.beuth-hochschule.de/~solymosi/veroeff/objektdiagramme/bilder/Multip2.jpg

單一繼承雖然避免了這個問題,但是他引起另一個問題:不夠用!從多個類共享程式碼是一個鋼需!

一般的單一繼承語言只好選擇組合(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提供了功能實現,這些程式碼就可以當做一種元件,組合到任意的類裡,從而實現了類似多繼承的程式碼複用。

軟體架構不再是一塵不變的繼承+類組合,從此有了新的樣貌:

單一繼承樹+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,程式碼就越簡單。

相關文章