簡介:如何定義架構?應用架構的要素有哪些?什麼是應用架構中的分類思惟?開源應用架構COLA的做者張建飛介紹他在COLA架構設計中的一些思想經驗,分享他的應用架構之道。
模塊(Module)、組件(Component)、包(Package),這些概念對於咱們技術同窗並不陌生,但並非全部人都能理解其要義。前端
深刻理解以後,我才發現,其背後的深意是分類思惟。而這種分類也是應用架構的核心所在,經過不一樣粒度、不一樣層次的分類,把複雜的軟件系統實現控制在能夠被理解、被維護的程度。不然,對於動則上100萬行代碼的軟件,人類根本沒有辦法理解和維護。java
試想一個極端狀況,假如沒有這些概念協助咱們分類,咱們把全部業務邏輯都寫在一個類裏面,會是什麼樣的結果呢?咱們不少的「非人類」系統,正是由於沒有進行合理的分類形成的。程序員
早期,我不喜歡JavaScript的一個重要緣由,正是由於其缺乏像Java中package和jar的概念,致使代碼的組織形式比較鬆散、隨意。這個問題直到ES六、React才獲得比較好的解決,在此以前,前端工程師不得不依靠seaJS,requireJS這些框架來作模塊化、組件化的事情。數據庫
至此,你可能有疑問,分類有什麼魔力?怎麼就成了應用架構的核心了呢?客官彆着急,由我細細道來。編程
所謂分類,就是依據必定的標準對給定的事物進行組別的劃分。咱們人類天生就有分類的本能,例如,當咱們觀察下面這張圖的時候。後端
不管是誰,乍一看到上面的六個黑點,都會認爲共有兩組墨點,每組三個。形成這種印象的緣由主要是,人類大腦會自動將發現的全部事物以某種持續組織起來。基本上,大腦會認爲同時發生的任何事物之間都存在某種關聯,而且會將這些事物按某種邏輯模式組織起來。前端工程師
之因此咱們大腦有這樣的本能,是由於人一次可以理解的思想或概念的數量是有限的。正如喬治米勒在他的論文《奇妙的數字7》中提出的。人類大腦的短時間記憶沒法一次容納7個以上的記憶項目。因此,當信息量過大時,惟有歸類分組才能幫助咱們去理解和處理問題。架構
其實,自古及今,人類一直在作着歸類/分類,早在春秋時期,《戰國策》中就提出過「物以類聚,人以羣分」的概念。app
在互聯網行業,咱們會對客戶進行分類,而後針對不一樣的客戶進行分層運營,也是這個道理。框架
日常咱們所說的分析和綜合的背後,其實就是分類能力。分析是在一個類裏面找差別性,綜合是在不一樣事物中找聯繫、找共同性,而這個共同性至關於分類的維度。
分類思惟的能力,直接體現的就是看透事物本質的能力。
概念定義
在討論架構以前,咱們先來明確一下Module、Component和Package這幾個概念。
由於這些概念一直以來存在不小的歧義。經過Stack Overflow上幾十篇詢問這些概念差別的提問,以及五花八門的回答就能可見一斑。
在一篇Stack Overflow的帖子[1]中,咱們看到這樣的回答:
The terms are similar. I generally think of a "module" as being larger than a "component". A component is a single part, usually relatively small in scope, possibly general-purpose.
然而,另外一篇Stack Overflow的帖子[2],卻有着不一樣的答案:
There is no criteria to measure which one is greater than the other. One component can contain list of modules, and one module also can contain many components.
在《實現領域驅動設計》一書中,做者有這樣的描述:
If you are using Java or C#, you are already familiar with Modules, though you know them by another name. Java calls them packages. C# calls them namespaces.
然而,在AngularJS的設計文檔[3]中,它對Module和Component是這樣定義的:
The module can be considered as a collection of components, Each component can use other components. One of many modules combines up to make an Application.
經過比較,結合我本身的認知,我更贊同AngularJS裏面的定義,即Module是比Component更大的概念。好比在Maven中,Module是組成Application的第一級層次,而Component的粒度通常比Module要小,多個Component會組成一個Module。
所以,在進一步探討以前,我特地對這些概念作以下定義:
基於上面的定義,他們的表示法(Notation)是這樣的:
應用架構的要素
關於架構的定義有不少,我最喜歡,也是最簡潔的定義是:
即架構是一種結構,是由物件(Components)+ 物件之間的關係 + 指導原則組成的。
應用架構也是如此,從大的層面來講,企業級應用都逃不過以下圖所示的三層結構,即前端、後端和數據庫。
對於後端開發來講,應用層是咱們的主戰場,也是整個系統最複雜的部分(固然,前端也不簡單),全部的業務邏輯都匯聚在此。因此,對於應用層,咱們須要進行進一步拆分,而不只僅是在這裏寫業務邏輯就完事了。
對應用層的進一步分層,就造成了COLA所提倡的四層結構,對應到Maven中,就是有4個Module,編譯打包以後會有4個Jar。一個典型的應用,其Module呈現出以下的結構:
<modules> <module>cloudstore-adapter</module> <!--Adapter 層--> <module>cloudstore-app</module> <!--App 層--> <module>cloudstore-domain</module> <!--Domain 層--> <module>cloudstore-infrastructure</module> <!--Infra 層--> <module>cloudstore-client</module> <!--RPC SDK--> <module>start</module> <!--SpringBoot啓動--> </modules>
當業務變得複雜時,這種分層結構天然比沒有分層要好。這也是COLA一直致力要去解決的問題——控制複雜度。
從COLA 1.0的事無鉅細,到COLA 3.0的化繁爲簡。我漸漸明白,COLA做爲應用架構,其核心不是去提供功能,而是提供基模(Archetype)。
在1.0的時候,COLA提供了Interceptor能力,提供了Event Bus能力,提供了擴展點能力。一個是我認爲你們「須要」這些,另外一個是感受NB的框架就應該面面俱到,沒有幾個高級功能都很差意思開源。事實證實,我犯了一個慣性錯誤——過分設計。Interceptor徹底能夠用AOP替代,內部事件和擴展點不多被用到。因此在COLA 3.0的時候,果斷的去掉了這些「雞肋」,只保留了擴展點功能。
迴歸到架構的本質,COLA的核心應該是規定應用的結構和規範,即應用架構基模(Archetype)。而不是去糾結那些錦上添花的功能。
升級到COLA 3.1
實際上,這樣的迴歸工做,COLA 3.0已經作的差很少了。在此次3.1的升級中,除了進一步去除了Event Bus的功能以外,最重要的就是從新規範了分包策略,和擴充了原來控制層(Controller)的職責。
分包策略調整
分層是一種在功能維度上的橫向切分,即每一層都有本身的職責。
分層處理沒有問題,只是這種功能劃分,會帶來一個問題,即領域維度的內聚性會收到影響。當一個application只負責一個領域的時候沒有問題。然而,當一個application包含多個業務領域的時候,這種內聚性缺失的弊端就比較明顯了。
更好的分包策略是按領域劃分,而不是按功能。由於,領域更內聚,功能是爲領域服務的,應該歸屬於領域。
然而,不巧的是,在COLA應用架構裏面,咱們要綜合橫向功能維度的劃分,和縱向領域維度的劃分,兩個都很好,兩個都想要。怎麼辦?咱們能夠採用物理劃分和邏輯劃分相結合的辦法。
橫向上,咱們用Module作有層次劃分,屬於物理劃分。縱向上,經過Package來進行邏輯劃分。最後,造成一個以下的結構:
按照這個思想去分包,在工程中,Module下的頂層package再也不是功能,而是領域:
按照領域的分包策略至少會帶來兩個好處:
用Adatper代替Controller
Controller這個名字主要是來自於MVC,由於是MVC,因此自帶了Web應用的烙印。然而,隨着mobile的興起,如今不多有應用僅僅只支持Web端,一般的標配是Web,Mobile,WAP三端都要支持。
在這樣的背景下,狹義的控制層已經不能知足需求了,由於在這一層,不只僅要作路由轉發,還要作多端適配,相似於六邊形架構中的Driving Adapter的角色。鑑於此,咱們使用適配層(Adapter)替換掉了Controller,一方面,是爲了呼應六邊形架構;另外一方面,的確也是須要作多端適配。
基於這樣的變化,我重構了COLA Archetype,把Adapter做爲一個層次凸顯出來。實際上,Infrastructure也是適配器,是對技術實現的適配(或者叫解耦),好比,我須要數據來幫助構造Domain Entity,可是我不care這個數據是來自於DB、RPC仍是Search,或者說,我能夠在這些技術實現中進行自由切換,而不影響我Domain層和App層的穩定性。
改造後的COLA在架構風格,模塊、組件以及分包策略上都會有所調整,具體變化請參考下面兩張圖。
COLA架構圖:
COLA3.1
COLA組件關係圖:
這麼重要的思惟能力,其應用確定不只僅侷限於架構設計的範疇。開篇已經說過了,分類是咱們人類的本能,是分析和綜合問題的重要手段。
生產關係決定生產力,好的組織結構會助力業務發展,反之,則會拖業務的後退。所以,大公司的CEO每一年都會花不少時間在組織設計上,這也是爲何,在大廠,每一年咱們都會看到不小的組織調整。
看到一篇文章《蘋果公司的組織架構是怎樣的》[4],裏面介紹了蘋果成功和其優秀的組織架構有關係。以下圖所示,傳統企業偏向於業務型組織,而高科技企業偏向於職能型組織。
有沒有感受蘋果的組織架構,和咱們的COLA思想是同樣的:),物理上,按照職能劃分;邏輯上,按照業務和產品劃分。
蘋果這樣的組織設計,是由於它是技術和創新驅動的公司,協做成本不是最大的問題,缺乏專業性(技術不行),缺乏創新纔是攸關生死的大問題。因此他寧可犧牲協同效率,也要確保專業性,也就是說,作攝像頭的只作攝像頭,作iOS的只作iOS,技術leader直接向CEO彙報,能夠決定產品的發展方向。由於他們在這個領域更專業。
很早之前,史蒂夫·喬布斯就有這樣的觀點:蘋果公司的經理們應該是他們管理領域的專家。在 1984 年的一次採訪中,他說:
咱們在蘋果經歷了那個階段,當時咱們出去想,哦,咱們要成爲一家大公司,讓咱們僱傭專業的管理人員。咱們出去僱了一羣專業的管理人員。一點也無論用……他們知道如何管理,但他們在專業方面什麼都不知道。若是你是一個偉大的人,爲何你想爲一個你什麼都學不到的人工做?你知道什麼是有趣的嗎?你知道誰是最好的經理嗎?他們是偉大的我的貢獻者,他們歷來都不想成爲一名管理者,但卻決定本身必須成爲,由於沒有其餘人可以出色地完成工做。
說實話,看完這篇文章,我很感慨,一方面是佩服喬布斯的洞見能力,另外一方面也爲咱們這個行業感到唏噓,業務技術也是技術啊,卻沒有一個像樣的培育發展技術的環境和土壤。
現在,業務技術Leader還有多少是專一在技術上呢,儼然都變成了業務Leader。若是技術Leader都變成了純管理者,那麼誰去關心技術,誰去關心代碼,誰去關心工程師的成長呢?
最後,我仍是要中庸一下,分類很重要,但同時也很難,帶有必定的主觀性。就像比爾.布萊森在《萬物簡史》裏說的:
分類學有時候被描述成一門科學,有時候被描述成一種藝術,但實際上那是一個戰場。即便到了今天,那個體系比許多人認爲的還要混亂。以描述生物基本結構的門的劃分爲例。許多生物學家堅持認爲總數30個門,但有的認爲20來個門,而愛德華在《生命的多樣性》一書裏提出的數字高達使人吃驚的89門。
咱們觀察事物的視角不一樣,對問題的認知程度不一樣,得出來的分類也會不一樣。就拿COLA來講,直到如今的3.1版本,我我的認爲其分層和分包的方式才相對比較合理。然而,頗有可能在後期的迭代中,分類方式又會改變。
組織架構的分類方式也是同樣,按照業務和職能劃分,均可以。關鍵看其分類是否匹配你組織的特性,沒有最好的分類,只有最合適的。
除了本文分享的分類思惟,更多的思惟能力還能夠參看做者的新書:《代碼精進之路:從碼農到工匠》。這是一本爲專業程序員而寫的書,主要分爲技藝、思想和實踐三個部分,詳細介紹了編程技巧和方法論、抽象能力、分治思想、常見的應用架構模式,以及COLA架構的設計原理。但願可以幫助廣大程序員培養良好的編程習慣和思惟。
若是你以爲這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
點贊,轉發,有大家的 『點贊和評論』,纔是我創造的動力。
關注公衆號 『 Java鬥帝 』,不按期分享原創知識。
同時能夠期待後續文章ing🚀