簡體   English   中英

是否應將應用程序服務注入域服務

[英]Should An Application Service Be Injected Into A Domain Service

我正在使用帶有以下層的Entity Framework 6在WinForms應用程序上工作:

  • 介紹
  • 應用
  • 基礎設施

當用戶從UI單擊保存按鈕時,它將在應用程序層中調用應用程序服務並傳遞請求。 然后,應用程序服務通過請求調用域服務。 域服務調用域模型內的幾個實體,以對請求中使用的數據執行驗證。

域模型中的一個或多個驗證需要來自存儲庫的信息,以確定從表示層接收的請求中的數據是否符合某些業務規則。

我正在考慮兩種解決方案。

  1. 讓應用程序服務從存儲庫中檢索所需的信息以進行驗證,並將這些值傳遞到域服務中,域服務將調用域模型和實體來驗證傳入的規則和值請求。 然后,當域服務完成其驗證時,讓應用程序服務保存請求,這將導致控制權返回到同步等待驗證完成的應用程序服務。 如果執行此操作,則域層將沒有對存儲庫的直接或間接(注入)引用。 如果執行此操作,則域服務的單元測試將更加容易,因為沒有注入任何內容來執行驗證。 它所需要的一切都已經傳遞了。缺點是某些業務知識已放入應用程序服務中,因為現在它需要知道要檢索哪個存儲庫信息以驗證請求。

  2. 在調用域服務以驗證請求時,將應用程序服務的實例注入其中。 然后,域服務可以使用注入的應用程序服務從存儲庫中獲取信息,該應用程序服務的服務合同在域層中定義。 一旦所有信息都可用,它將根據需要傳遞給各個實體以驗證規則和值。 驗證完成后,域服務將使用注入的應用程序服務保存請求。 域服務完成並退出后,它將保存操作的狀態返回給一直等待驗證完成的應用程序服務。 然后,外部等待應用程序服務可以將保存結果返回到UI。 我這里擔心的是,在對域服務進行單元測試時,我將不得不模擬注入的應用程序服務。

哪種選擇或其他行動方案會更好? 提前致謝。

“應將應用程序服務注入域服務中”

沒有永不!

通常可以從應用程序服務中解析數據並將其傳遞給域服務,但是如果您認為域邏輯正在泄漏,則可以應用接口隔離原理(ISP)並根據合同約定在域中定義接口要求查詢“所需數據”。 在您的存儲庫或任何其他可以完成任務的對象上實現該接口,並將其注入到域服務中。

例如(偽代碼)

//domain

public interface WantedDataProvider {
    public WantedData findWantedData(...) {}
}

public class SomeDomainService {
    WantedDataProvider wantedDataProvider;
}

//infrastructure

public class SomeRepository implements WantedDataProvider {
    public WantedData findWantedData(...) {
        //implementation
    }
}

編輯:

我有一個帶有員工姓名的請求匯總根。 一個規則是員工必須是全職員工,而不是承包商

如果合計信息已經存在,則您也可以將此AR用作其他AR的工廠。 假設員工持有合同類型...

Employee employee = employeeRepository.findById(employeeId);
Request request = employee.submitRequest(requestDetails); //throws if not full time
requestRepository.add(request);

請注意,除非更改集合邊界,否則此處只能使最終不變,除非其他解決方案相同。

當域中的重要過程或轉換不是實體或值對象的自然職責時,請將操作添加為模型中的獨立接口,聲明為服務。 根據模型的語言定義接口,並確保操作名稱是“泛在語言”的一部分。 使服務成為無狀態-藍皮書Evans

不要過於傾向於將領域概念建模為服務。 僅在情況合適時這樣做。 如果我們不小心,可能會開始將服務視為建模的“銀彈”。 過度使用Services通常會導致創建Anemnic Domain Model(所有域邏輯都駐留在Services中)的負面后果。 -弗農,紅寶書

我試圖通過廣泛的引用來告訴您,您似乎將域服務視為必須擁有的東西,而您絕對不必這樣做。 您的應用程序服務可以愉快地使用存儲庫來獲取聚合,然后調用聚合根方法來執行必要的操作。 您的聚合根負責通過在內部執行必要的驗證來保護自己的不變量,並在出現任何問題時拋出驗證異常。

如果您絕對必須使用域服務,那么如果您做得對,就意味着您實現了洋蔥體系結構,其中內部層不了解外部層,您的域服務將無法了解應用程序服務。 但是,如果絕對必須,您可以將委托發送到域服務中,以執行應用程序服務所需的操作。 但是,這種情況太復雜了,難以置信。 看到您只需要進行驗證,請閱讀藍皮書和紅皮書中引用的部分,並做出正確的決定。 同樣,DDD中沒有強制性域服務,這是常見的誤解之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM