每一个物体都应该有一个界面,所有的物体都是松散耦合的?

从我读过的最好的做法是有基于接口的类和松散耦合的对象,以帮助代码重用和unit testing。

这是正确的,这是一个应该始终遵循的规则吗?

我问的原因是我最近在一个有100多个不同对象的系统上工作。 几个共享的通用接口,但大多数不知道是否应该有一个接口镜像这些类的每个属性和function?

我正在使用C#和dot net 2.0,但我相信这个问题将适合多种语言。

对于真正提供服务的对象是有用的 – authentication,存储等等。对于没有任何进一步依赖关系的简单types,以及从未有任何替代实现的地方,我认为可以使用具体types。

如果你过分沉迷于这种事情,你最终会花费大量的时间来嘲弄/扼杀世界上的一切 – 这往往会导致脆弱的testing。

不是真的。 服务组件(为你的应用程序做事情的类)非常适合于接口,但是作为一个规则,我不会为诸如基本实体类的接口打扰。

例如:如果您正在处理域模型,那么该模型不应该是接口。 但是,如果该域模型想要调用服务类(如数据访问,操作系统function等),那么您应该查看这些组件的接口。 这减less了类之间的耦合,意味着它是接口,或耦合的“契约”。

在这种情况下,你会发现编写unit testing要容易得多(因为你可以有数据库访问的存根/嘲笑/赝品等),并且可以使用IoC来交换组件,而无需重新编译你的应用程序。

我只能使用需要抽象级别的接口 – 也就是说,您需要使用多态行为。 常见的例子是dependency injection,或者你有一个工厂types的场景,或者你需要build立一个“多重inheritance”types的行为。

在我的情况下,与我的开发风格,这是相当经常(我喜欢聚合深度inheritance层次结构除了UI控件以外的大多数事情),但我已经看到非常好的应用程序使用很less。 这完全取决于…

哦,是的,如果你确实沉迷于接口 – 注意networking服务。 如果您需要通过Web服务公开您的对象方法,那么它们不能真正返回或接受接口types,只有具体的types(除非您要手动编写所有您自己的序列化/反序列化)。 是的,这让我感到很难过

接口的一个缺点是它们不能被版本化。 一旦您发布界面,您将不会对其进行更改。 如果您使用抽象类,那么您可以通过添加新方法并将它们标记为虚拟来轻松地扩展合同。

例如,.NET中的所有stream对象都是从抽象类System.IO.Stream派生的。 这使得微软很容易添加新function。 在frameworkj的第二版中,他们添加了ReadTimeoutWriteTimeout属性而不会破坏任何代码。 如果他们使用了一个接口(比如说IStream),那么他们将无法做到这一点。 相反,他们不得不创build一个新的接口来定义超时方法,如果我们想使用这个function,我们必须编写代码来有条件地投射到这个接口。

当你想明确定义软件两个不同部分之间的交互时,应该使用接口。 特别是当你想撕毁连接的任何一端并用其他东西replace它时。

例如,在我的CAM应用程序中,我有一个连接到点集合的CuttingPath。 有一个IPointList接口是没有意义的,因为在我的应用程序中,CuttingPaths总是由Points组成。

但是我使用IMotionController接口与机器进行通信,因为我们支持许多不同types的切割机,每个切割机都有自己的指令集和通信方法。 所以在这种情况下,把它放在界面后面是有道理的,因为一个安装可能使用另一个不同的机器。

我们的应用程序自80年代中期以来一直保持,并在90年代后期进行了面向对象的devise。 我发现可能会发生什么变化,超出了我原先的想法和界面的使用。 例如它曾经是我们的DrawingPath是由点组成的。 但是现在它由实体(样条曲线,弧,ec)组成,所以它指向一个EntityList,它是Object实现IEntity接口的集合。

但是,这种变化是通过认识到可以使用许多不同的方法绘制DrawingPath来推动的。 一旦意识到需要各种绘图方法,则需要一个接口而不是与一个实体对象的固定关系。

请注意,在我们的系统中,DrawingPaths被渲染到低级别的切割path,这些切割path始终是一系列的点线段。

我试图从最近的一个项目上直接接受“代码到界面”的build议。 最终的结果实质上是每个类的公共接口(小i)在接口(大I)实现中重复一次。 这在实践中是毫无意义的。

我觉得更好的策略是将接口实现限制为动词

 Print() Draw() Save() Serialize() Update() 

…等等。这意味着那些主要作用是存储数据的类 – 如果你的代码devise得很好,他们通常只会这样做 – 不需要或者不需要接口实现。 任何你可能想要的运行时configuration行为,例如代表相同数据的各种不同的graphics样式。

当工作要求真的不想知道工作是如何完成的时候更好。 这意味着你可以给它一个macguffin它可以简单的信任将做任何它的公共接口,并让有问题的组件简单地select何时做这项工作。

我同意kpollock。 接口被用来获得对象的共同点。 它们可以用于IOC容器和其他用途的事实是一个附加的function。

假设您有几种不同types的客户类别,但具有相同的属性。 在这种情况下,拥有一个ICustomer接口将它们绑定在一起非常棒。 通过这样做,您可以创build一个以相同的方式处理ICustomer对象的CustomerHander类/方法,而不是为每个客户变体创build一个handerl方法。

这是接口的优势。 如果你只有一个实现了接口的类,那么这个接口没有什么帮助,它只是坐在那里,什么也不做。