尼恩說在前面
在40歲老架構師 尼恩的讀者交流群(50+)中,最近有小伙伴拿到了一線互聯網企業如阿里、滴滴、極兔、有贊、希音、百度、網易、美團的面試資格,遇到很多很重要的面試題:
談談你的DDD落地經驗?
談談你對DDD的理解?
如何保證RPC代碼不會腐爛,升級能力強?
微服務如何拆分?
微服務爆炸,如何解決?
你們的項目,DDD是怎么落地實操的?
所以,這里尼恩給大家做一下系統化、體系化的梳理,使得大家可以充分展示一下大家雄厚的 “技術肌肉”,讓面試官愛到 “不能自已、口水直流”。
也一并把這個題目以及參考答案,收入咱們的 《尼恩Java面試寶典PDF》V130版本,供后面的小伙伴參考,提升大家的 3高 架構、設計、開發水平。
《尼恩 架構筆記》《尼恩高并發三部曲》《尼恩Java面試寶典》的PDF,請到文末公號【技術自由圈】獲取
除了本文,尼恩輸出了一個 《從0到1,帶大家精通DDD》系列,幫助大家徹底掌握DDD,地址是:
《阿里DDD大佬:從0到1,帶大家精通DDD》
《阿里大佬:DDD 落地兩大步驟,以及Repository核心模式》
《阿里大佬:DDD 領域層,該如何設計?》
《極兔面試:微服務爆炸,如何解決?Uber 是怎么解決2200個微服務爆炸的?》
《阿里大佬:DDD中Interface層、Application層的設計規范》
《字節面試:請說一下DDD的流程,用電商系統為場景》
《DDD如何落地:去哪兒的DDD架構實操之路》
《DDD落地:從騰訊視頻DDD重構之路,看DDD極大價值》
《DDD落地:從美團抽獎平臺,看DDD在大廠如何落地?》
《美團面試:微服務如何拆分?原則是什么?》
《DDD神藥:去哪兒結合DDD,實現架構大調優》
大家可以先看前面的文章,再來看本篇,效果更佳。
另外,尼恩會結合一個工業級的DDD實操項目,在第34章視頻《DDD的學習圣經》中,給大家徹底介紹一下DDD的實操、COLA 框架、DDD的面試題。
DDD現在非常火爆,是有其巨大生產價值,經濟價值的, 絕不僅僅是一套概念那么簡單。
DDD的絕大價值,具體請參見以下視頻:
從騰訊視頻DDD重構案例,看看DDD極大價值
文章目錄
- 尼恩說在前面
- 網易新聞App架構重構實踐
- 移動端架構與網站架構的區別
- 網易新聞客戶端的架構演進歷程
- 第一階段:Static Method
- 第二階段:MVP
- 第三階段:MVPs
- 第四階段:符合 DDD 的 VIPER
- 基于 DDD 的短視頻架構優化
- DDD 的選型與實踐
- 選型背景
- 落地難題
- 重構效果
- DDD 落地面面觀
- 說在最后
- 尼恩技術圣經系列PDF
網易新聞App架構重構實踐
作者:小智
嘉賓:李云鵬,網易新聞架構技術組工程師,國內首個移動架構模型書籍《移動開發架構設計實戰》作者。10 余年互聯網行業經驗,擅長移動端架構選型、項目重構與插件開發相關工作。曾就職于世界 500 強核心技術實驗室,作為第一發明人,申請了 14 項專利和著作權。
當前,大多數移動開發團隊將 MVP 作為業務層的核心架構模式,并在此基礎上實現了客戶端的組件化、插件化、容器化等。然而,作為業務層核心的 MVP 架構模式仍存在諸多問題。在領域驅動設計(DDD)思想的指導下,網易新聞 App 對其架構進行了全面重構,取得了良好的重構質量和項目收益。那么,移動端架構與網站架構有何不同?網易新聞客戶端的架構演變過程是怎樣的?為何選擇 DDD 思想來指導重構?在 DDD 實踐中應注意哪些方面?
移動端架構與網站架構的區別
傳統的網站架構,通過超文本傳輸協議,使得瀏覽器能夠便捷地將我們想要訪問的頁面展示出來。每個網站由多個頁面組成,這些頁面都屬于 Web Server 的一部分,如圖 1 所示。
圖 1 Website 與 Server 抽象模型
網站在大多數情況下無需關注離線化,而主要關注負載均衡、高并發和多級緩存等場景,以實時響應大規模流量。
相較之下,移動端 App 需先讓用戶進行安裝,然后才能訪問頁面。移動端的高并發網絡請求等場景通常交由 Server 端處理,而移動端更關注處理用戶交互和界面變化,如圖 2 所示。
圖 2 Application 與 Server 抽象模型
所以移動端和網站端的核心關注點不同,也就造成了二者在架構上的歷史演進的不同。舉一個簡單的例子,最初起源于 .NET Framework 3.0 的模型 / 視圖 / 視圖模型(MVVM)思想,從 WPF 應用過渡到 http://ASP.NET,用于網頁的開發,后來卻在移動端成為最流行的架構模式之一。
隨著網站端的歷史演進,網頁的工作量和跨平臺的需求增長迅速,使得網站前端開發的重要性日趨明顯,網站端已經抽象為了前端和后端,網站前端通過瀏覽器實現跨平臺,與移動端共同組成了大前端。
目前常見的移動端架構設計模式主要包括關注面向接口編程的 MVP(Model-View-Presenter)、關注數據驅動與雙向綁定的 MVVM(Model-View-ViewModel)、關注表現層分離的 MVC(Mode-View-Controller)和符合領域驅動設計思想(DDD)的 The Clean Architecture 等。
網易新聞客戶端的架構演進歷程
網易新聞客戶端的架構演進主要經歷了四個階段:Static Method、MVP、MVPs 和 VIPER。
為擺脫沉重晦澀的架構模型束縛,網易新聞客戶端團隊將一些軟件設計中的元素抽象為輕松的食品加工中的元素,用蛋糕模型來做示例。
第一階段:Static Method
從最初的設計階段開始,為了簡單地達到代碼的可復用性,新聞客戶端采用了一種 Static Method 的設計方式,將業務邏輯按照業務模塊轉移到一些工具類中,使得開發人員可以用最小成本復用這些業務邏輯。
在 Static Method 的模式中,技術團隊將 View 抽象為一塊蛋糕,蛋糕上需添加奶油、檸檬、櫻桃(Model)等食材。負責輸送材料的加工廠(Static Method)派遣工人(而非廚師)將材料直接運送并擺放在蛋糕上,如圖 3 所示。這樣蛋糕便具備了所有應有的食材成分。然而,食材擺放隨意,使得蛋糕顯得混亂,如果再繼續這樣堆砌食材,它就不再像是一塊蛋糕了。
圖 3 Static Method 蛋糕加工模型
因此,隨著時間推移和業務迭代加速,這種失去封裝、多態和繼承的面向對象特性的工具類設計難以應對業務變化。因此,轉向流行的 MVP 模式成為必然趨勢。
第二階段:MVP
傳統的 MVP 模式中,一個 View 由一個 Presenter 管理,在這種模式下產生了代碼復用的難題。
由于 Presenter 與 View 通過接口協議綁定,一個 Presenter 中的業務邏輯通常只能為一個 View 服務。因此,代碼復用性較差,容易產生大量冗余代碼。
Presenter 與 View 為一對一的方式,就像一塊蛋糕(View),指派給一個廚師(Presenter)去制作,但是廚師一個人需要做的事情太多,他需要親自加工食材(Model),再將這些材料一一裝飾在蛋糕上面,如圖 4 所示。如果這時候再告訴他我們的蛋糕還需要添加一些突然增加的裝飾和點綴,他可能會面臨崩潰。
圖 4 MVP 蛋糕加工模型
第三階段:MVPs
為解決 MVP 代碼復用問題,許多設計方法將 View 與 Presenter 改為多對一模式,即一個 Presenter 可為多個 View 服務,而一個 View 也可被多個 Presenter 控制。這意味著更多 Presenter 參與其中,會產生更多適應不同 View 的接口。
Presenter 與 View 為多對一的方式,就像一塊蛋糕(View),指派給多個廚師(Presenters)在共同加工。而每個廚師可能會處理多塊蛋糕,他們同時還要做好手上的裝飾品(Model),再親自將其放在每個蛋糕上。在這期間,廚師們直接接觸每塊蛋糕時,還加入了很多他們擅長的但是蛋糕不需要的手藝。多個廚師圍著一塊蛋糕轉,蛋糕有了很多他原本不想擁有的東西,而這些廚師們也難以管理,他們直接操控蛋糕,沒人能夠合理控制他們,如圖 5 所示。因此,新聞客戶端逐步過渡到符合 DDD 的 VIPER 模式。
圖 5 MVPs 蛋糕加工模型
第四階段:符合 DDD 的 VIPER
在符合領域驅動設計的 VIPER 架構設計模式下,一塊蛋糕(View)只由一個主廚(Presenter)進行裝飾擺放,但是蛋糕上所有的飾品食材,都由這位主廚指派給多個不同的廚師(Interactor)進行加工(Entity)。當這些廚師加工完畢后,再把材料送過來,通知主廚,由主廚親自進行擺放。
那些負責加工的廚師沒有機會再直接接觸到蛋糕,蛋糕只有它原本應有的樣子,變得更加利于加工制作。更美好的是,以往蛋糕需要每個廚師親自配送到它需要被送達的地方,現在廚師只需要打個電話,一切配送工作都將由快遞員(Router)去完成,如圖 6 所示。
圖 6 VIPER 蛋糕加工模型
通過這種分工合作的模式,VIPER 架構不僅提高了工作效率,還降低了出錯率。每個環節都有專門的負責人,使得整個流程更加順暢。此外,這種架構還有助于后續的迭代和升級,因為各個模塊之間的耦合度較低,便于獨立開發和更新。
基于 DDD 的短視頻架構優化
以網易新聞客戶端的視頻詳情頁為例,新聞客戶端的視頻詳情頁結構可以抽象為圖 7。初期設計的視頻詳情頁,所承載的業務并不多,界面也較為簡單,Holder、子頁面和適配器等都在 Fragment 類中定義實現。但是隨著短視頻風口的到來,業務加速迭代,視頻的業務需求急劇增加,視頻詳情頁所需要承載的業務也越來越多,Fragment 類從最初的幾百行,急速擴張到兩千多行。基于舊有的視頻詳情頁設計,加入新的業務,使得維護成本變得越來越高,類也變得越來越大,臃腫膨脹的類已經變為了“面條代碼”。
圖 7 視頻詳情頁抽象結構
基于 DDD 的思想,新聞客戶端實現了一套包含 UseCase 的基礎框架,劃分出了領域模型,由于視頻詳情頁由多 Fragment 組成,技術團隊還加入了共享變量層,使擁有統一生命周期的組件之間能解耦傳遞數據,重構后的視頻詳情頁整體架構如圖 8 所示。
圖 8 視頻詳情頁重構后的架構設計圖
DDD 的選型與實踐
選型背景
新聞客戶端的多數業務模塊在設計初期的時候,多數業務模塊所承載的業務量并不大。但隨著需求的逐漸增加,為了快速迭代,開發人員往往將代碼堆積在一起,導致業務模塊間的邊界變得模糊,耦合度也越來越高。
為了解決這個問題,DDD 的限界上下文為技術團隊提供了明確領域模型邊界和實現解耦的方法。VIPER 是一種符合 DDD 理念的架構模型,盡管最初在 iOS 端流行,但其核心思想與 The Clean Architecture 相似,因此同樣適用于 Android 端,成為一種通用解決方案。
落地難題
在將 DDD 落地的過程中,團隊遇到的比較困難的問題大致是兩方面,一方面在于優化工作流程,另一方面在于轉變編碼思想。
在工作流程方面,傳統需求評審涉及產品經理、項目經理、軟件工程師、UI 交互設計師等,但關注點往往集中在整體業務,事件劃分不夠明確。要推動多個團隊改變評審方式以確定限界上下文的事件風暴,具有一定的困難。因此,開發團隊在編碼階段開始前,進行內部技術評審,邀請準領域專家與開發人員共同分析討論界限上下文。
在編碼思維方面,團隊成員需要接受 DDD 思想,轉變為領域驅動思維。技術團隊組織了一系列相關分享,通過編程中的“隱喻”,讓大家逐步建立對 DDD 的認識,加深理解。
重構效果
在基于 DDD 的架構重構初期,新聞客戶端選擇了視頻詳情、視頻列表和圖集三個業務模塊進行 VIPER 重構,以探索 DDD 的實際應用。
- 在重構質量上,先確定領域模型,代碼整體解耦符合預期,三個模塊重構后上線均未出現嚴重線上問題。
- 在項目收益上,一方面,DDD 幫助團隊提高迭代開發效率;另一方面,代碼可維護性大幅提高,模塊錯誤率降低約 50%。
新聞客戶端以半年為周期,統計模塊重構前半年與重構后半年的系統故障率(主要指開發期間產生的問題),如圖 9 所示。數據表明,業務變化頻繁的模塊(如視頻)通過 DDD 獲得的模塊穩定性收益更為顯著。
通過采用 DDD 理念進行架構重構,新聞客戶端在快速迭代和需求變化的過程中,實現了更高的靈活性、可擴展性和代碼質量。通過明確領域模型邊界、優化工作流程和轉變編碼思維,團隊成功應對了落地難題,為客戶端在競爭激烈的市場中奠定了基礎。
圖 9 DDD 重構前后系統故障率統計圖
DDD 落地面面觀
自從2003年領域驅動設計(DDD)概念提出以來,它在軟件學術界贏得了廣泛認可。然而,受到國內外開發環境、開發者觀念等多種因素影響,DDD在國內的實際應用并未完全達到預期效果。從2013年開始,微服務架構和中臺化在國內逐漸興起,DDD作為指導原則,有助于明確劃分領域和子領域,因此在企業應用實踐中取得了良好成果,成為國內突然流行的主要原因之一。
對開發團隊而言,實施DDD的關鍵環節是通過事件風暴進行領域分析建模,這對領軍人物的領域素養要求較高,需要承擔領域專家的職責。
針對移動端領域,The Clean Architecture 是目前最適合、符合 DDD 理念的架構模型。Google 官方推出的安卓藍圖項目為 MVP 提供了一套符合 The Clean Architecture 的 MVP-Clean 項目,開發者可以借此展開逐步探索和嘗試。
由于國內外軟件工程師的職業環境和所承受的壓力有所不同,在面對突發業務需求沖擊時,開發者往往只能瘋狂堆疊代碼,導致被迫放棄 DDD 設計。需求變更時,容易出現風險。
在風險加劇的情況下,各種推諉責任的現象頻發,問題本質歸咎于組織結構、環境因素以及邊界劃分不明確。
針對組織和團隊層面,初期無需大規模調整,即可滿足 DDD 轉型需求,并為后續微服務和中臺化建設提供便利。但需注意,改變團隊成員固有的開發思維至關重要,團隊內應定期舉辦 DDD 相關分享,使大家對 DDD 觀念逐漸認同。
總之,在國內軟件開發環境中,實踐 DDD 具有重要意義。遵循 DDD 原則,開發者能夠更好地應對業務需求變化,提高代碼質量和系統穩定性。在組織及團隊層面,推動 DDD 轉型有助于微服務架構和中臺化的實施,提升整體開發效率。為實現這些目標,團隊需共同努力,培養領域素養,明確邊界劃分,并改變固有思維,為 DDD 實踐奠定堅實基礎。
說在最后
DDD架構如何落地,是是非常常見的面試題。
以上的內容,如果大家能對答如流,如數家珍,基本上 面試官會被你 震驚到、吸引到。
在面試之前,建議大家系統化的刷一波 5000頁《尼恩Java面試寶典PDF》,并且在刷題過程中,如果有啥問題,大家可以來 找 40歲老架構師尼恩交流。
最終,讓面試官愛到 “不能自已、口水直流”。offer, 也就來了。
當然,關于DDD,尼恩即將給大家發布一波視頻 《第34章:DDD的學習圣經》, 幫助大家徹底穿透DDD。
尼恩技術圣經系列PDF
- 《NIO圣經:一次穿透NIO、Selector、Epoll底層原理》
- 《Docker圣經:大白話說Docker底層原理,6W字實現Docker自由》
- 《K8S學習圣經:大白話說K8S底層原理,14W字實現K8S自由》
- 《SpringCloud Alibaba 學習圣經,10萬字實現SpringCloud 自由》
- 《大數據HBase學習圣經:一本書實現HBase學習自由》
- 《大數據Flink學習圣經:一本書實現大數據Flink自由》
- 《響應式圣經:10W字,實現Spring響應式編程自由》
- 《Go學習圣經:Go語言實現高并發CRUD業務開發》
……完整版尼恩技術圣經PDF集群,請找尼恩領取
《尼恩 架構筆記》《尼恩高并發三部曲》《尼恩Java面試寶典》PDF,請到下面公號【技術自由圈】取↓↓↓