01 如何解決復雜業(yè)務設計 Aliware 軟件架構設計本身就是一個復雜的事情,但其實業(yè)界已有一個共識,那就是“通過組件化完成關注點的分離從而降低局部復雜度”。其實現在我們用的無論是容器、中間件、消息、數據庫等,在某種意義上都是組件化的產物。這樣的好處是在不同的系統里可以復用。在云原生興起的今天,以通用的、組件化的服務形式更容易為我們所用,所以說現在如果還不享用云原生技術紅利,那你就會被時代拋棄。 云原生滿足非功能性質量需求 云原生在技術上能夠最大程度的解決眾多非功能性質量和技術需求(如上圖),那作為一個企業(yè)級應用架構,自然會把專注點轉移到業(yè)務應用功能性設計本身上來?,F在來說對于一個復雜業(yè)務架構進行設計,我們要想做到又快又好,無非是兩種情況:一是架構師本身對業(yè)務理解很深、能力超強、爐火純青;二是原有的業(yè)務系統本身模型清晰,足夠的“高內聚低耦合”,可以快速在其基礎之上分析業(yè)務變化形成新的業(yè)務架構設計。我們應該追求的是第二種情況,這也就意味著從一開始的企業(yè)級模型建設,就要對模型設計、業(yè)務流程仔細對待,只有做到基礎扎實,才能有后面的“快速迭代”。 我們再回到架構設計的本質,即為什么我們要在代碼實現前做設計。設計首先是要解決問題的復雜度。于是有人做了一個架構,交給了一個團隊去實現,很快發(fā)現實現的架構和設計完全是兩回事。當然原因很明確——缺少了交流和溝通;其次是要建立團隊協作溝通的共識。即使我們做好了一個團隊都達成共識的架構設計,大家都兢兢業(yè)業(yè)把設計變成了現實,一個長期困擾軟件行業(yè)的問題出現了,需求總是在變化,無論預先設計如何“精確”,總是發(fā)現下一個坑就在不遠處,結果往往是情況越來越糟糕,也就是我們常說的架構“腐化”了,最后大家不得不接受重寫。這些經歷讓我們逐步明確了軟件架構設計的實質是通過核心問題的分離降低復雜度,并讓系統能夠更快地響應外界業(yè)務的變化,并且使得系統能夠持續(xù)演進。在遇到變化時不需要從頭開始,保證實現成本得到有效控制。 所以,我覺得從架構設計角度,以下三點是最為關鍵的:
上面的三點毫無疑問都指向了業(yè)務,從業(yè)務出發(fā)、面向業(yè)務變化是我們現代架構設計成功的關鍵,所以說復雜業(yè)務架構設計的核心實質是保證面對業(yè)務變化時我們能夠有足夠快的響應能力。 領域設計 Aliware 前面說了業(yè)務軟件開發(fā)的常見病:從一個小的項目不斷開發(fā)演化變成一個大型業(yè)務系統,但隨著新需求的不斷增加,最終演變成了開發(fā)團隊的噩夢。而這些噩夢大部分是源于軟件的概念完整性(“概念完整性”一詞來源于軟件工程的經典著作《人月神話》)遭到了破壞。這些業(yè)務代碼可能是一代又一代的開發(fā)人員各行其道的堆疊起來的(我們又稱之為“屎山”),而這個過程中沒人有意識的去維護軟件的概念完整性。而 DDD 領域設計,特別是 DDD 提供的戰(zhàn)略建模層面的概念,是維護軟件概念完整性的良藥。 “技術服務于業(yè)務、業(yè)務驅動技術”是目前大部分人的共識,尤其是對商業(yè)公司而言。而 DDD 領域設計主張在軟件設計中把業(yè)務領域本身作為關注的焦點(換句話說就是軟件開發(fā)人員要懂業(yè)務)非常符合這種思想;并且,DDD 提供了切實可行的面對復雜業(yè)務軟件設計的解決方法,這也是我非常提倡作為一個架構師去深入學習和討論 DDD 領域設計的相關知識。 戰(zhàn)略建模 在戰(zhàn)略層面,DDD 非常強調對業(yè)務問題的分析和分解,通過識別核心問題來降低問題的復雜度。DDD 在戰(zhàn)略層面維護模型的概念完整性的方法,最重要的兩個概念就是界限上下文(Bounded Context)和防腐層(Anti-Corruption Layer)。
關于界限上下文的定義,隨便一本講 DDD 的書上都會詳細講解,這里我只想分享一下自己的一些理解。這時,有人會問:界限上下文多大才能合適呢,劃分上下文有沒有可以遵循的規(guī)則呢? 劃分上下文的規(guī)則,無非就是放之四海而皆準的“高內聚、低耦合”,這么說可能還是太虛。其實真正讓大家感到糾結的是,不知如何切分的那些東西之間所存在的關聯,有的甚至干脆都納入到一個上下文里。其實,我認為與其關注上下文的“大小”,不如關注模型的“質量”,關注概念的完整性是不是容易被破壞。我覺得,判斷大小是不是合適,要結合應用開發(fā)團隊的能力,看開發(fā)團隊能在多大的一個范圍內掌控軟件的概念完整性。只要是開發(fā)團隊沒有問題,這個范圍就算再大也都是可以的。 如果開發(fā)團隊的水平在業(yè)界屬于上游,那么維護上下文的范圍往往是很大的;一些公司開發(fā)團隊的水平參差不齊,所以在項目的實施過程中,可能需要劃分相對小的上下文,盡可能減少“屎山”的不斷堆積。
界限上下文需要時刻保護好自己所維護的邊界,以及邊界內概念的完整性,這時需要將某個上下文的概念轉化為另一個上下文概念的地方就叫做“防腐層”。防腐層的實現有很多種,典型的比如作為適配器 Adaptor 來實現,另外廣義上講,Gateway 也是一個典型性的防腐層組件,當然,防腐層的代碼和其他內部業(yè)務模型之間要存在明顯的物理邊界(當然不一定說要把防腐層作為一個個獨立部署的進程),至少我們可以考慮把防腐層作為一個獨立的類庫來進行構建和維護,阿里內部的比如星環(huán)、其實就是這個思路。 一個典型的防腐層的設計 戰(zhàn)術建模 DDD 在戰(zhàn)術上最核心的概念就是實體和聚合,為了更好的理解什么是聚合、聚合根、聚合內部實體,下面舉例說明一下。想象一下一個電商系統的訂單相關的模型,我們可能會得到訂單 Order、訂單頭 OrderHeader、訂單行項 OrderItem 三個相互關聯的概念:
“聚合是數據修改的單元”,基于這個原則,我們可以做到“聚合內強一致、聚合外最終一致”,比如,我們可以不能接受一個訂單內的所有訂單項的金額之和不等于訂單頭的總金額,我們就必須把訂單頭和訂單行項這兩個實體劃分到同一個聚合內。
我們不妨先看一下《實現領域驅動設計》一書中對聚合設計原則的描述,原文是有點不太好理解的,我來稍微解釋一下:
上面的這些原則是 DDD 的一些通用的設計原則,還是那句話:“適合自己的才是最好的。”在系統設計過程時,你一定要考慮項目的具體情況,如果面臨使用的便利性、高性能要求、技術能力缺失和全局事務管理等影響因素,這些原則也并不是不能突破的,總之一切以解決實際問題為出發(fā)點。
DDD 領域建模通常采用類似事件風暴,一般通過用例分析、場景分析和用戶旅程分析等方法,通過頭腦風暴列出所有可能的業(yè)務行為和事件,然后找出產生這些行為的領域對象,并梳理領域對象之間的關系,找出聚合根,找出與聚合根業(yè)務緊密關聯的實體和值對象,再將聚合根、實體和值對象組合,構建聚合。 電商系統大家都比較熟悉了,而且關于電商業(yè)務來說有許多比較成熟的模型可以直接借鑒;那下面我們以另外一個場景-保險投保業(yè)務為例,看一下聚合的構建過程主要都包括哪些步驟,當然這個例子我是從其他的學習資料里看到的,比較典型,可以當作示例來進行說明: 保險投保業(yè)務簡單示例(From 學習資料)
那以上就是一個聚合誕生的完整過程了。 不同場景下的領域建模策略 Aliware 由于企業(yè)內情況千差萬別,發(fā)展歷程也不一樣,有遺留單體系統的微服務改造,也有全新未知領域的業(yè)務建模和系統設計,還有遺留系統局部優(yōu)化的情況。不同場景下,領域建模的策略也會有差異。下面我們就分幾類場景來看看如何進行領域建模。 新建系統 新建系統對于復雜的業(yè)務領域,領域可能需要多級拆分后才能開始領域建模。領域拆分為子域,甚至子域還需要進一步拆分。比如:保險它需要拆分為承保、理賠、收付費和再保等子域,承保子域再拆分為投保、保單管理等子子域。復雜領域如果不做進一步細分,由于問題域太大,領域建模的工程量會非常浩大。你不太容易通過事件風暴,完成一個很大的領域建模,即使勉強完成,效果也不一定好。 對于復雜領域,我們可以分三步來完成領域建模和微服務設計。
單體遺留系統 如果我們面對的是一個單體遺留系統,只需要將部分功能獨立為微服務,而其余仍為單體,整體保持不變,比如將面臨性能瓶頸的模塊拆分為微服務。我們只需要將這一特定功能,理解為一個簡單子領域,參考簡單領域建模的方式就可以了。在微服務設計中,我們還要考慮新老系統之間服務和業(yè)務的兼容,必要時可引入防腐層。 云原生時代下的挑戰(zhàn) Aliware 隨著云原生技術的興起,現在企業(yè)級架構就更加的云化,而云化的架構風格有了新的關注點:彈性邊界。彈性邊界是一個云原生企業(yè)級應用架構的核心概念,它指把彈性作為最優(yōu)先的考慮要素而劃定的系統邊界,決定了我們是否能夠充分發(fā)揮云原生平臺的全部能力。于是我們就需要新的方法來彌補以前業(yè)務模型的不足,以滿足新的云原生化的需要?,F在可以說,微服務基本上就是以云原生架構作為基礎,而在固定彈性的平臺上使用微服務架構,有極高的實施成本??梢哉f,云原生實際上就應該是微服務的前置條件。 在云原生時代,我們需要將彈性作為首要考慮的因素,納入建模的考量。那么彈性邊界,就是我們劃分系統的重要依據。而且,我們還需要考慮彈性邊界間的依賴關系,盡量避免彈性耦合。對于業(yè)務建模來說,為了配合云原生時代的架構,我覺得要做到如下幾點:
不要忽視組織結構的影響 Aliware “康威定律”告訴我們,組織結構會決定團隊溝通的結構,也會決定產品的結構。對組織結構的梳理,在需求調研的時候會經常做。如果是信息收集而言,業(yè)務架構設計在這里并沒有什么特殊之處。區(qū)別在于,業(yè)務架構的目標是企業(yè)級的能力規(guī)劃,希望能夠突破壁壘、形成合力。正是這個原因,組織結構對業(yè)務架構設計的反作用力也是很大的,企業(yè)級數字化轉型方案要與組織結構相匹配,否則落地的時候會困難重重??梢哉f,部門利益是做企業(yè)級架構的最大障礙之一,跨越這個障礙也是對架構師的能力的要求之一。當然,有些情況下,沒有更好的解決方案時,不動也是一種選擇。 以我的經驗,這種問題沒有特別好的辦法,無非是兩種:一是有超強能力者主導,在最高層的支持下,強力推進這種決策,但是企業(yè)越大,尤其是以業(yè)務為主導地位的企業(yè)中,這種結構就愈難形成;二是加強企業(yè)內部的業(yè)務架構人員的能力和數量(最好各個部門都有類似的角色),讓這些企業(yè)機構人員以合作伙伴的方式全程參與到項目中,在項目的實施過程中搭建起協作網絡,提升決策效率,才能使組織結構不再是企業(yè)數字化轉型的瓶頸。 SOA-微服務-中臺:妥協的藝術 Aliware 多年前,這些傳統的大型 ERP 業(yè)務軟件,其實都是在一個很大的范圍內維護業(yè)務概念的完整性。一個 ERP 安裝完畢后,數據庫有七八百張表(也就是七八百個實體)處于同一個界限上下文之內。但是這些 ERP 在這樣一個巨大的界限上下文內仍然很好的維護了業(yè)務概念的完整性,實在令人敬佩。 然而實現它非常困難,但是破壞它卻非常容易。一套 ERP 定制項目實施下來,數據庫里可能又多了幾百張表,更不用說不規(guī)范的命名看起來千奇百怪。這些廠商的 ERP 實施顧問和開發(fā)人員,夜以繼日的維護這個龐大的“屎山”。我們不能讓這些龐大的“單體應用”無限制的增長,于是我們又一次祭起了“分而治之”的大旗。想 SOA 這樣的軟件組件化技術給我們提供了拆分的工具。我們把一個大的界限上下文按照利于拆分成幾個相對來說小一些的界限上下文;在物理上,我們把一個大的單體應用拆分成若干服務。 一般來說,我們會讓服務的物理邊界和界限上下文的領域邊界基本堆砌,一個界限上下文對一個或多個可以獨立部署的服務應用,服務應用包含了界限上下文的核心業(yè)務邏輯的實現。SOA 的服務組件的物理邊界給服務間的調用增加了一些困難,這就使得開飯人員簡化對象之間的關系,編寫更加“高內聚、低耦合”的代碼。當服務組件不多的時候,構建防腐層的工作量也不會很大,我們只要處理好組件之間的代碼即成就好了。 但是,我們的架構師和開發(fā)人員太喜歡“分而治之”了,微服務的廣泛使用甚至說是濫用,讓我們看很多微服務真的是很“微”,幾乎是一個 DDD 的聚合就可以對應一個可以獨立部署的微服務。這樣的微服務單單靠本身做不了太多的業(yè)務,這就需要更多更多的微服務“聚合”起來一起才能對外提供業(yè)務服務。 當然,微服務技術基礎設施的發(fā)展也為服務之間的調用提供了更多的便利,跨越微服務的邊界成為了常態(tài);這個時候,業(yè)務開發(fā)人員區(qū)分“同一個上下文內的服務調用”和“上下文之間的防腐層”就要時刻保持頭腦清醒,這時候的界限上下文和微服務的物理邊界往往很難對齊,這就必然增加了維護每個界限上下文概念完整性的難度。 既然維護一個個“微小”的獨立的界限上下文概念完整性越來愈難,那么我們干脆將它們再聚合起來吧?將它們融合到一個大小適度的界限上下文,那這就是所謂的企業(yè)級業(yè)務架構,也就是我們現在說的業(yè)務中臺,最終目的可以說想要獲得“企業(yè)級”的大和諧。 所以在一定程度上講,軟件工程就是妥協的藝術,是“中庸之道”。我們要不要中臺,要大的中臺,不管企業(yè)的大小,都應該結合自身的業(yè)務目標以及擁有的資源,在“維護更大范圍的概念完整性”和“維護更多的防腐層代碼”之間做出平衡,那這也是一個企業(yè)級架構師所要做的最核心的事情之一。 我們團隊這些年確實做了一些“業(yè)務中臺方法論”的積累和實踐,并且在一些項目中做了實踐,當然其中最靈魂的部分之一還是前面說的領域設計。以前很多人說 DDD 領域設計乃至業(yè)務中臺方法論最難的就是沒有一個合適的工具或者平臺來實踐,今天其實阿里開源的 COLA 以及內部使用的星環(huán)、BizWorks 都是很好的工具和平臺。 結語 Aliware 企業(yè)級應用架構是在不斷的演進和迭代,但是我始終感覺企業(yè)應用架構的形成過程是在一種看起來科學的方法論下,但是又不完全科學的過程中實現的。仔細想一下,做軟件架構的其實很羨慕做建筑架構的,因為建筑架構有嚴謹的力學基礎作為基座,有很多可以精確計算的東西,而軟件架構卻沒有多少可以精確計算出來的成分,所以,前面說的“不斷的妥協”不失是一種可行的設計思路和設計藝術;其實這也應驗了那句“沒有銀彈”。 由于時間倉促,有些內容簡單帶過,有些本應該結合實例來說明的地方在本文中也簡略而過,后面有時間的話我會結合更多的實際案例來對本文說的觀點進行補充。也希望本文能夠激發(fā)大家一起對目前云原生時代的企業(yè)級應用架構設計的思考和討論,相互學習,共同進步。 來源:阿里巴巴中間件
|
|