1. 程式人生 > >領域驅動設計,讓程序員心中有碼

領域驅動設計,讓程序員心中有碼

需求 制造業 甚至有 model 表達 網頁程序 參與 控制系統 業務規則

我一直認為,程序員也是藝術家,他們撰寫的每一行代碼,是獻給這大好世界的優美詩篇。不同的人,寫的代碼也許風格迥異。有的,如春風化雨潤物無聲,有的,如高山流水,曲高和寡,還有的如旱日春雷,先聲奪人。而如果說,代碼是詩篇,那麽代碼的分層藝術絕對是最先映入讀者眼簾的序幕了。

     分層,一直以來是一個非常經典的軟件工程學問題,提到分層,無論是資深或者新入門的開發者,或多或少都有自己的理解。    

     在8年前,我剛參加工作時,有幸參與了比較多項目的研發和維護過程,這些項目的開發者,大多是比我年長幾歲的軟件開發者。在他們的開發習慣中,往往會傾向於直接在代碼中寫入用戶界面、數據庫訪問等支持代碼,甚至有相當一部分情況下,會把代碼寫入到用戶界面中,這意味著在用戶界面層,往往會寫入大量的代碼,說不定會超過上萬行代碼。我覺得可以將這種設計,理解為“單層架構“。

    再後來的項目開始有了一點點改變,這個時候的架構,被成為“三層架構“。在.NET開發史上,三層架構成為一種歷史悠久的框架,從十年前開始,一直到今天,依然是.NET開發者最為熟練的技術框架。如圖所示,三層架構在客戶端和數據庫之間增加了一個中間層,將有效的業務規則、數據訪問等放在業務層中進行處理。界面層主要使用對數據的綁定渲染,再通過數據層實現數據的提交處理。有的開發者說,三層架構通吃一切項目,似乎所有的項目都可以用三層架構來套用。然而在實際工作中,往往會忽略了業務邏輯層,業務邏輯往往會放在界面層或數據層中,最終導致界面層和數據層充斥著臃腫的代碼,令人難以維護。

技術分享圖片

   MVC架構也是一種非常主流的技術架構,這種架構是一種非常優秀的架構,他將用戶界面層通過模型層最早來源於上世紀七十年代,為Smalltalk語言所設計的一種模式,許多基於用戶界面的架構也受到了他的啟發。MVC架構,通過將邏輯、數據、界面顯示分離的形式,實現代碼的組織,廣泛適用於桌面端或網頁程序的開發過程。這種架構的特點是耦合性低、重用度高、生產周期短、部署快。但是同樣由於缺乏明確的定義,以及代碼過於集中,導致代碼腐化問題非常嚴重。

技術分享圖片

  MVP架構是從MVC架構中演進出來的典型代表,這種架構通過Presenter來處理邏輯,Model提供數據,View負責顯示。當然,他和MVC的區別在於,數據的顯示往往是通過Presenter來進行的,所有的界面操作也都是在Presenter中實現,這意味著View層,只是單薄的一層。

技術分享圖片

與此同時,開發者們也善於使用存儲過程或視圖等不同的方式寫入復雜的業務邏輯,期待的往往是如果是代碼發生變更時,只需對數據庫進行修改即可,而無需去修改已經部署在用戶端的大量的代碼。  使用存儲過程、觸發器或視圖等方式,時至今日,依然是備受關註的一種實現技術,尤其是面向傳統產業開發的項目,例如面向制造業的工業控制系統,要進行程序的部署仍然需要非常繁瑣的流程,這意味著用戶層的部署相對來說不方便,而數據庫的變動反而更方便。          

  不同類型的架構或設計的理念迄今仍深刻的影響著開發者的思維模式和工作方法,並最終或多或少的影響著軟件工程的實現。

  從高內聚,低耦合的軟件工程學基本原則來說,模塊與模塊之間的關系,稱為耦合,而模塊內部的關系稱為內聚。而分層的目的,正是為了在滿足這個基本原則的前提下,提高代碼的可用性和穩定性。過少的分層,意味著代碼可讀性必然很糟糕,甚至不利於軟件的編譯分發,而過多的分層,則同樣意味著模塊的維護將對整體過程代碼不便。

  領域驅動設計認為,如果代碼中,與領域相關的內容分散在不同的部分,那麽要進行業務和代碼的分析將變得難以下手。對用戶界面的簡單調整都可能意味著代碼邏輯的變化,而想要調整業務規則,可能需要開發者們去排查與之相關的所有部分,例如界面層,數據層,甚至是存儲過程和視圖,這種過程實際上已經沒辦法建立可用的業務模型,甚至沒辦法建立測試用例和單元測試的開展,只能靠開發者憑經驗去處理不同的情況。為了保證代碼的可用性,應當盡可能的分析理清所使用的技術和手段,程序層次設計應當簡單明了,易於理解。          

  在復雜系統設計中,分層是一種非常不錯的理念,其目的是為了更好的實現關註度分離,使設計的每個部分,既能得到單獨的關註,也能維護系統內部復雜的交互關系。領域設計認為,上述提到的幾種設計模式,往往是下面四種概念的某種變體。

用戶界面層(或者表示層),負責向用戶顯示信息和解釋用戶指令。這裏的用戶,既可以是使用用戶界面的人,也可以是另外一個計算機系統。
應用層:定義軟件要完成的任務,並且只會表達領域概念的對象來解決問題。這一層實際上負責的是系統與應用層進行交互的必要渠道。
領域層(或模型層)負責表達業務概念、業務狀態信息以及業務規則。盡管技術細節由基礎設施層實現,但業務情況狀態的反映則需要有領域層進行控制。領域層是業務軟件的核心。
基礎設施層:為上面各層提供通用的技術能力:為應用層傳遞消息,為領域層提供持久化機制,為用戶界面層繪制屏幕組件等等。基礎設施層還能夠通過架構框架來支持4個層次減的交互模式。
    在傳統項目中,往往不見得會如此鮮明的劃分層次,但是在進行模型驅動設計的關鍵,正是需要將領域層從復雜的業務代碼中抽離出來。在設計過程中,應當采取以下操作:

1、給復雜的應用層次劃分層次;

2、對每個層次進行獨立的設計,使其具有內聚性並且只依賴於它的下層;

3、采用標準的架構模式,只與上層進行松散的耦合。

4、將所有與領域模型有關的代碼放在一個層中,並讓它與用戶界面層、應用層和基礎設施層的代碼分開。

5、領域對象應當把重點放在如何表達領域模型上,而不需要考慮自己的顯示和存儲問題,也無需管理應用任務等內容。

6、模型設計的目的是達到含義豐富、結構清晰、業務鮮明。

   適當的分層,往往會通過架構框架的形式予以體現。在項目開發過程中,我們通常會使用一些框架,這些框架往往來源於平時項目的積累或者互聯網大佬的知識分享。但是這些框架往往不見得完全符合我們的項目需求。領域驅動設計認為,好的架構框架既能解決復雜技術問題,也能讓領域開發者集中精力去表達模型,而無需考慮其他問題。然而使用框架很容易為項目制造障礙,最終同樣會給人造成錯誤的理解,即,我們這個項目很簡單,並不需要復雜的框架。然而,筆者認為,大部分情形所認為的不需框架的原因,往往是項目確實非常簡單,或者開發者低估了項目的復雜度,或者由於公司短視的觀點,而忽略了代碼的架構設計和分層與建模工作,這最終導致項目容易陷入泥潭。

  當然,也同樣要克制欲望,貿然選擇難以駕馭的框架,反而讓項目開發過程變得不可收拾。因此,要選擇性的運用框架來解決問題,明智和審慎的應用框架的價值,讓開發者專註於核心業務問題的建模工作,才是提高開發效率和程序質量的手段。

領域驅動設計,讓程序員心中有碼