Skip to content
Rain Hu's Workspace
Go back

[IT] 分層架構 Layered Architecture

hgraca

分層是一種常見於系統中做法,用於分隔或組織程式碼,根據程式碼在系統中的角色或職責。

In an object-oriented program, UI, database, and other support code often gets written directly into the business objects. Additional business logic is embedded in the behaviour of UI widgets and database scripts. This happens because it is the easiest way to make things work, in the short run.
When the domain-related code is diffused through such a large amount of other code, it becomes extremely difficult to see and to reason about. Superficial changes to the UI can actually change business logic. To change a business rule may require meticulous tracing of UI code, database code, or other program elements. Implementing coherent, model-driven objects becomes impractical. Automated testing is awkward. With all the technologies and logic involved in each activity, a program must be kept very simple or it becomes impossible to understand. - Eric Evans 2014, Domain-Driven-Design
在物件導向的程式中,使用者介面、資料庫和其他輔助程式碼常常直接被寫入商業物件中,額外的商業邏輯被嵌入在使用者介面和資料庫腳本,因為這是最簡單且最快速使事情可以運作的方式,導致這種情況時常發生。
當與領域相關的程式碼在更大量的程式碼中擴散,程式碼便開始變得困難且難以理解,UI 的變更可能導致業務邏輯的改變,同樣地,業務邏輯的更動需要密切地追縱 UI、資料庫與組其它組件的程式碼。實作內聚且以模型驅動的物件變得不可行、自動化測試變得笨拙,由於每個動作都涉及到所有的技術和邏輯,程式必須保持簡單,否則就會難以理解。 - 艾瑞克‧埃文斯 2014, 領域驅動設計

分層的意義

在一個分層系統中,每一層:

在分層架構中,可以用嚴格的方式定義:該層只能訪問其底下的層;或以更靈活的方式定義:該層可以訪問其下的任何層。馬丁‧福勒(Marting Fowler)和我自己的經驗都告訴我,第二種情況在實作中似乎效果更好,因為它避免了在中介層(intermediary layers)中創建代理方法(proxy methods),甚至完整的代理類別(proxy classes),並可能退化為 Lasagna Architecture 的反模式(下面有更多關於它的信息)。

Sometimes the layers are arranged so that the domain layer completely hides the data source from the presentation. More often, however, the presentation accesses the data store directly. While this is less pure, it tends to work better in practice. - Fowler 2002, Patterns of Enterprise Application Architecture
有時候,各層會被安排得使得領域層完全隱藏了資料來源,使其對於呈現層來說是不可見的。然而,更常見的情況是,呈現層會直接存取資料儲存庫。雖然這種方式較不純粹,但在實際操作中,這種方式往往效果更佳。 - Fowler 2002,企業應用架構模式

優點如下:

缺點如下:

60年代與70年代

雖然軟體開發始於50年代,但我們今日所知的,可以被交付、部署且供非開發者自己使用的應用程式的軟體開發模式,實際上是誕生於60年代和70年代。

然而,60年代與70年代的應用程式仍與今日的形式大相逕庭,當時並沒有 GUI(該技術是80年代末或90年代初才出現),所有的應用程式只能透過 CLI 操作,並在一個只會傳送使用者輸入內容的簡單終端機上顯示。而這些應用程式,很可能都是在同一台電腦上使用的。 1-tier

這些應用程式相當簡單,因此並未考慮到分層的設計,且它們被部署並在一台電腦上使用,實質上它們是單層(one-tier)的應用程式,雖然在某些時候,這種簡單的客戶端可以是遠端的。然而這些應用程式雖簡單,但它們並不具有可擴展性,例如,如果我們需要將軟體更新到新版本,我們將必須在每台已安裝該應用程式的電腦上進行更新。

80年代與90年代

在1980年代,企業應用程式開始活躍起來,我們開始看到在公司中有多個使用者在桌機上透過網路使用這些應用程式。

在這個時候,主要有三層:

隨著使用情境的轉變,分層開始成為一種實踐,儘管它直到1990年代(Fowler 2002)才開始因客戶端/服務器(client/server) 系統的興起而普遍。這實際上是一種兩層(two-tier)應用程式,其中客戶端將是用作應用程序介面的豐富客戶端應用程序,而服務器將具有業務邏輯和數據源。

這種架構模式解決了可擴展性問題,因為多個用戶可以獨立使用該應用程式,我們只需要另一台桌面電腦,將客戶端應用程式安裝在其中即可。然而,如果我們有幾百個,甚至只有幾十個客戶,並且我們想要更新應用程式,那將是一項高度複雜的操作,因為我們必須一個接一個地更新客戶端。

90 年代中期之後

大約在1995年至2005年間,隨著向雲端環境的普遍轉變,應用程式使用者的增加,應用程式的複雜性和基礎設施的複雜性的提高,我們最終看到了分層方案的演變,其中一個典型的實施可能是:

這是一種三層(3-tier)架構模式,也被稱為n層架構。這是一種可擴展的解決方案,並解決了更新客戶端的問題,因為用戶介面存在並在伺服器上編譯,儘管它是在客戶端瀏覽器上渲染和運行的。

2000 年以後

在2003年,Eric Evans發布了他的標誌性書籍《領域驅動設計:解決軟體核心的複雜性》。在該書中發布的許多關鍵概念中,也包含了對軟體系統分層的視野: ddd

反模式:千層麵架構 Anti-pattern: Lasagna Architecture

Lasagna Architecture」通常被用來指稱分層架構的反模式。當以下情況發生時:

Conclusion 結論

分層架構是另一種提供關注點分離、封裝和解耦的方式,通過將程式碼單元按照其在應用程式中的功能角色進行分組。

然而,就像生活中的大部分事物一樣,過度反而會適得其反!所以,經驗法則是:只使用我們需要的層次,我們需要的階層,而不多做任何事!我們不能為了追求不存在的建築聖杯而忘我。真正存在的是需求,以及最適合該需求的最佳選擇。這也是 Lean 的一部分,順帶一提。

此外,值得注意的是,這種自上而下的分層方法已經過時。在現代軟體開發中,我們不應再採用這種方式,有新的且更好的方式來思考應用程式的層次。我將在接下來的文章中討論這些。


Share this post on:

Previous
[IT] MVC 及其變形
Next
[IT] 單體架構 Monolithic Architecture