新年福利|架構的“一小步”,業務的一大步
作者:閒魚技術-絳曲
前言:
談到“架構”這兩個字,會有好多的名詞閃現,比如:分層架構、事件驅動架構、DDD、CQRS等。亦或者一堆的軟體設計原則,如:KISS原則(Keep it Simple and Stupid)、SOLID原則(單一責任原則、開放封閉原則、里氏替換原則、介面分離原則、依賴導致原則)等。甚至如狀態圖、用例圖、時序圖、活動圖等UML建模,GOF設計模式等。
本文不會討論這些架構概念,而是從閒魚詳情頁這個業務場景出發,分析出當前的業務問題和痛點,然後通過一步步的架構推導設計,解決這些痛點。隨著業務的發展,相信這些問題大家都會遇到。而解決問題的過程,或多或少的會用到上面的設計原則。
圖1:一種架構的定義
一:老的業務架構 – MVC架構
很多同學開始寫業務的時候,基本都會先建表,然後生成CURD,最後再堆業務邏輯,從DAO->Manager->Service->Controller一路寫到底。在業務小的時候,這種架構非常的簡單實用,可以快速的開發上線。
但隨著業務發展,人員不斷增加,老的架構難以支撐業務的發展,穩定性和效率受到極大挑戰。蠻荒時代已過,精耕細作的時代到來,急需一種更合適的架構來支撐業務的發展。
以閒魚的詳情頁舉例,在業務初期,詳情的樣式只有普通的開價寶貝一種,但隨著業務的發展,演變出拍賣、免費送、租房、玩家等細分領域的商品詳情頁(我們將細分領域的業務命名為“垂直業務”)。
圖2:閒魚詳情頁業務演變
此時,還不斷的在老的業務邏輯裡新增新的業務邏輯,導致所有的詳情業務邏輯堆在一起。於是乎,會出現下面的場景:
1)今天A詳情業務線的同學,加了段邏輯,掛了,影響了所有業務線的同學;
2)B詳情業務線的同學想做單獨的監控、快取、降級等,做不到啊,大家的邏輯在一起,改造成本太高;
3)C詳情業務線的同學本想只關注C詳情業務邏輯,發現所有業務都在一起,不得不將所有業務都理清楚一遍;
4)D詳情業務線的同學發現前面的業務邏輯太複雜,為了將影響面減少到最小,找了一個認為最安全的地方,加了一段D詳情業務的特殊處理。
圖3:詳情頁堆邏輯程式碼
有人可能會問,堆邏輯正常的啊,加幾行程式碼,業務就上線了,網際網路提倡的敏捷開發,當然是怎麼快怎麼來。但敏捷開發 != 提需求 + 編碼 + 釋出,加幾行程式碼交付業務上線,可能會帶來眼前的收益,但一直這麼下去,程式碼會越來越臃腫,沒有設計和文件沉澱的系統,難以維護,出故障只是時間問題。
二:新的業務架構 – 業務隔離 + 領域建模
吉德林法則講:把難題清清楚楚地寫出來,便已經解決了一半。 老的架構的問題,歸納起來講:
1.業務沒有做隔離,所有的垂直業務邏輯都堆在一起,互相影響。
2.詳情頁業務足夠的複雜,卻沒有統一的模型,形成統一的認知。
因此,架構的設計方案就著重解決這兩個問題。
2.1 業務隔離架構推導與設計
一個業務,有多種形態的實現,很容易對應到設計模式裡的策略模式。最粗暴的方式,每個垂直業務都自己實現詳情頁。
圖4 使用策略模式,隔離每個業務的實現
這種方式,業務雖然隔離了,但維護成本極高,新增一個通用的功能,所有業務都需要新增一遍。 因此需要將共性內容(不變的部分)抽象出來,將變化的部分由各個垂直業務去實現。
圖5,抽象出共性(不變)和特性(變)的內容
這種方式,解決了業務的隔離,共性的內容統一維護,變化的部分由各個垂直業務獨立維護。但此時,所有的業務團隊還是在一個應用工程裡寫業務程式碼,會出現如下場景:
1)開發階段,各業務線都在這個應用里拉取一個分支進行開發,整合部署時,程式碼衝突難以避免。
2)A業務線新增了一段自己業務線的邏輯,部署失敗了,導致其它業務線也無法使用。
3)N業務線不在自己的團隊內,屬於外部合作團隊,如何新增該業務線的邏輯。
這些場景存在的原因在於,業務程式碼雖然隔離了, 但人員的開發過程並沒有隔離。有如下3中方法可供選擇:
a. 將共性的內容打成二方依賴包,每個垂直業務依賴這個二方包,進行獨立應用開發。
這種二方依賴的方法最常用,但在二方服務裡新增一個通用功能的時候,要告知所有業務方都升級二方包,還要發版,升級的成本高。
圖6.a 共性內容打成二方包
b. 垂直業務獨立應用開發,然後將程式碼打成jar包,再整合到共性業務應用裡,一起部署。
該方法依賴關係跟方法a相反,但部署方式不夠靈活。如果要實現垂直業務的獨立部署,改造成本太高,需要做類隔離,budle隔離等。
圖6.b 垂直業務打成二方包
- 綜合a和b的優點,將共性的業務獨立部署,垂直業務既可以獨立部署,也可以寫在共性內容應用裡。當呼叫某個垂直業務實現時,可以自動路由到具體的垂直業務實現(這個垂直業務實現可以是一個本地呼叫,也可以是一個遠端呼叫)。這樣,垂直業務的開發人員就可以在自己的應用中開發、部署、運維,解決開發人員的隔離問題。
圖6.c 互不依賴,部署方式可選
至此,業務的隔離,開發人員的隔離問題都已解決。但該架構方案顯然不只有詳情這一個場景可用,其他類似的業務場景也有相似的問題。因此,架構的程式碼不能與業務的程式碼耦合在一起,需要將架構的程式碼獨立出來,形成通用的技術工具,以應用於所有類似的業務,業務開發應該只關心業務的事情。我們特地為此開發了一個多實現“業務隔離”路由工具,最終的隔離架構設計圖如下:
圖7: 總體架構圖。
2.2.領域模型在詳情頁的使用
隔離的問題解決了,再來談談詳情頁的領域建模。
為何需要領域建模?好多java開發的同學,大都會遇到這樣的問題:1)一門OO(物件導向)的語言,寫出來的程式碼都沒有OO的感覺,到像是過程式的程式碼,物件導向的思想基本沒有使用到。2)雖然程式碼滿足了業務需求,但從程式碼中,完全看不到業務領域的影子,業務領域和程式碼是脫節的。3)隨著業務的越來越複雜,裡面的依賴關係梳理起來非常困難,業務模組沒有邊界可言。
為了不給後人挖坑,為了解決詳情頁複雜的邏輯,為了讓程式碼更有範,為了讓接手詳情的同學都有統一的業務領域認知,因此決定對詳情領域進行領域建模。
圖8: 領域驅動設計-模型關係總圖
Eric Evans的那本《領域驅動設計——軟體核心複雜性應對之道》經典書籍大行其道十幾年,網上關於領域建模的文章也是浩如煙海,自頂向下、自底向上、四色原型建模、問題空間領域模型抽象方法論也非常的多。但這些文章和書籍,要麼談論理論概念,要麼談論建模方式,對初學者來說,看完之後,還是寫不出相應的程式碼。
所以本文不在重複的去講領域建模的概念,直接通過閒魚詳情頁這個業務場景,講述建模的步驟、DDD的程式碼展示,給讀者一個更直觀的參考。
2.2.1 詳情頁領域建模
閒魚詳情頁是一個純展示的頁面,用一句話可以概括為,“詳情頁是包括:商品、賣家、買家、魚塘、認證、互動等內容的資訊聚合展示頁” 。
這裡我們使用四色原型建模法進行建模。上面的這句話最骨幹的內容為:詳情頁是一個“資訊聚合展示頁”(瞬間事件)。
圖9: 詳情頁是一個資訊聚合展示頁
骨幹內容定義好後,為了更好的描述詳情頁是什麼,需要補充一些實體物件,詳情頁主要包含商品、賣家、買家、魚塘這些實體(人-物-地點)。
圖10: 詳情頁中包含的主要實體
在此基礎上,進一步的進行抽象,使用者實體中,有賣家、買家這個角色存在;魚塘實體中,又有塘主、塘民角色存在(塘主也是塘民,所以塘主應該繼承自塘民)。加入角色後的模型如圖11所示:
圖11: 詳情頁中的角色
最後,再把一些描述資訊放進去
圖12: 模型中補充描述資訊
有了模型的設計,再轉為類圖設計。根據模型的抽象,詳情頁是資訊展示的聚合,因此它是個聚合根,包含了商品、賣家、買家、魚塘這些實體資訊。 商品資訊描述裡,又有視訊、圖片、文字、互動等資訊。視訊、圖片可以抽象為媒體資訊。使用UML設計出最終的類圖,如圖13所示
圖13: 詳情頁類圖結構
2.2.2 DDD程式碼展示
在實現詳情頁時,依據的是DDD中的定義。DDD中最主要的內容包括:entity、value object、aggregate、repository、factory和service (如圖8所示), 以及Infrastructure, Domain, application和User Interface 分層結構,如圖14所示:
圖14 領域驅動設計分層架構
Infrastructure主要用於持久化資料的讀取和寫入;Domain為領域層,提供領域資訊,這是業務的核心所在;Application是很薄的一層,沒有業務邏輯,用來協調應用活動;User Interface負責使用者資訊展示。將這個分層結構對映到工程結構如圖15所示。
圖15:DDD領域建模工程結構
這裡的Applicaiton層沒有業務邏輯,只作為二方服務對外提供。此外,工程結構中沒有寫User Interface層,因為該應用是以二方服務提供,當然,如果提供REST服務,則可以寫在這一層。
多數的使用者對MVC架構比較瞭解,因此,圖16對比了DDD的分層架構和MVC的架構,以做參考。
圖16:DDD分層對比MVC分層
根據上文的模型抽象,領域物件主要有 ItemEntity, SellerEnity, BuyerEntity, FishPoolEntity,並通過詳情頁聚合根DetailAggregate聚合。
圖17: 詳情頁聚合根
在圖15應用結構分層中,有3種型別的資料物件,DO物件表示持久化的資料物件, Entity為領域物件,DTO為對外的傳輸物件。
首先通過領域層的Repository,呼叫基礎設定層的Dao讀取DO結構,再使用Convertor轉為Entity領域物件。
圖18: Repository的定義
圖19: Converor轉化器的定義
領域entity處理各自的領域業務邏輯,然後通過領域層的DetailService,對聚合根DetailAggregate進行整體詳情頁業務領域處理。最後轉為DTO傳輸物件提供對外服務。
三: 總結和思考
本文從詳情頁業務出發,當業務越來越複雜時,如何做業務的隔離,做開發人員的隔離,以及如何通過領域建模,形成統一認知。給大家提供一個可行的參考。
但沒有任何一種架構可以適用於所有的場景,也沒有任何一個架構是最優的,所謂架構,都在解決“邊界”的問題。因此都需要從實際的業務場景出發,明確出問題的邊界在哪裡,要達到什麼樣的目標,再遵循一些基本的原則和方法,基本都能夠設計出符合自己業務特性的架構。
接下來將會給大家分享一篇從不同的視角出發,進行的業務架構設計。
相關文章
- 業務調整一小步,技術進一大步
- 自動化部署的一小步,前端搬磚的一大步前端
- 大模型走向產業的一小步,AI走向普惠的一大步大模型產業AI
- 改需求之路:設計師的一小步,程式設計師的一大步程式設計師
- 知識網路一小步,資料驅動一大步
- 5款受用一生的自學網站,每天堅持一小步,成功一大步!網站
- 一文搞懂SaaS業務架構:價值流、業務能力、業務流程、業務物件、組織架構架構物件
- 業務架構架構
- 業務架構、資訊架構、技術架構三位一體架構
- 微服務業務架構的探索微服務架構
- 關於軟體架構和業務架構的思考架構
- 新年程式設計師福利(多圖)程式設計師
- 按照業務領域畫資料架構圖 業務架構 資料架構架構
- SaaS業務架構:業務能力分析架構
- 【新年福利】2019年值得一用的8款協作工具
- 基於大中臺架構的電商業務中臺最佳實踐之一:業務中臺總體架構介紹架構
- CRM業務架構分析架構
- Java架構-到底什麼才是業務架構?Java架構
- Micronaut在2.0版本上邁出了一小步,但在無伺服器的Java上邁出了一大步 •DEVCLASS伺服器Javadev
- 在阿里架構師眼中構建一個較為通用的業務技術架構就是如此簡單阿里架構
- 業務單系統架構設計心得(一)架構
- 吊打面試官!業務架構的關鍵概念面試架構
- 新年福利|這款價值數萬的報表工具免費了!
- 架構的搭建(一)架構
- 2016新年福利!CoreThink×青雲Qingcloud合作GCCloud
- 打通MySQL架構和業務的任督二脈MySql架構
- 關於業務元件相關架構的討論元件架構
- 架構與思維:秒殺和競拍的業務架構,永不過時的話題架構
- 創業之初的技術題:如何構建一個較為通用的業務技術架構創業架構
- 趣頭條 業務架構師架構
- 架構思考-業務快速增長時的容量問題架構
- 低程式碼架構,內容賦能業務的最後一塊拼圖?架構
- 愛奇藝直播 - 春晚直播業務API架構API架構
- MySQL架構與業務總結圖MySql架構
- 極簡架構模式-業務代表模式架構模式
- 架構師之路 - 業務領域建模架構
- 秒殺業務架構優化之路架構優化
- App架構設計經驗談:業務層的設計APP架構