3

這不是我的意圖,就是在代碼所屬的DDD中進行關於驗證的辯論,而是專注於一種可能的方法以及如何解決本地化問題。我有我的域對象(實體)的其中之一體現在以下情形下,行爲(方法):本地化來自域對象(實體)的驗證消息

public void ClockIn() 
{ 
    if (WasTerminated) 
    { 
     throw new InvalidOperationException("Cannot clock-in a terminated employee."); 
    } 

    ClockedInAt = DateTime.Now; 
    : 
} 

正如你可以看到,當ClockIn方法被調用,該方法檢查對象的狀態確保員工沒有被終止。如果員工被終止,我們會拋出與「不要讓您的實體進入無效狀態」方法一致的異常。

我的問題是我需要本地化異常消息。這通常是使用應用服務(ILocalizationService)完成的(在此應用程序中),該服務是使用MEF在需要訪問其方法的類中導入的。但是,與任何DI框架一樣,只有在容器實例化對象時纔會注入/導入依賴項。 DDD通常不是這種情況。

此外,我所瞭解的有關DDD的一切都表明,我們的域對象不應該有依賴關係,這些關注點應該從域對象的外部處理。如果是這樣的話,我如何才能對本地化的消息進行本地化?

由於許多商業應用程序都需要全球化/本地化,因此這不是一項新穎的要求。我會很感激一些建議如何使這項工作,並仍然符合DDD的目標。

UPDATE

我沒有原先指出,我們的定位是推動所有的數據庫,所以我們有一個本地化服務(通過注射ILocalizationService接口)。因此,使用Visual Studio提供的靜態資源類作爲項目的一部分不是一個可行的選項。

另一個更新

也許會一起移動的討論指出應用程序是一個RESTful服務的應用程序。因此,客戶可能是一個簡單的網絡瀏覽器。因此,我無法編寫任何期望調用者可以執行任何類型的本地化,代碼映射等的代碼。當發生異常時(並且在這種方法中,試圖將域對象置於無效狀態是一個例外),異常被拋出,並且適當的HTTP狀態代碼與異常消息一起被返回,異常消息應該被本地化爲調用者的文化(Accept-Language)。

+0

相關:http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-objec。 – Steven 2012-04-11 06:46:19

+0

相關,是的,但遠不及答案。感謝您的鏈接! – SonOfPirate 2012-04-11 12:11:13

+0

您由Framework \ Platform爲.NET應用程序提供的用戶機制拋出新的異常(資源[「TerminatedEmployeeMessage」])。 http://stackoverflow.com/questions/1138934/c-sharp-class-library-localization – 2012-04-13 05:20:30

回答

2

不知道這個迴應對你有多大幫助,但本地化確實是一個前端問題。根據您的示例對異常消息進行本地化並不常見,因爲最終用戶不應該看到例外消息中描述的技術細節(並且任何對異常進行故障排除的人都可能擁有足夠的英語水平,即使它不是他們的母語)。

當然,如果有必要,您可以隨時處理異常情況,並在您的前端向用戶展示本地化的,用戶友好的消息。但將它作爲字體結尾的問題應該可以簡化您的體系結構。

+0

需求是在出現異常時向用戶界面提供描述性消息。這必須與UI中顯示的其他文本一起進行本地化。由於兩個原因,它不能簡單地成爲UI關注的問題:1.數據存儲在數據庫中,因此必須有後端提供商的信息;和2.它需要一個唯一的異常類型來處理每個可能的異常,以便客戶端可以捕獲它並查找本地化的文本。相反,由於服務器具有本地化文本,因此在服務器上執行本地化更爲清晰。 – SonOfPirate 2012-04-13 17:47:34

+0

作爲示例,第二個業務規則將不會鎖定已經鎖定的員工。這也會導致拋出InvalidOperationException,但會顯示與上面所示不同的錯誤消息。所以我要麼將其本地化,要麼控制我想要的消息,要麼創建兩個異常類來表示每種情況。而且,當應用於現實世界的企業級應用程序時,這種應用程序變得非常龐大,我正在開發數百個業務規則來強制執行。 – SonOfPirate 2012-04-13 17:49:39

+1

這聽起來像你可能過分依賴於例外。例外情況下,驗證邏輯不必執行。您可以返回已知的錯誤代碼,並將它們映射到資源標識符,以便您可以在UI中顯示本地化的消息。 – Clafou 2012-04-13 19:17:23

0

如果本地化是域/應用程序的重要組成部分,您應該讓它成爲頭等公民並注入它所屬的任何地方。我不確定你的意思是「DDD說我們的域對象不應該有依賴關係」 - 請解釋一下。

+0

在「域對象依賴關係」,「DDD實體依賴關係」或其他任何變體上進行網絡搜索,您會發現大量關於此主題的文章,帖子和討論。而根據埃文斯的說法,這根本不是好的做法。 – SonOfPirate 2012-04-13 12:20:05

1

正如Clafou所說,您不應該以任何方式將消息傳遞到UI。

如果你還是堅持在做這個,一個選擇是拋出一個錯誤代碼,而不是郵件的

throw new InvalidOperationException("ERROR_TERMINATED_EMPLOYEE_CLOCKIN");

,然後,當它發生時,做任何你需要的例外,做(日誌,查找本地化,不管)。

+0

正如我對@Clafou所說的那樣,例外是針對特殊情況的,這就是我所描述的。我曾考慮過將資源鍵設置爲例外信息,但這似乎有點像將方塊塞入圓孔中。如果可能,我想找一個方形洞。 – SonOfPirate 2012-04-14 02:48:26

0

爲避免向域模型對象添加內部依賴關係,您是正確的。

一個更好的解決辦法是處理服務的方法,如內的行動:

public class EmployeeServiceImpl implements EmployeeService { 

    public void ClockEmployeeIn(Employee employee) throws InvalidOperationException { 
     if (employee.isTerminated()) { 
      // Localize using a resource lookup code.. 
      throw new InvalidOperationException("Error_Clockin_Employee_Terminated");  
     }  
     employee.setClockedInAt(DateTime.Now); 
    } 
} 

然後,您可以使用您的DI框架的地步,你將作出的clockin呼叫注入服務使用該服務將域對象與業務邏輯的更改隔離開來。