以前在專案開發時對分層架構所定下的原則,去避免不必要的地雷,以及每一層的要處裡的職權。
我會考慮分層架構,是希望提高系統的嚴謹度,以及 Method 的共用性,所以 Dao 層級就要避免功能導向,不然就是把單頁的程式拆分到多個層去而已。
DomainModel / ViewModel
- 這三類都屬於 POCO 類型的物件,單純的資料載體,不允許有動作的 method,不可以外部取資料
- 相同資料的欄位命名必須一致,反例: ProjectId, Pid, pid, PID, p_id
- 有欄位就要有資料,明明有欄位定義卻不從 DB 取資料,這會造成不必要的雷
DomainModel
- 欄位定義可與 DB 一致
- 將 DB 的資料進行彙整,成為完整的資料體
ViewModel
欄位定義與 View 的表單(Form)一致,與 DomainModel 可能很相似,但有些欄位只會用在表單上,所以 DomainModel 不適合用在表單 Binding 上
例如:
- 同意上述條款
- 舊密碼, 新密碼, 確認密碼
Dao
- 回傳 DomainModel
- 定義單純的 BD 操作 List, GetById, Save, Insert, Update
- 與 ORM 不同,是進一步將資料操作簡化
- 保證 Method 的通用性,避免功能導向,例如: 有一個 Method 是專門為了A畫面功能而存在的
Service
- 回傳 DomainModel
- 驗證商業邏輯,如必要資料欄位,數值範圍等...
- 調用一個或多個 Dao 來完成商業邏輯
- 處理 DB 交易,來協調多個 Dao 的調用
Controller
- 處理 DomainModel 到 ViewModel 的轉換
- 調用 Service 進行 DomainModel 的資料處理
- 調配 Responses 的結果 Html, Json, PDF ...
- 驗證資料類型的正確,數值﹑日期
- 負責 Access 的權限阻擋
View
- View 是被動的,不能存取任何 Controller / Service / Dao
- 負責資料呈現及格式化,如 日期﹑金額 ...
- Ajax 只能對 Controller 調用
附註
- 同一層之間不可以互相參考,這容易發生循環參考,例如:
- Controller 呼叫 Controller
- Service 呼叫 Service
- Dao 呼叫 Dao
- 同一層之間有相同邏輯可以抽離到 Support 類
- 建議定義命名規範,讓每一個人寫出來的程式像是同一個人寫的,好處是降低支援或接手的人的困難度
- 任何第三方的 API 都需要包裝,隔離直接相依的問題,而且可以單獨測試
架構關係全貌
Model 傳遞的關係
用 Interface 隔離實作
Web Api 的呼叫關係