昨天妹子讓我幫她解決個問題,本覺得能夠輕鬆搞定,可是打開他們項目的一瞬間,我頭皮發麻。自己功能很少的一個小項目,解決方案里居然有幾十個類庫。僅僅搞明白各個類庫的做用,代碼層次之間的引用關係就花了一個多小時。 前端
顯然可能他們項目結構的代碼模型出了問題,設計混亂,不容易上手。java
項目中一個好的的代碼模型必定是簡單、清晰、明瞭、易於上手的。它老是會讓人用起來很舒服,它可讓項目團隊成員更好地理解代碼,根據代碼規範實現團隊協做;它可讓各層的邏輯互不干擾、分工協做、各據其位、各司其職,避免沒必要要的代碼混淆。它可讓咱們的代碼擴展性很好,可讓系統的可維護性更好......web
而代碼模型的搭建跟項目的分層架構有關係,絕大多數項目開發中都會會採用分層開發,它有着分散關注、鬆散耦合、邏輯複用、標準定義、擴展性強等衆多好處。而在分層架構中最經常使用的有兩種:三層架構和DDD(領域驅動)分層架構。咱們選擇的分層方式也決定了咱們的項目結構中的代碼模型。數據庫
三層架構是一種嚴格分層模式,而嚴格分層架構模式的特色是上層只能訪問相鄰的下層,其餘層次間的調用都不容許。它把職責劃分爲界面展現、業務邏輯、數據訪問三層,還有一個業務實體,前面三層都要依賴它,因此它並不構成一個層。編程
三層架構是一種面向過程的編程思想,它有幾個特色後端
在使用三層架構開發的時候咱們一般會直接將數據表結構映射爲業務實體類。這樣的好處是隻須要理解一套模型,以致於市場上也產生了一系列的代碼生成工具能夠一鍵生成實體和增刪改查的代碼。但對於複雜點的業務,這樣作也會產生不少的問題。api
而當業務再也不是簡單的增刪查改時,咱們能夠在三層架構的基礎上有個簡單的變形:提取一個服務層出來,用來組合模塊間的交互,還爲業務邏輯層提供了一個防腐層,能夠把記錄日誌、驗證權限、處理異常等職責分配給服務層。緩存
三層架構有一個顯著缺點就是它的內存模型不是基於業務模型而是是基於數據庫模型創建的。而不少時候咱們的業務模型並不能和咱們的數據庫模型徹底吻合。安全
例如:若是你的數據庫模型的粒度很小。有些業務就須要鏈接多張數據庫表才能實現。而若是數據庫模型的粒度很大(這是大部分項目的選擇),代碼的質量(重用性、穩定性、擴展性)就不好。因爲沒有從業務的角度去仔細定義每個對象,每一個人會根據本身的須要創建各類QueryModel或ViewModel(相信三層架構用久了的同窗都會遇到這個問題)。架構
並且如今不少大型系統都會採用分佈式的架構,如如今的微服務架構。服務內不只僅是簡單的增刪查改,會有更多的與其它服務交互的內容,而服務的拆分也是以業務模型爲導向的。
這個時候DDD(領域驅動)分層架構就會更有優點。
DDD分層架構主要包含四層:用戶接口層、應用層、領域層、基礎層。
DDD分層架構也分爲嚴格分層架構和鬆散分層架構,在嚴格分層架構中,領域服務只能被應用服務調用,而應用服務只能被用戶接口層調用,服務是逐層對外封裝或組合的,依賴關係清晰。而在鬆散分層架構中,領域服務能夠同時被應用層或用戶接口層調用,服務的依賴關係比較複雜且難管理。所以我我的推薦使用嚴格的分層架構
對於項目開發中應該如何選擇咱們能夠基於兩點考慮:系統自己的業務複雜度和團隊人員能力。
若是大家的系統只是個簡單的小系統有或者系統自己業務並不複雜,基本都是些增刪改查。那麼三層架構將是你良好的選擇。它會讓你的開發變得簡單,會大大提升你的開發效率,並且這種分層架構的學習成本很低,新人簡單熟悉就能夠很容易的上手。對於簡單的系統使用DDD分層,反而增長了系統的複雜度。
而若是大家的系統很複雜或者對於一些成長性的網站系統(一開始很小,隨着業務發展慢慢壯大的系統),那麼你能夠考慮使用DDD分層架構,DDD的思想可讓你更好的對業務進行建模,這種分層架構會讓你的系統擴展性很好,在網站壯大的過程當中,單體系統必然會向分佈式系統進行發展,而DDD的思想能夠對服務進行很好的拆分,如當下的微服務架構,DDD的思想就能夠幫助咱們很好的定義服務的邊界。
團隊人員的能力仍然是選擇要考慮的因素。由於DDD對於人員的能力要求相對於三層架構要高。它須要團隊的人員要有一個良好的邏輯思想和建模能力,並且DDD的學習成本也要高一些。若是你的團隊成員能力通常或者以入行不久的新人爲主,或者你的團隊人員流動性較大的話,也是不建議使用DDD的。這種狀況下使用三層架構會更好一些。
總有些人會以爲DDD的概念「高大上」,所以爲了使用DDD而使用DDD,更有甚至,根本都沒有真正弄明白DDD,就開始使用,最終搞的個四不像,不只沒有解決問題,反而徒增了系統複雜度,拉低性能和效率,其實真正項目中改如何選擇,應該結合你的團隊和系統來,權衡利弊綜合考慮。簡單、優雅、方便、快捷的解決問題豈不是更好?
一旦選定了分層架構,項目中所對應的代碼模型也就肯定了。咱們以.net爲例(java只須要把程序集當成jar包來看就能夠了),推薦下面這兩種代碼模型。
這是最簡單的三層架構代碼模型,業務邏輯層,數據訪問層,應用接口層(界面層,界面層能夠是mvc,也能夠是webapi。(由於如今不少項目都是先後端分離,服務端開發人員不須要寫頁面,因此就沒有寫MVC,界面層我也改叫用戶接口層了)。。固然如今幾乎是沒有人這麼用的。由於這樣作的依賴性很高。不利於擴展。所以咱們要引入依賴倒置的概念。所以咱們的結構須要作以下變形
這種結構在簡單三層的基礎上對業務邏輯層和數據訪問層引入了其抽象層,這樣就很好的將層與層之間的依賴關係進行了解耦。
好比,我曾經遇到多個項目數據庫從MSSQL轉到MySql。在三層架構中,其實大量的邏輯都應該被封裝在業務邏輯層。這個時候咱們是須要把DAL換成MySql的DAL,業務邏輯不須要任何改動。若是是最簡單的三層架構那種絕對依賴關係,咱們必然要改動業務邏輯層以接入新的DAL。而這種依賴倒置的層次結構則不須要。
因爲三層架構中同層引用時應該避免的。業務邏輯也是基於數據庫模型創建的,而有些業務則須要組合多個業務來實現,爲了實現業務邏輯代碼複用有些能夠採用繼承和多態的方式來實現。有些時候則須要再引入一個服務層(防腐層)來組合模塊間的交互。也能夠把記錄日誌、驗證權限、處理異常等職責分配給這一層。
不少項目可能還要加個工具層,用來放一些經常使用的工具類。可是工具類這個東西,與項目有關的能夠放在這裏,若是是多項目之間能夠複用的,最好用更專業的作法:單獨管理維護,打包成Nuget包(maven包),由各個項目進行調用。
按照 DDD 分層架構模型設計出來的代碼模型應該長什麼樣子呢?
如上圖所示:
應用層
Event:存放事件相關代碼,能夠進行事件的發佈和處理。事件發佈和訂閱放在應用層,事件相關的業務邏輯放在領域層。
Service:對多個領域服務或外部應用服務進行封裝、編排和組合,對外提供粗粒度的服務。應用服務主要實現服務組合和編排,是一段獨立的業務邏輯。
領域層
基礎設施層
在DDD的代碼模型中須要注意的是:
毫無疑問,項目中選擇合適的分層架構並設計一個優秀的代碼模型有着巨大的好處,但實際上不管是三層架構仍是DDD分層架構都沒有明確的規定其標準的代碼模型。所以以上兩種代碼模型僅供你們參考。
而常常會有些設計者在設計的時候總喜歡「炫技」,設計出來的代碼模型「深奧複雜」、晦澀難懂,美其名曰「高大上」。熟不知大道至簡,優秀的設計是用簡單的方式解決複雜的問題,而不是把簡單的問題複雜化,在解決問題的基礎上,簡單實用纔是正途!
最後,但願每一個項目都能有一個好的設計人員,結合實際狀況,設計出一個好的代碼模型,利己利人!