将不同聚合中的实体从公共类继承是否可以?

时间:2012-11-21 14:03:11

标签: domain-driven-design

我在属于不同聚合的几个实体中有一些共同的行为,我想在抽象类中考虑因素。

让不同聚合中的实体从公共抽象类继承是否有任何缺点?


用例

有几个实体具有可以用不同语言翻译的名称,描述或其他属性。

例如,我会使用setName(language, name)设置名称,并使用getName(language)检索。

每种语言的每个文本都存储在一个对象中,例如:

class EntityName
{
    protected Entity entity;
    protected Language language;
    protected String text;
    protected int version;

    public EntityName(Entity entity, Language language)
    {
        this.entity = entity;
        this.language = language;
        this.version = 1;
    }

    // setText(), getText(), ...
}

对于给定的Entity班级,EntityNameEntity聚合内。只有Entity可以通过EntityNamesetName()创建,读取和写入getName()

但是,EntityNameEntityDescriptionOtherEntityName等类都会共享相同的代码。唯一不是更改的部分是对聚合的引用,因此也就是构造函数。

3 个答案:

答案 0 :(得分:4)

关于这个话题并不多。但是,请看一篇名为How To: Domain Driven Design

的文章

请特别阅读标题为第2步 - 识别聚合和聚合根的部分:

  

在高级情况下,类中存在多态性   模型也会影响聚合边界。这发生在时   多个聚合根类都共享相同的基类

如果您正在存储域模型之外的簿记数据(id,版本,创建时间戳,更新时间戳)(例如,为了支持您的持久层),我不认为这是一个问题。但是,如果您尝试重用真正的业务方法和属性,则可以考虑使用组合或AOP引入替换继承。

<强>更新

在查看更新的用例之后,看起来好像是在尝试实现代码重用而不是真正的Liskov is-a关系。有些语言更好地支持这种类型的重用,例如mixins(Groovy)或traits(Scala)。假设Java,您可以做的一种方法是创建一个类并使用Project Lombok的@Delegate注释转发到您的实现。这有以下好处:

  • 提供相同级别的聚合包装
  • 为您生成字节码,而不需要在源文件中复制
  • 允许您为真正的is-a保存一个继承选项 未来的关系
  • 确保整个域的一致性

我相信这更纯粹,并使您的模型具有灵活性。我在一些项目上使用了Project Lombok并取得了巨大的成功。它允许您支持Java中一些缺少的语言功能,并且更多地关注您的域,而不是实现某些习语所需的必要样板代码。

答案 1 :(得分:1)

我认为只要通用定义不影响聚合根设计就行。也就是说,您开始对聚合根进行建模,并注意它们有很多共同点,因此您可以提取公共基类。

但是,我会对此三思而后行,因为从不同的有界背景聚集根源的几率是多少?这是IMO的代码味道。

答案 2 :(得分:0)

正确的继承由is-a关系定义。 imho很少有适用于聚合根的情况。

仅仅因为根看起来相似并不意味着它们来自同一个地方。

如果您可以创建一个名称在域中有意义的基类,请继续。如果没有,请不要。