DDD N-Layered Architecture 心得雜感

學習了DDD N-Layered一段時間,發現真的是博大精深。
說到DDD N-Layered,下面這張圖,一定不陌生。
0825.image_75ECC48B
這邊我不打算講解這張圖,如果你想了解更多關於DDD N-Layered的知識,
可以到這邊下載電子書http://microsoftnlayerapp.codeplex.com/documentation
共有下面這幾個章節可以學習
– Chapter 1: Architecture Guide Introduction
– Chapter 2: The Architecture Design Process
– Chapter 3: N-Layered Architecture (Global Vision)
– Chapter 4: The Data Persistence Infrastructure Layer
– Chapter 5: The Domain Model Layer
– Chapter 6: The Application Layer
– Chapter 7: The Distributed Service Layer
– Chapter 8: The Presentation Layer
– Chapter 9: Cross-cutting Infrastructure Layers
– Chapter 10: Architecture and Patterns in ‘Cloud-Computing’ PaaS and Windows Azure
好了,本篇文章的主題開始,就是開始聽我講一些有的沒的。


其實我覺得DDD N-Layered Architecture(以下簡稱DDD)是一個很好的架構,
非常的適合大型專案與多人合作的環境。
如果完全的遵守DDD的規則來寫程式(1人專案),你會發現1個月後,你自己寫的程式,自己都看不太懂。
因為切的很細,實作的細節非常多。
0825.image_75ECC48B
舉個例子來說。如果依照DDD來實作(請看上圖)的話,每層的參考關係應該如下。
UI ---> Application Layer ---> Domain Model Layer <--- Infrasturcture Layer for Data Persistence(Data Access Layer)
如果以.Net來實作的話,共會有4個專案。

分別是UI、Application Layer、Domain Model Layer、Data Access Layer,

特別的是Domain Model Layer不參考任何Layer。。
ddd_test1
理論上UI那層不能夠直接存取到DB。必需透過Application Layer,Application Layer再去跟DataAccess Layer要資料,
因為這個專案有使用ORM,所以DataAccess Layer需要參考到Domain Model Layer的ORM Entity。
頭昏了嗎? 這還只是前菜,DDD整個存取模式的概觀。
接下來才是主菜。
因為UI那層看不到Domain Model Layer,UI也不知道什麼ORM Entity。
所以在Application Layer必需使用DTO(Data Transfer Object)來回傳資料,什麼是DTO? 有興趣的可以參考這篇。

In 91 Blog 的[工作心得]傳統程式架構到3-Layer架構的心路歷程

「理論上」ORM Entity 產生出來的Class是不太適合拿來當DTO的,因為如果ORM Entity產生出來的Class有變,
那麼前端的DTO結構就會受到影響,有可能會造成問題。
所以為了這個理論,在實作上程式就會非常的複雜。以下我就說幾個CRUD(Create、Read、Update、Delete) with ORM,且使用DTO的流程。
Create:
UI -> 把資料塞到DTO -> 把DTO傳到Application Layer -> Application Layer 把資料轉換成ORM Entity
-> 把ORM Entity傳到DataAccess Layer -> DataAccess Layer 把 ORM Entity 新增到資料庫 -> 完成。


Read:
UI -> 把查詢條件傳到Application Layer -> 依查詢條件向DataAccess Layer要資料
-> DataAccess Layer查到資料後回傳ORM Entity給Application Layer -> Application Layer 把 ORM Entity 轉換成DTO
->回傳DTO到UI ->完成


Update:
UI -> 把資料塞到DTO -> 把DTO傳到Application Layer -> Application Layer 把資料轉換成ORM Entity
-> 把ORM Entity傳到DataAccess Layer -> DataAccess Layer 依據傳進來的資料,使用ORM向資料庫查詢此筆資料,
並假設此筆資料名為UpdateRow1 -> 把要更新的資料一筆一筆的對映到剛剛查到的資料(UpdateRow1) ->
把更新後的資料(UpdateRow1)更新回資料庫中 -> 完成。


Delete:
UI -> 把刪除資料的條件傳到Application Layer -> 把刪除資料的條件傳到DataAccess Layer
->DataAccess Layer 依據傳進來的刪除條件,使用ORM向資料庫查詢此筆資料,並假設此筆資料名為DeleteRow1
-> 刪除此筆資料 -> 完成。


看到了嗎,上面就是要實現DDD所要付出的「代價」,幾乎就是 DTO 跟 ORM Entity在那邊轉來轉去。
不可否認DDD在多人、大型的專案下,的確有好處。
但是事實上,在台灣很多都是1人專案,這樣子搞,只會把自己搞死,萬一下一個接手的不會、也沒聽過DDD,
那就是整個系統砍掉重練。


用個比較生活化的例子來說:
你預計2年後要結婚,然後到時候需要有一棟房子住,而這棟房子你想自己1個人蓋(了不起3個人)。
這時候你會蓋一間小平房,能力好一點就蓋一棟透天厝。


但你總不可能為了考量到以後你要生3個小孩、把父母接過來、開一間公司,所以要把這房子蓋成商業大樓吧。
零零總總其實就是時程、品質、成本的考量與取捨。所以我想說的是,
不要為專案的未來做過多的假設,當然適度的假設是一定要的。


寫到這邊,你一定會覺得我在說DDD很爛,叫大家不要用。
其實不是的,我自己本身也很討厭那種1個檔案寫了好幾萬行的程式,全部黏在一起。
相反的我覺得DDD是個好架構,但是時程、人力、成本上的考量,我想要對DDD做一些修改,
讓程式簡化,但也保留了部份日後修改程式的彈性。


但修改會失去DDD架構中部份的彈性,所以這部份就見人見智了,
寫軟體沒有什麼方法是絕對好的,只有相對適合的方法。


上面CRUD(Create、Read、Update、Delete)的例子,很多工都卡在 DTO 與 ORM Entity 的互轉。
所以我想把這個部份省掉,做法就是讓UI這層直接參考到Domain Model Layer,
這樣子一來,就可以把 DTO 與 ORM Entity 互轉的工省掉了。每一層都直接用 ORM Entity Class來傳遞送。
如下圖所示。
ddd_test2
但這樣子做,代表前端的UI層與Domain Model Layer綁在一起了,日後如果ORM的模型如果有變,
前端UI的程式碼也會影響到,但相較於日後程式的可維護,我想對於1人專案來說,這是值得的。
如果你有更好的想法或是想發表一下見解,也歡迎於此篇文章中留言,大家一起討論。

新增評論

Loading