“業務邏輯層”在哪裡適合 MVC 應用程序?
首先,在有人大喊大叫之前,我很難用一個簡單的標題來概括它。另一個標題可能是“領域模型和 MVC 模型有什麼區別?” 或“什麼是模型?”
從概念上講,我將模型理解為視圖和控制器使用的數據。除此之外,對於模型的構成似乎有很多不同的意見。什麼是域模型、應用程序模型、視圖模型、服務模型等等。
例如,在我最近詢問儲存庫模式的一個問題中,有人直接告訴我儲存庫是模型的一部分。但是,我閱讀了其他意見,認為模型應該與持久性模型和業務邏輯層分開。畢竟,儲存庫模式不應該將具體的持久性方法與模型分離嗎?其他人說域模型和MVC模型之間存在差異。
讓我們舉一個簡單的例子。MVC 預設項目中包含的 AccountController。我已經閱讀了一些意見,其中包含的帳戶程式碼設計不佳,違反了 SRP 等等。如果要為 MVC 應用程序設計一個“適當的”成員資格模型,那會是什麼?
您將如何將 ASP.NET 服務(成員資格提供程序、角色提供程序等)從模型中分離出來?或者你會嗎?
在我看來,模型應該是“純粹的”,可能帶有驗證邏輯..但應該與業務規則分開(驗證除外)。例如,假設您有一條業務規則,規定在創建新帳戶時必須向某人發送電子郵件。在我看來,這並不真正屬於模型。那麼它屬於哪裡呢?
有人願意解釋這個問題嗎?
我這樣做的方式——我並不是說這是對還是錯,是擁有我的觀點,然後是一個適用於我觀點的模型。該模型僅包含與我的視圖相關的內容 - 包括數據註釋和驗證規則。控制器僅包含用於建構模型的邏輯。我有一個包含所有業務邏輯的服務層。我的控制器呼叫我的服務層。除此之外是我的儲存庫層。
我的域對像是分開存放的(實際上是在他們自己的項目中)。他們有自己的數據註釋和驗證規則。我的儲存庫會先驗證域中的對象,然後再將它們保存到數據庫中。因為我的域中的每個對像都繼承自內置驗證的基類,所以我的儲存庫是通用的並驗證所有內容(並要求它從基類繼承)。
你可能會認為擁有兩組模型是程式碼重複,並且在某種程度上是重複的。但是,在某些完全合理的情況下,域對像不適合視圖。
一個典型的例子是使用信用卡時 - 我在處理付款時需要一個 cvv,但我無法儲存 cvv(這樣做會被罰款 50,000 美元)。但是,我還希望您能夠編輯您的信用卡 - 更改地址、姓名或到期日期。但你不會在編輯時給我號碼或 cvv,我當然不會把你的信用卡號碼以純文字形式放在頁面上。我的域具有保存新信用卡所需的這些值,因為您將它們提供給我,但我的編輯模型甚至不包括卡號或 cvv。
這麼多層的另一個好處是,如果架構正確,您可以使用結構映射或其他 IoC 容器並交換部分,而不會對您的應用程序產生不利影響。
在我看來,控制器程式碼應該只是針對視圖的程式碼。顯示這個,隱藏那個,等等。服務層應該包含應用程序的業務邏輯。我喜歡將所有這些都放在一個地方,以便輕鬆更改或調整業務規則。儲存庫層應該相對笨拙——沒有業務邏輯,只查詢您的數據並返回您的域對象。通過將視圖模型與域模型分離,您在自定義驗證規則方面擁有更大的靈活性。這也意味著您不必將每條數據都轉儲到隱藏欄位中的視圖中,並在客戶端和伺服器之間來回推送(或在後端重新建構)。
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && Model.SomeObject.SomeInt == 3 && ...) { %>雖然一切似乎都分散並分層,但它有一個以這種方式建構的目的。完美嗎?並不真地。但我確實更喜歡它而不是過去從控制器呼叫儲存庫並將業務邏輯混合在控制器、儲存庫和模型中的設計。