模式的模式:從設計模式到元模式
經歷了一番買書、讀論文、讀代碼,我發現了以前對於模式的理解不夠深刻。也因此呢,這篇文章就是用來記錄一些缺乏的東西,諸如於模式語言、模式的模式等。
PS:爲了方便閱讀,本文的書名使用都是簡寫模式,全稱在最後的相關資料中。
模式重談
爲了避免出現類似於 Datum 是最好的語言這一類的問題,在那之前,我得先闡述一下對於模式的看法:
-
模式是對於慣用方式的總結,不限於編程,有相當多的人習慣了使用各種設計模式,但是他並不知道這是何種模式。它是一個概念字表,用於快速溝通。
-
模式是解決方案,滿足錘子定律,只有遇到特定的問題時,你纔會需要它。
-
模式是適用於特定場景的,大部分的模式對於當前所處的系統是無用的,往往只有少數的模式是適合的。
-
模式是知識體系的展現,掌握模式的多少,更多的說明見多識廣,並不一定代表真實的代碼水平和能力。
-
模式需要刻意練習,學習模式是一個漫長的過程,所以總會遇到理解解決、使用錯誤的情況,不要擔心。
-
模式種類繁多,計算機行業普遍認同的是:模式的起源是亞歷山大的《建築的永恆之道》。在更早的時間裏,也還有對應的總結,但是這裏是最體系化的技巧。
除了設計模式之外,我們所處的行業還有大量的其它模式:
-
**容器設計模式。**應對於雲原生應用下一系列複雜的分式場景,Google 的工程師發表了相關的論文對此進行總結,常見的有 Sidecar、Adapter、Ambassador 等。
-
**架構模式。**架構模式是在給定上下文中解決軟件架構中常見問題的通用,可重用的解決方案。除此,一些常見的架構風格,如微服務、事件驅動架構等,從大類上來說也被歸納到架構模式中。
-
……
所以,你會發現這些模式只是人們對於慣用法的總結。
尋找模式
回過頭來看,當我們會發現進入一個新的領域,進行相關領域的架構設計之時,我們會不斷搜尋各類的資料,而後再去貼合到設計中去。實際上呢,我們是在尋找該領域的模式,有了這些模式,便可以照貓畫虎的設計一個系統,而不會出現太大的問題。
運氣好的情況下,我們甚至於能比在這個領域的大多數人做得更好 —— 因爲我們所掌握的是解決這一類問題的模式。
這時,我們已經有一個很有優勢性的套路,以幫助我們更好地進入新的領域。但是呢,作爲一個新的領域的初來者,往往不知道到底應該採用哪一種模式,也不確定模式之間存在何種關係。
相關書籍:《設計模式》
模式歸類:目錄、集合、倉庫
在一個軟件系統中,模式很少獨立存在,往往是多個模式相互組合,用於解決特定的問題。而其中的一種組織方式的模式就是模式集合。隨後,根據不同的需求,再對進行分門別類。如《POSA 5》所介紹的幾種方式:
-
即時(ad hoc)組織。
-
根據層次劃分:根據抽象、粒度和規模的層次劃分。
-
根據領域組織:電信、金融、電子商務等。
-
根據分區組織:歸屬於架構的哪一部分。如層、階層(tier)、組件和包都是分區的例子
-
根據意圖組織:如 POSA、GoF 的 23 種設計模式、DDD
-
……
接着,讓我們來看幾個分類示例。
設計模式的組織
在《設計模式》一書中,引入的概念是『設計模式空間』,在這裏它們被分爲了三大類:
-
創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。
-
結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
-
行爲型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式
其劃分的兩條準分別是: 目的準則,用來完成什麼工作;範圍準則,指定的模式是用於類還是用於對象。
DDD 的組織
《領域驅動設計》一書其中也是一本模式合集,這就是爲什麼這本書不易於讀懂的原因之一。另外一個原因則是,翻譯這本書的人沒有理解好什麼是統一語言。
在 《領域驅動設計》 一書以多種形式組織了模式,依次的四個部分是(PS:個人臨時總結):
-
運用領域模型 —— 『模型知識提取的模式』
-
模型驅動設計的構造塊 —— 『模型設計的模式』
-
通過重構來加深理解 —— 『模型優化的模式』
-
戰略設計 —— 『模型邊界劃分的模式』
而這個順序其實也是我們在實施 DDD 過程中的設計過程,而後再進行層次化的組織,如『戰略設計』部分根據不同的意圖,又分爲不同的合集:
-
保持模型的完整性,如限界上下文、上下文地圖等
-
精煉:核心域、通用域等
-
大型結構:演化秩序(Evolving Order)、系統隱喻等
所以從結構上來看,《領域驅動設計》是一本由小而大的書,閱讀難度略大,需要一定的經驗。
模式分類的意圖
我們把『如何應用設計模式看作是一個問題域』,那麼模式分類就是在這個問題域裏的一種解決方案。
在計算機的不同的複雜領域裏,如並行編程、架構設計等等,它們本身是包含了大量的模式。而有了對於這些模式的進一步分類,對於我們應用模式會有更大的幫助 —— 至少在應對同一個次級問題時,我們可以尋找可能的替代模式。
不過呢,多數時候,我們往往不知道的是:我們遇到的問題是什麼?
角落裏的模式語言
如 《POSA 5》所定義的一樣:模式語言與具體領域高度相關,並且能對這一類系統提供具體而周全的引導,具體包括以下幾項:
-
要解決的主要問題有哪些?
-
這些問題應該以什麼樣的先後次序解決?
-
解決一個給定問題,有什麼可用的替代解決方案?
-
怎樣處理問題之間的依賴性?
-
在有 “周邊” 問題存在的情況下,怎樣最有效地解決單個問題?
簡單來說,模式語言針對於某個特定的問題(如並行編程)所抽象的模式,幷包含了他們之間的關係等,能用於系統性地解決這一類問題。
書中還提到 了 Gerard Meszaros 的觀點 “模式語言可以用來指導生手創建系統”。Aha,這不就是我們想要的東西嗎?作爲一個進入新領域的新人,我們需要這麼一個模式語言。儘管模式語言可以幫助我們解決這一類的問題,但是它也意味着它自身需要:充分覆蓋、進展可持續、緊密集成。依照這一系列的前提,它意味着設計這個模式語言的人應該是業內專家,並且模式本身應該是不斷演進的。
因此,當我們把如何實施和使用模式看作是我們的問題時,那麼模式語言解決這一類問題的模式。
分佈式計算的模式語言
《POSA》系列大概是在中文世界 裏,我們所能找到的最好的資料。因此,這裏再次以《POSA 4》作爲例子,《POSA 4》全稱是《面向模式的軟件架構:分佈式計算的模式語言》。
先來看圖(圖中的圈內表示的是問題域,連續表示的是他們的關係,每個問題域下包含了相關的模式):
POSA Pattern Language
舉例來說開頭的『From Mud to Structure』(從混沌到結構)就是一個大的問題域,對應於這個問題域則包含了一系列的模式,如:MVC、分層、PAC、微內核等。同時,針對於這個問題題來說,如果我們還要數據庫訪問,那麼我們從數據庫訪問中獲得對應的模式,以此來完善我們的設計。
然後,在我們進入了具體的模式 / 問題域之後,它還詳細介紹瞭如何實現對應的模式。如分層:
POSA Layer
有了這系列的配合,我們便可以完善整個系統的設計。
微服務的模式語言
接着,讓我們來看看《微服務架構設計模式》中關於微服務的架構模式概述:
微服務模式語言
從上圖中,我們可以看到由 Chris Richardson 整理的這個微服務模式語言,對語言進行了多層的分類,並指明瞭它們之間的關係。頗爲遺憾的是這個模式語言只包含了關係,缺少了一些相關關係的描述。
雖然如此,但是從總體上來說,它還是能在一定程度上幫助我們設計微服務。
相關書籍:《POSA 4》、《POSA 5》、《微服務架構設計模式》
模式的模式
從模式再模式歸類,再到模式語言,我們已經有了整套的方案。最後,我們就剩下一些有意思的問題,諸如於如何發現新的模式?如何對現有的模式進行一些抽象。
對於『模式的模式』的理解,有助於我們更好地理解好設計模式。對於設計模式的理解之後,只需要理解其背後的模式,就不需要再去熟記每個設計模式。
所以,我們就來到了元素模式,依據的它也是來自於一本書《元素模式》。
元素模式:設計模式的模式
模式是來源於對慣用法的總結,而諸如於元素模式則是對於設計模式的提取,即模式中的模式。元素模式(Elemental Design Patterns)的核心要義是一組面向對象的基本概念。
對 OO 中的設計模式進行更細緻的拆分,我們就能得到位於其背後的模式。作爲其中的核心元素模式便是:創建對象、檢索、繼承和抽象接口。於是,如書上所說,結合這四個 EDP,我們可以創建對,並實施特定的保證,在運行時建立自此的關聯,並從一種類型出發建立其他類型,以及創建出聲明,並帶有關於未來的、未定的類型的保證。
而我們在實施方法調用時,也被抽象了四個 EDP:遞歸、委託、重定向和集聚,以此構成了設計的砌塊。
架構模式的模式
最後就回到了我想抽象的問題,那麼架構模式其背後的模式又有什麼呢?我試着進行了簡單的拆解:
-
契約。輸入與輸出、API 等。
-
分割。隔離變化、明確職責等。
-
約束。功能需求和非功能需求、性能等。
-
封裝。接口封裝。
-
協作。協作風格等
-
……
當然了,我還需要他們進行重新命名,以構建在架構模式領域的統一語言。
其它
儘管,它有些複雜,但是依舊很有意思。
相關資料
-
《元素模式》
-
《設計模式》 -> 《設計模式:可複用面向對象軟件的基礎》
-
《POSA 4》 -> 《面向模式的軟件架構,卷 4:分佈式計算的模式語言》
-
《POSA 5》 -> 《面向模式的軟件架構,卷 5:模式與模式語言》
-
《領域驅動設計》 -> 《領域驅動設計:軟件核心複雜性應對之道》
有興趣可以在未來一起完善相關的資料:https://github.com/phodal/pattern-languages
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/alnJLyZv3wuRT2L8pD2CJw