先有接口还是类? - The Interface or the Class

11

在设计软件新功能的过程中,哪个流程是最佳实践?

  1. 设计类将要实现的接口。
  2. 先编写类,然后稍后提取接口。

如果选择第二种方式,何时决定需要接口?

16个回答

19

当你需要从几个类中重构共同特征时,界面会出现。

在你有多个具有共同特征的类之前,很难预见应该是什么样的接口。

一旦你有了几个类,就更容易理解接口应该是什么样的,然后回过头来重构那些类以正确实现新发现的接口。

有些人在纸上设计很多类来找出接口应该是什么。这样可以避免重构真正的代码。相反,你必须重构你的设计。


是的。我从现有类中提取“接口”(在Java意义上)的成功率比起前期设计要高得多。但另一方面,我总是从内部向外设计单个类——在实现之前我知道API。 - emk
由于我使用Python,因此没有正式的Java风格接口。但是,通常需要突出一些类的某些特性,将它们标识为可见和重要,就像Java接口一样。 - S.Lott

6
提示问题!测试先行。然后是测试的实现,这是一个可能已经实现或未实现接口的类。使测试通过的一部分可能涉及从现有类中提取接口,但不要在有需要接口之前就猜测接口的需求。
试图提前弄清楚这个问题会让你发疯-或者至少,在我进行TDD之前,我总是这样做。确定应用程序需要的功能,编写测试,并让测试指导你对代码的操作。

3
我同意Brian Guthrie的观点。测试优先,因为它将推动你的设计。虽然这通常意味着最终会得到一个具体类(通过指定其行为集作为一组测试来设计),但依赖关系通常会通过接口来表示(以允许模拟和遵循依赖倒置原则)。
这通常意味着在有类之前就有了接口,但只是因为你更早地需要它们。

2

我通常选择第二种方式。先编写一个类,然后再提取接口。通常提取接口的原因是需要该接口的第二个实现(通常作为单元测试的模拟对象)。


2
无论如何,您的设计阶段应该始终在实施阶段之前进行。在开始编码之前,您应该对类之间的交互有一个清晰的了解,并且希望您的接口决策从中明显。
但是,如果您已经编写了一个类,并且现在需要重构它以具有界面,则请记住,接口仅是选择一组具有共同目的并将被多个类使用的函数/方法。如果您发现其他类需要一些有用的功能,则这些方法将成为界面的良好候选者。
使接口非常有用的另一个部分是,如果您发现类的某些部分不是私有的,但您想要隐藏它们以便于某些其他对象,则可以使用需要公开的函数,并将它们制作为接口。
我强烈反对任何人说你不应该事先设计。所有程序员都喜欢直接跳入其中,有时需要重构,但是强大的设计阶段将在以后节省大量的重构时间。

2

需要先有需求还是先有功能实现呢?

在我的工作流程中,界面通常是首要考虑的。如果项目的某个部分需要新功能,则会以我想如何使用它——也就是说,以其接口为基础来构建它。然后再进行功能实现。

这样,实现过程只包含实际需要的内容,不会浪费时间在过度设计华丽无用的代码上。


1
我认为接口应该首先考虑,但它们会在你开发特定类/方法时出现。当你遇到一个依赖于其他类/方法的点时,使用接口来添加依赖关系并继续编写代码。然后,在完成当前组件的编写后,返回并创建实现所需接口的组件。

1

这完全取决于情况...

当你在设计阶段就知道会有多个类具有相同的“共性”,但它们的实现不同,那么接口就应该首先考虑。

然而,软件是有机的;它不断发展,因此我可以想象,在某些情况下,你可能会有一个类,经过一段时间后,需要从该类中提取一个接口。


1

对于大多数类来说,接口是真正重要的东西,因为实现可以随时更改,但一旦在接口中提供了某些内容,就很难或不可能撤回。对于项目的其余部分,接口是最重要的,而实现则是其他人的问题。

理想情况下,在任何实现工作之前应该先指定接口的主要特性。(设计测试也是个好主意。)细节可以允许发展,但对接口的任何更改都应基于其他类和例程的需求,而不是实现的产物。实现应始终由接口确定,而不是相反。

(由于这是一个与语言无关的问题,我假设所讨论的“接口”是类的公共功能,而不是例如Java替换C++抽象类的功能。在C++中,这将是类定义中标记为“public”的部分。)


感谢您的括号回复。我正在使用C#编写,所以是的,这是类的公共功能。我标记它为语言无关,因为我正在使用C#,VB(.NET或其他),Java或伪代码并不重要。我想要看到何时以及为什么这样做。 - David Williams

1

我想提出两种不同的观点来解释接口:

  1. 接口是系统中一个重要实体的抽象。您可以基于接口和它们之间的协作来设计系统。
  2. 接口是系统中允许实现变化的地方。平台差异、第三方库等都被接口隐藏,可以为软件的不同配置实现不同的接口。

但在这两种情况下,您都需要先进行设计,然后再编码。

对于新系统,我希望首先确定候选接口,然后再由类来实现。对于现有系统,当您发现系统中的重要实体或变化点之前并不重要或不需要提供变化点时,就需要从现有类中开发接口。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接