軟件架構編年史:分層架構

在一個面向對象的程序裏,UI、數據庫和其它支撐代碼會被寫到業務對象裏。額外的業務邏輯也會被嵌到 UI 控件和數據庫腳本里。這是由於在短期內完成夠用的代碼是更簡單的選擇。

當領域相關的代碼擴散到這樣大規模的其它代碼中,要發現和理解這些代碼會相當困難。表面上對 UI 的修改實際上也會改變業務邏輯。要修改業務規則就得小心翼翼地追蹤 UI 代碼、數據庫代碼,或者其它的編程元素。實現內聚的、模型驅動的對象變得不切實際。自動化測試也變得尷尬。如果每個活動都要捲入所有的技術和邏輯,程序必須非常簡單,要不然就完全無法理解。

——Eric Evans 2014, Domain-Driven Design Reference

在分層架構中,分層的使用可以嚴格地限制:分層只知道直接的下層,或者可以寬鬆一些:分層可以訪問它之下的任何分層。Martin Fowler 和我自己的經驗都是第二種方式實際中會更好,因爲它避免了在中間分層創建代碼方法 (或者完整的代理類),也避免了退化成千層面的反模式 (下文會詳細探討)。

它的優勢有:

它的劣勢在於:

◐ 20 世紀 60 年代和 70 年代

儘管上世紀 50 年代軟件開發就開始了,它真正發展成我們今天所見的這樣是在 60 年代和 70 年代,隨着構建可以被髮行、部署並可以被除了開發者自己之外其它人使用的應用的活動發展起來的。

然而,當時的應用程序和今天的應用程序截然不同。那時還沒有 GUI(大概 80 年代末 90 年代初纔出現),所有的應用程序要通過命令行使用,顯示在一個啞終端裏,它只是將用戶的輸入傳輸給應用程序,應用程序很可能就在同一臺電腦中被使用。

應用程序此時還十分簡單,還不需要分層,它們被部署到一臺電腦之中被使用。它們實際上是單層的應用程序,儘管有時啞客戶端還是遠程的。儘管這些應用程序非常簡單,但它們卻無法伸縮,例如,如果我們需要升級軟件的新版本,我們要在每臺安裝了該軟件的電腦上升級。

◐ 20 世紀 80 年代和 90 年代的分層

在 20 世紀 80 年代,企業應用出現了,在公司裏有多個用戶開始使用桌面電腦通過網絡訪問應用。

這時它們多半分成三層:

用戶界面 (展現):用戶界面就是網頁、命令行或者原生桌面應用;

例如:作爲 (富) 客戶端的 Windows 應用,普通用戶在桌面電腦上使用,和服務器器通信才能完成工作。客戶端負責應用的流程和用戶輸入的校驗;

業務邏輯 (領域):應用之所以存在的邏輯;

例如:應用服務器,包含業務邏輯並從原生客戶端接收請求,採取行動並將數據保存到數據存儲;

例如:數據庫服務器,應用服務器用它來完成數據持久化。

隨着使用上下文的變遷,分層實踐開始得到應用,儘管它真正得到大範圍的實踐是在 C/S 系統崛起的 20 世紀 90 年代。這實際上是一種 兩層 應用,客戶端是一個用爲應用界面的富客戶端應用程序,而業務邏輯和數據源放在服務器。

這種架構模式解決了伸縮性問題,因爲很多用戶可以獨立地使用應用,只需要另外一臺安裝了客戶端應用程序的桌面電腦就行。然而,如果我們有數百或者數十個客戶端而我們想用更新應用程序的話,操作會特別複雜,因爲我們要一個一個地更新客戶端。

◐ 20 世紀 90 年代中期之後的分層

這就是三層架構模式,也叫 N 層架構。它是可伸縮的解決方案,儘管用戶界面是在客戶端瀏覽器中渲染和運行,但由於用戶界面存放於服務器上並在服務器上編譯,它 “解決了客戶端的更新問題”。

◐ 新世紀之後的分層

2003 年, Eric Evans 出版了他的標誌性著作 Domain-Driven Design: Tackling Complexity in the Heart of Software。在書中提出的許多關鍵概念之中,也有對軟件系統分層的展望:

用戶界面

負責繪製用戶和應用交互的界面,並將用戶輸入轉換成應用的命令。值得注意的是,“用戶”可以是人類也可以是其它應用。它和 Ivar Jacobson 的 EBI 架構 (後面其它文章會介紹更多細節) 中的邊界對象不謀而合;

應用層

指揮領域對象完成用戶要求的任務。它不包括業務邏輯。它和 Ivar Jacobson 的 EBI 架構中的交互器對象對應,唯一不同的是 Jacobson 的交互器可以是任意和界面或實體無關的對象;

領域層

這一層包含了所有的業務邏輯、實體、事件或者其它任何包含業務邏輯的對象類型。顯然它和 EBI 中的實體對象類型相對應。這是系統的心臟;

基礎設施

支撐上面所有層次的技術能力,如持久化機制和消息機制。

◐ 反模式:千層麪架構

千層麪架構常常說的就是分層架構的反模式。以下這些情況發會出現:

◐ 總結

分層架構是另一種根據代碼在應用中的功能角色對代碼單元進行劃分的方式,它帶來了關注點的分離、封裝性和解耦。

然而,和生活中的很多事情一樣,過猶不及!所以,最重要的一條經驗是:只使用必要的層次和物理層次,夠用就行!我們千萬不要得意忘形地追逐架構的聖盃,它根本就不存在。存在的只是需求,和最可能恰好符合它的架構。順便說一句,這也是精益所提倡的。

此外,還有一點值得注意,上 / 下這種縱向的分層方式已經過時了。現代的軟件開發中我們不應該使用這種方式了,應用的層次有更好的新思路。我會在接下來的文章中進行探討。

◐ 引用來源

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ivUmJkZkNyrifQKqpbha-w