【问题标题】:Should Model Objects Have Interfaces?模型对象应该有接口吗?
【发布时间】:2011-01-25 16:04:53
【问题描述】:

我正在我的系统中创建域模型。在设计我的模型对象时,我应该为每个实体对象制作接口吗?人们告诉我,我们的 Web 层不应该关心实体的实现,我们应该能够交换实现,但我不确定这是否会发生。

例如,如果我们有一个教师类维护一个学生列表,那么 getStudents 方法可以是:

public List<Student> getStudents() {
      return this.students;
}

或者这个:

public List<Student> getStudents() { 
     return someExternalService.retrieveStudents();
}

我了解这种好处,但一般做法是什么?

【问题讨论】:

  • “一般实践”不一定等同于“良好实践”,尤其是在 OO 设计方面:)
  • 我不明白你的例子。您的问题是教师应该实现某个接口,还是通过接口使用依赖项?对于这两种情况,我有不同的答案。你的文字让我觉得你在想前者,但这个例子让我觉得你想要后者。这是什么?
  • Martinho,我的问题是 Teacher 是否应该实现一个接口并生成 TeacherImpl 类。
  • 但您的示例似乎是在问“教师应该保存数据还是只调用其他类?”

标签: java oop interface modeling


【解决方案1】:

除非您有充分的理由认为您需要更换模型,否则我暂时不会担心。基于 YAGNI 原则 (You ain't gonna need it)

【讨论】:

  • 感谢您的回答。我都同意。我实际上对此有后续跟进,我将作为一个单独的问题发布。它涉及建模关联。
  • 在我看来,YAGNI 更多地应用于功能,而不是设计。例如,接口不会导致代码膨胀或测试复杂化;根据我的经验,为了方便起见而缺少接口才是问题所在。
  • @Noel - 我认为您对它的起源是正确的,但我认为避免过度设计可能很有用。我发现有几次对某人说“你不需要那个”,他们可以驳斥你的说法并为添加提出一个很好的论据,或者他们发现他们无法证明它的合理性并决定/意识到它是不是真正的要求。我同意在这种情况下,添加接口并没有太大的危害,但它可能会导致“以防万一”添加更多代码。
  • 如果您打算将逻辑或行为放入域模型中,那么您可能需要一个接口。如果您不这样做,那么无论何时使用该行为,您都必须声明测试结果,而不仅仅是测试该方法是否被调用。
  • 这是一个很棒的答案...我曾经为所有东西创建接口,而不考虑现在是否需要它。就在一天,一位初级开发人员质疑我为什么要这样做,坚持认为我错了,我应该考虑一下我现在是否真的需要它。不必要的多态性降低了代码的简单性。丹尼尔是对的,他继续教给我一些宝贵的经验。
【解决方案2】:

我见过或参与的项目都没有领域实体的接口。

但在我的一个项目中,我有接口NamedEntity

public interface NamedEntity {
   int getId ();
   String getName ();
}

所有域实体都实现了这个接口。它使我有可能不为不同的实体创建不同的 jsf 转换器,而是创建一个使用此接口而不是具体域类的转换器。

【讨论】:

  • 很好的例子。 Nitpick:你说你见过或参与的项目都没有这种现象,然后你很快提供了一个例子……
  • 这个投票揭示了 SO 声誉计数中的错误(或只是不清楚的行为)。
  • 我同意。我真的不希望任何人有界面,但其他人不同意。
  • @Roman:根据点赞数,声望上限为 200/天。以后只会添加赏金和接受的答案。另请参阅常见问题解答和元数据。
  • @BalusC:看到这篇帖子meta.stackexchange.com/questions/41683/…经过一番思考,我认为这不是但是。
【解决方案3】:

我不能谈论一般实践,但这不仅仅是隐藏实现。

这是关于将接口形式化为文档和合同的基础。

在将模型抽象为接口时,您正在为服务客户端开发人员创建文档。根据您的开发风格,您可能已经或可能没有对您的服务的正式描述(例如,基于 WSDL 的描述)。接口可以满足这一需求。

【讨论】:

  • 其实这有点适用于我的情况。有服务客户端开发人员基于我的模型对象提供服务,所以也许接口方法不是一件坏事。
【解决方案4】:

我认为拥有检索对象的服务接口与模型对象本身之间存在重要区别。

在运行时,加载模型对象的服务可能会根据您请求数据的位置而有所不同。但是,无论您如何创建此对象,预期的数据对象的格式和类型都不会改变。因此,携带状态的模型对象不需要接口,但创建和加载这些模型对象的服务类需要接口。

如果模型对象不仅是简单的 bean 类型的对象,而且还公开某种行为的对象,那么模型对象具有接口的唯一原因是有意义的。

【讨论】:

    【解决方案5】:

    我的一般观点是我不会为领域模型创建一对一的接口集,因为这只会复制您的领域模型的类结构。它没有添加任何有用的东西。

    我能立即考虑考虑引入接口的两种情况是:

    1. 接口描述了领域模型中某些类集的契约/行为,在其中独立于实现它的类对行为进行建模是很有用的
    2. 您需要向外部客户端公开您的域模型并希望对他们隐藏实现细节

    换句话说,如果接口可以帮助您描述行为或帮助您向客户端隐藏实现细节,请添加接口。其他原因可能是有效的,但我想到了这两个。

    【讨论】:

    • 是的,我完全同意。这实际上从第二个开始,我们将域模型暴露给外部客户端。这种方法已经发生了变化,现在我被困在每个模型对象的接口上。我考虑过摆脱它,但想先咨询社区。​​span>
    【解决方案6】:

    提取接口是最简单的重构之一;最坏的情况是类重命名 -> 移动方法。一旦你找到了改变主意的理由,改变主意的努力是微乎其微的。我一直发现,如果一个决定很容易改变,它会更加强化 YAGNI 和 KISS。反驳的观点是,最初创建接口并不费力,这是真的,但是如果多次做出决定,维护就会随着时间的推移而增加 - 通常不会被使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      相关资源
      最近更新 更多