復雜系統(tǒng)設(shè)計方法論
如何解決復雜架構(gòu)問題?
天下難事必作于易。
軟件架構(gòu)中很重要的一個思想就是:“分治”。
當一個問題或是架構(gòu)異常復雜時,想到的最簡單的方式就是把復雜問題拆解成一個個可解的簡單問題。
比如日常工作中處理一個較為復雜的業(yè)務(wù)系統(tǒng),可以通過拆解到更精細的粒度一個個環(huán)節(jié)解決。
通過流程化方式梳理套路:
業(yè)務(wù)拆解 》復雜度來源 》 核心挑戰(zhàn)點 領(lǐng)域驅(qū)動設(shè)計 》 業(yè)務(wù)過程分析 》 領(lǐng)域模型抽象 》 模型分解 分層組織 》 工程架構(gòu) 》 模塊化 》 組件化 考慮功能復用 》 可選路徑:業(yè)務(wù)身份、能力定義、擴展點定義、工程流程、編排 方案產(chǎn)出 》 整體 -》模塊 -》流程 -》 細節(jié) 》 方案評審 》 最終方案
針對于功能復用,看下大部分業(yè)務(wù)中臺的解決思路。
復雜度來源:
架構(gòu)設(shè)計的目的是為了解決軟件系統(tǒng)的復雜度帶來的問題
所以在架構(gòu)設(shè)計時,首先要分析的就是系統(tǒng)的復雜度。只有正確的分析了系統(tǒng)的復雜性,后續(xù)的架構(gòu)設(shè)計方案才不會偏離方向。否則,如果對于復雜性有了錯誤的判斷,即使后續(xù)的設(shè)計方案再先進,都是做得多、錯的多。
比如一個偏運營的系統(tǒng),其復雜度在于復雜業(yè)務(wù)帶來的業(yè)務(wù)復雜度。如果架構(gòu)師將復雜度定義為高QPS,那就沒有解決核心問題,反而引入新的問題。
解決核心問題:
射人先射馬,擒賊先擒王
確定了系統(tǒng)的復雜度,就確定了系統(tǒng)設(shè)計的難點,在進行系統(tǒng)設(shè)計時,可以把難點列出來,各個擊破。
比如營銷系統(tǒng)的復雜度來源于營銷形態(tài)的變化,營銷形態(tài)千變?nèi)f化,每次促銷都有不同的玩法和定義。所以營銷系統(tǒng)需要對營銷形態(tài)有所抽象,任何活動或優(yōu)惠手段都是基于這個營銷模型建立起來的。
領(lǐng)域驅(qū)動,復雜架構(gòu)治理的第一個方法論。
底層模型的抽象,可以通過DDD方式對領(lǐng)域模型進行抽象。促銷引擎,編排之外考慮性能問題,可以采用緩存、異步、最終一致性等。系統(tǒng)之間的交互,要理清關(guān)系和依賴。
每個系統(tǒng)都有其需要解決的核心問題域,一個領(lǐng)域下的多個解決類似問題的系統(tǒng)同屬于一個核心域。
只要確定了系統(tǒng)所屬的域,那么這個系統(tǒng)的核心業(yè)務(wù)和關(guān)鍵問題基本就確定了。
DDD里面有領(lǐng)域?qū)<业母拍睿I(lǐng)域?qū)<乙钊腩I(lǐng)域研究,只有這樣才會遇到非常多該領(lǐng)域下的問題,積累出比較豐富的經(jīng)驗,所以相關(guān)行業(yè)經(jīng)驗非常重要,不要光看著技術(shù)實現(xiàn),要積累業(yè)務(wù)問題。
通常一個領(lǐng)域下只有一個核心問題,也就是核心域。當然領(lǐng)域下還有其他的域,比如通用域、支撐域,在梳理域的過程中,就是定義子域邊界的過程。
復雜架構(gòu)落地過程中可以參考一些架構(gòu)模型。
常見的有三層架構(gòu):


領(lǐng)域驅(qū)動設(shè)計時的分層模型:

各層定義說明:

整潔架構(gòu)模式:

Robert Martin 的整潔架構(gòu)將領(lǐng)域模型放在整個系統(tǒng)的核心,這一方面體現(xiàn)了領(lǐng)域模型的重要性,另外一方面也說明了領(lǐng)域模型應(yīng)該與具體的技術(shù)實現(xiàn)無關(guān)。
領(lǐng)域模型就是業(yè)務(wù)邏輯的模型,它應(yīng)該是完全純粹的,無論你選擇什么框架,什么數(shù)據(jù)庫,或者什么通信技術(shù),按照整潔架構(gòu)的思想都不應(yīng)該去污染領(lǐng)域模型。
如果以 Java 語言來實現(xiàn),遵循整潔架構(gòu)的設(shè)計思想,則所有領(lǐng)域模型對象都應(yīng)該是 POJO(Plain Ordinary Java Object)(具有領(lǐng)域邏輯的 POJO 對象)。

插件化領(lǐng)域分層架構(gòu):

DDD的核心訴求就是將業(yè)務(wù)架構(gòu)映射到系統(tǒng)架構(gòu)上,在響應(yīng)業(yè)務(wù)變化調(diào)整業(yè)務(wù)架構(gòu)時,也隨之變化系統(tǒng)架構(gòu)。
微服務(wù)追求業(yè)務(wù)層面的復用,設(shè)計出來的系統(tǒng)架構(gòu)和業(yè)務(wù)一致,不過領(lǐng)域模型并不直接反映數(shù)據(jù)結(jié)構(gòu),需要明確這一點。
領(lǐng)域驅(qū)動設(shè)計最后落地到數(shù)據(jù)存儲上,不需要直接參考領(lǐng)域模型,在最后的技術(shù)架構(gòu)上可以自由選擇合適的技術(shù)架構(gòu)。
Java項目一般是典型的Maven多模塊項目,可以使用不同的Module,區(qū)分各個層次,進一步,通過Package來控制DDD中的限界上下文。
如何實現(xiàn)功能復用?
編程DRY原則
編寫整潔代碼,有一個非常重要的原則就是DRY,Don't Repeat Yourself,避免產(chǎn)生重復代碼,有經(jīng)驗的程序員都能夠意識到這一條約束。
如果你使用Idea開發(fā),Idea也會識別并且提示你重復的代碼,建議你進行抽象。
DRY它相信更少的代碼是好的,它節(jié)省了時間和精力,易于維護,并且減少了bug的幾率。
除了在軟件開發(fā)領(lǐng)域,在業(yè)務(wù)系統(tǒng)層面,也存在如何避免重復能力建設(shè),考慮業(yè)務(wù)復用的問題。
業(yè)務(wù)層面的DRY
業(yè)務(wù)系統(tǒng)層面的DRY原則,其實可以總結(jié)為一個問題,就是復雜業(yè)務(wù)系統(tǒng),如何實現(xiàn)具有共性的業(yè)務(wù)能力的復用,這個也是很多業(yè)務(wù)中臺關(guān)注的問題。
一般的,大部分業(yè)務(wù)中臺(特指業(yè)務(wù)中臺,不包括數(shù)據(jù)中臺等其他形態(tài))對業(yè)務(wù)復用的方式,都可以通過定義業(yè)務(wù)身份 ——> 梳理擴展點 ——> 枚舉業(yè)務(wù)能力 ——> 根據(jù)不同業(yè)務(wù)身份編排工作流 ——> 實現(xiàn)業(yè)務(wù)能力復用,這樣的流程來實現(xiàn)。
可以對比編程中的Pipeline模式,或者責任鏈模式,只不過每個鏈條上負責處理輸入和輸出的,是不同的業(yè)務(wù)功能。
可擴展性和過度設(shè)計如何平衡?好的架構(gòu)設(shè)計一定是擴展簡單的。
在設(shè)計時,要盡量封裝可能的變化,在業(yè)務(wù)流程發(fā)生一些調(diào)整時,能夠比較方便地修改系統(tǒng)程序模塊或組件間的調(diào)用關(guān)系而實現(xiàn)新的需求,也就是我們常說的可擴展性。
但是可擴展性本身也是系統(tǒng)設(shè)計的復雜度來源之一,這就涉及到一個問題,如何平衡可擴展和過度設(shè)計。
區(qū)分確定性和變化。
好的架構(gòu)一定是擴展簡單,運行平穩(wěn)的。
系統(tǒng)架構(gòu)最開始可以從一個通用的流程開始,case-by-case,然后將「變化少」的部分沉淀下來為架構(gòu),將「變化多」的沉淀為擴展或者配置,梳理清楚,將這兩者結(jié)合起來,最后完成系統(tǒng)架構(gòu)設(shè)計。
用容量規(guī)劃的方式來處理擴展程度。
可以使用容量規(guī)劃的思想,來處理可擴展性設(shè)計。
在做技術(shù)方案時,容量規(guī)劃是一個特別重要的環(huán)節(jié),要預估未來幾年的增長量,進行數(shù)據(jù)庫和緩存的容量規(guī)劃。
我覺得這個方式也可以應(yīng)用在擴展性設(shè)計上,對業(yè)務(wù)變化進行預期,考慮技術(shù)方案能夠支持的業(yè)務(wù)發(fā)展時間。
方案評審 好的技術(shù)方案很難一蹴而就,大部分時候要經(jīng)過反復的調(diào)整,就是需要關(guān)聯(lián)的各方參與方案的評審和修改,最終確定最終技術(shù)方案。
復雜業(yè)務(wù)系統(tǒng)開發(fā)的一些體會:
熟悉業(yè)務(wù),抽象產(chǎn)品需求,分析相關(guān)測試用例,了解各種用戶角色和其使用的場景自頂向下進行方案設(shè)計,對于比較復雜的業(yè)務(wù)系統(tǒng),比較好的方式是先關(guān)注頂層模型,避免在一開始就陷入技術(shù)和業(yè)務(wù)細節(jié)中去
從整體設(shè)計,到模塊局部規(guī)劃,設(shè)計好部署架構(gòu)、分層和分模塊、API設(shè)計、數(shù)據(jù)庫設(shè)計等
可以參考成熟的解決方案,比如將開源軟件,改造,變成適合自己業(yè)務(wù)需求的架構(gòu)
驗證和優(yōu)化架構(gòu)設(shè)計方案,完整的架構(gòu)設(shè)計方案,需要有多次的評審,充分收集各方面的反饋,反復修改后確定
合理進行擴展,考慮架構(gòu)預期能滿足多長時間的業(yè)務(wù)增長,比如未來一年的業(yè)務(wù)變化。
