五月 29

學習了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人專案來說,這是值得的。

如果你有更好的想法或是想發表一下見解,也歡迎於此篇文章中留言,大家一起討論。

留下評論