从域对象(实体)本地化验证消息

时间:2012-04-10 23:18:54

标签: localization dependency-injection domain-driven-design globalization

我不打算在代码所属的DDD中进行有关验证的辩论等,而是专注于一种可能的方法以及如何解决本地化问题。我在我的一个域对象(实体)上有以下行为(方法),它举例说明了该场景:

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

    ClockedInAt = DateTime.Now;
    :
}

如您所见,当调用ClockIn方法时,该方法会检查对象的状态以确保Employee尚未终止。如果Employee被终止,我们会抛出一个与“不要让您的实体进入无效状态”方法一致的异常。

我的问题是我需要本地化异常消息。这通常是(在此应用程序中)使用在需要访问其方法的类中使用MEF导入的应用程序服务(ILocalizationService)完成的。但是,与任何DI框架一样,只有在容器实例化对象时才会注入/导入依赖项。 DDD通常不是这种情况。

此外,我所学到的关于DDD的一切都说我们的域对象不应该有依赖关系,那些问题应该从域对象外部处理。如果是这种情况,我该如何进行本地化消息,例如上面显示的消息?

这不是一项新颖的要求,因为许多商业应用需要全球化/本地化。我很欣赏一些建议如何使这项工作仍然符合DDD的目标。

更新

我最初没有指出我们的本地化都是数据库驱动的,所以我们确实有一个本地化服务(通过可注入的ILocalizationService接口)。因此,使用Visual Studio提供的静态Resources类作为项目的一部分并不是一个可行的选择。

另一个更新

也许它会推动讨论,以表明该应用程序是一个RESTful服务应用程序。因此,客户端可以是一个简单的Web浏览器。因此,我不能编码任何期望调用者可以执行任何类型的本地化,代码映射等。当发生异常时(在这种方法中,尝试将域对象置于无效状态是一个例外),抛出异常并返回相应的HTTP状态代码以及异常消息,该异常消息应本地化到调用者的文化(Accept-Language)。

4 个答案:

答案 0 :(得分:2)

不确定此响应对您有多大帮助,但本地化确实是一个前端问题。根据您的示例本地化异常消息并不常见,因为最终用户不应该看到技术细节,例如异常消息中描述的那些(并且即使不是他们的母语,任何将对您的异常进行故障排除的人也可能具有足够的英语水平)。

当然,如果有必要,您可以随时处理异常并向前端用户提供本地化,用户友好的消息。但是将其作为字体端关注点应该简化您的架构。

答案 1 :(得分:1)

正如Clafou所说,你不应该以任何方式使用异常将消息传递给UI。

如果你仍然坚持这样做,一个选择是抛出错误代码而不是消息

throw new InvalidOperationException("ERROR_TERMINATED_EMPLOYEE_CLOCKIN");

然后,当它发生时,做你需要做的任何事情(日志,查找本地化,等等)。

答案 2 :(得分:0)

如果本地化是域/应用程序的重要组成部分,您应该将其作为一等公民并注入其所属的任何位置。我不确定你的意思是“DDD说我们的域对象不应该有依赖” - 请解释一下。

答案 3 :(得分: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);
   }
}

然后,您可以在进行clockin调用的位置使用DI框架注入服务,并使用该服务将域对象与业务逻辑的更改隔离开来。