【问题标题】:Should be localization part of domain in DDD应该是 DDD 中域的本地化部分
【发布时间】:2013-04-04 23:21:43
【问题描述】:

在遵循 DDD 概念时,我正在努力决定是否应该了解我的域本地化?我提供了两种解决方案来解决这个问题。两者都使域本地化在不同的地方有意识。我什至应该将本地化文本放置到域中吗?分享您对此问题的解决方案或我的两个示例的优缺点。谢谢。

示例 1

class Persion {

  String name;

  // other fields ommited

  void rename(String newName) {
    String oldName = this.name;
    this.name = newName

    // publish event with old name and new name
  }

  String name() {
    return name;
  }
}

class PersionRepository {

  void store(Persion persion) {
    Locale loc = LocaleContextHolder.get().getLocale();

    // store object to DAO - create/update fields for context locale
  }

  // other methods ommited
}

示例 2

class Persion {

  Map<Locale, String> name;

  // other fields ommited

  void rename(String newName) {
    Locale locale = LocaleContextHolder.get().getLocale();
    String oldName = this.name.put(locale, newName);

    // publish event with old name and new name
  }

  String name() {
    Locale locale = LocaleContextHolder.get().getLocale();
    return this.name.get(locale);
  }
}

class PersionRepository {

  void store(Persion persion) {
    // store object to DAO - create/update fields for all locales
  }

  // other methods ommited
}

【问题讨论】:

  • 重言式,这取决于您是否决定您的对象的域包括本地化。不过,我可能会选择将这种担忧与其他“业务”逻辑分开。
  • 什么时候需要本地化文本?如果只是在 UI 层,那就在那里做本地化。
  • 你们都对 99% 我需要本地化文本,仅用于域逻辑之外的 UI。所以你的意思是从域对象中完全删除本地化文本?
  • 是的。如果本地化本身不是领域的一部分,它似乎是表示层的问题,所以在那里处理它。
  • 感谢您的回复。这里的每个人都建议这样做,但你是第一个。您能否将您的 cmets 总结为答案(也许有一些小例子),以便我给您一个信用。

标签: java design-patterns localization domain-driven-design


【解决方案1】:

在大多数情况下,最好的选择是从域中删除本地化。

域类应该只包含与其不变量相关的数据,因为它们负责业务规则。要检索本地化描述,请使用投影 DTO 和应用服务。

你可以使用这样的东西:

public final class VatCode {
    private final String _code;
    public VatCode(String code)
    {
        // VAT code validation here...
        _code = code;
    }

    @Override
    public String toString() {
        return _code;
    }

    @Override
    public boolean equals(Object obj) {
        // ...
    }

    @Override
    public int hashCode() {
        // ...
    }
}

public class Person {
    private final VatCode _identifier;

    public Person(VatCode identifier)
    {
        _identifier = identifier;
    }

    // some command and some query here...
}

public class PersonDTO {
    private final String _vatCode;
    private final String _personalDescription;

    public PersonDTO(String _vatCode, String _personalDescription) {
        this._vatCode = _vatCode;
        this._personalDescription = _personalDescription;
    }
    // other fields here...

    public String getVatCode()
    {
        return _vatCode;
    }

    public String getPersonalDescription()
    {
        return _personalDescription;
    }

    // some more getter here
}

public interface LocalizedPersonalInformationService {
    PersonDTO getInformationOf(VatCode person, Locale localization) throws ProperExceptionList;
}

即:

  • 类似于VatCode 值对象(覆盖equals、hashCode 和toString)来标识Person 实体
  • 一个Person 实体,持有确保业务不变量所需的最少数据量并公开一组command and queries
  • 带有有用描述的PersonDTO(有人称之为read-model
  • 能够提供PersonDTOs 的LocalizedPersonalInformationService
  • 和(显然)所有needed exceptions... :-)

【讨论】:

    【解决方案2】:

    如果可能的话,将所有本地化都放在 UI 层中。有时人们觉得这很难做到。例如,我在一个项目中工作,其中业务逻辑会引发异常,并且该异常会显示在 UI 中。要本地化异常,我们必须执行以下操作(为简洁起见省略了详细信息,我们还必须有一个 LocalizedRuntimeException 和一个 LocalizedException):

    //====ArbitraryBusinessLogic.java====
    
    if(badThing) {
      throw new SubclassOfLocalizedException(LocalizedStrings.ERROR_FOO,param1,param2);
    }
    
    //====LocalizedException.java====
    
    public class LocalizedException extends Exception {
    
      private LocalizationKey localizationKey;
      Object [] params;
    
      public LocalizedException(LocalizationKey localizationKey, Object ... params) {
        super();
        localizationKey = localizationKey
        params = params;
      }
    
      public String getLocalizedMessage(Locale locale) {
        //message would be something like "The %s foo'd the %s"
        //or of course "le %s foo'd le %s" (FYI: I don't speak French)
        String message = getLocalizedMessageForKey(localizationKey);
        return String.format(locale,message,params);
      }
    
      public String getLocalizedMessage() {
        return getLocalizedMessage(getDefaultLocale());
      }
    
      public String getMessage() {
        return getLocalizedMessage();
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      相关资源
      最近更新 更多