我正在開發一個3層應用程序(不是3層!),其中一個層(物理羣集)上運行的客戶端應用程序與另一個服務應用程序層和另一層上的數據庫服務器。應用程序有很多業務規則,流程邏輯等,我相信應該可以在應用程序層和服務層上使用,以改善用戶體驗,減少對服務的調用並消除冗餘編碼。.NET中的分佈式DDD:與客戶端共享域對象
讓我們用這個例子:在我的領域層,我有一個Document對象。該對象包含AllowPublish屬性,該屬性檢查對象的內部狀態,如果狀態允許發佈文檔,則返回true/false。該對象還具有一個Publish方法,該方法通過將IsPublished標誌設置爲true並引發已發佈的域事件來修改對象的內部狀態,以反映它正在發佈的事實。
我有一個單獨的AuthorizationService,它確定是否允許當前用戶發佈以及將該對象持久化到數據庫的DocumentRepository。
在我的服務應用程序中,我的DocumentService有一個PublishDocument方法,它接受文檔ID,使用ID從存儲庫中檢索文檔,檢查AllowPublish屬性,如果爲true,則調用Publish然後使用存儲庫持久更新的對象。
我在客戶端上的行爲稍有不同。在這種情況下,我使用AllowPublish屬性來啓用/禁用命令按鈕。啓用並單擊後,我會調用一個服務代理,該服務代理公開一個接受文檔ID的PublishDocument方法。代理將該調用傳遞到具有相同名稱的服務應用程序的DocumentService方法。爲了消除重複的代碼,共享業務邏輯,驗證規則等,我將域對象放置在一個單獨的程序集中,由客戶端應用程序和服務應用程序共享。這意味着客戶端應用程序現在可以訪問我的Document類的Publish方法,儘管它只與我的服務應用程序有關,並且只應該被我的服務應用程序使用。這讓我重新考慮了我正在採取的整個方法。
雖然我瞭解使用DTO在客戶端和服務器之間傳遞狀態,但我使用.NET 3.5,據我所知,共享程序集是共享業務和驗證規則的唯一方法。客戶端應用。我有一些想法,我可以去的其他方向,但希望得到一些建議,然後開始一條新的道路。
另一方面,我目前對客戶的實施採取了我認爲是一種全面的授權方法,可能只是一個指標,表明不同的模式會更好。就像我在我的服務器端服務應用程序中有一個DocumentService用來執行授權的AuthorizationService,我有一個類似的代理,我的客戶端代碼使用它。這意味着我需要在我的客戶端代碼中使用另一個間接層來支持授權,可能是Controller或ViewModel。如果用例是有效的,那很好。
EDIT
我可能需要澄清的是,AllowPublish屬性是動態的文檔正在被編輯時。當第一次檢索時,它可能是錯誤的,但隨着業務規則的滿足會變成真。通過在客戶端應用程序中運行業務規則,我們可以提供更豐富的用戶體驗。
這可能是調查CQRS的好時機。這不是一小步,而是根據你所描述的,這可能是一個很好的選擇。這個想法是爲寫入(命令)和讀取(查詢)分別建立模型。這樣,您的文檔對象(又名DDD實體或Agregate)將成爲寫模型的一部分,在讀模型中,您將擁有一個簡單的DTO,其中包含所有已經計算好的屬性 - DocumentDTO的AllowPublish將成爲一個簡單的布爾字段每當Document實體發生更改時都會更新。如果您需要我可以提供更多信息,但我認爲谷歌應該足夠了。 – 2011-05-02 14:18:12
事實上,我的精神實施CQRS。例如,檢索文檔列表的查詢方法實際上會返回包含簡單隻讀屬性(不過是DTO)的DocumentInfo對象。這些DTO仍然由具有邏輯的實際域對象生成,以確定像AllowPublish這樣的布爾屬性將包含哪些值。雖然我喜歡CQRS背後的概念,但我並不喜歡實現,因爲我發現它超出了平均開發人員的理解範圍。所以,我嘗試用R/O DTOs來簡化讀取和寫入域對象。 – SonOfPirate 2011-05-02 15:34:13
我應該澄清:CQRS因爲它是一個交易存儲而失去了我 - 這意味着我們正在存儲交易,而不是狀態。這對許多應用程序來說都很好,但對於我的努力,我還沒有遇到過這樣的情況,因爲它非常適合。我不想通過一系列交易來檢索我的當前狀態,並且實施服務對於彙總數據的額外開銷等等太多。我喜歡分離職責的想法,實際上已經實現了一個版本,其中查詢是針對CUBE而不是實際的數據存儲執行的。這跟我來的時間差不多。 – SonOfPirate 2011-05-02 17:11:00