11

我正在阅读R. Martin 和 M. Martin的 C# 中的敏捷原则、模式和实践, 他们在他们的书中建议,将所有接口保存在一个单独的项目中,例如。接口

例如,如果我有一个包含所有自定义 Gui 类的Gui项目,我会将它们的接口保留在Interfaces项目中。具体来说,我在Gui中有一个 CustomButton 类,我会将 ICustomButton 接口保留在Interfaces中。

优点是,任何需要 ICustomButton 的类都不需要对Gui本身的引用,而只需要对重量轻得多的Interfaces项目的引用。

此外,如果Gui项目中的类发生更改并因此导致它被重建,则只有直接引用 CustomButton 的项目需要重新编译,而引用 ICustomButton 的项目可能保持不变。

我理解这个概念,但看到一个问题:

假设我有这个界面:

public interface ICustomButton
{
    void Animate(AnimatorStrategy strategy);
}

如您所见,它指的是 AnimatorStrategy,这是一个具体的类,因此将位于不同的项目中,我们称之为Animation。现在界面工程需要引用Animation。另一方面,如果Animation使用 Interfaces 中定义的接口,则需要引用它。

循环依赖——“我们来了”。

我看到,这个问题的唯一解决方案是,接口中定义的所有方法都接受本身就是接口的输入。尝试实现这一点很可能会产生多米诺骨牌效应,并且即使对于最基本的类也很快需要实现接口。

我不知道我是否愿意在开发中处理这种开销。

有什么建议么?

4

4 回答 4

17

谨防永远、永远和永远——尤其是几乎所有、没有或每一个。

您是否应该始终所有接口放在单独的程序集中?不——不一定。

您是否应该放置您希望代码的外部使用者实现的接口 - 可能。如果您希望项目中的多个程序集依赖它们,我会将接口放入外部程序集中 - 这有助于打破耦合依赖关系。我还使用这种做法来解决循环引用问题,其中程序集需要了解彼此的接口。

我不会将仅在项目内部使用的接口放在单独的程序集中。当我的项目相对较小时,我也不会将接口提升到它们自己的程序集中——或者接口不打算在没有依赖它们的程序集的情况下使用。

至于您提供的示例-我建议您考虑不要从接口中引用系统中的类。只要有可能,我就会尝试让接口只引用其他接口——这使事情相对解耦。您不能总是实现这一点 - 因此,当您拥有这些类型的接口时 - 您必须将它们与它们所依赖的程序集一起保存。

如果您决定将接口放入单独的程序集中 - 您不必将它们全部放入单个程序集中。您可能希望按预期用途将它们分开——这样消费者可以只引入与特定功能域相关的接口。

于 2009-07-16T13:59:59.630 回答
3

简单的答案是 AnimatorStrategy 也应该是一个接口。AnimatorStrategy 的实现在 Animation 项目中,但接口将在 AnimationInterfaces 或 Interfaces(根据需要)项目中。

我不一定有一个接口项目,但每个功能组都有一个。Animation 的客户端将引用 AnimationInterfaces,而 Gui 的客户端将引用 GuiInterfaces。

通过这种方式,您可以保留您的合同,而无需混合任何实施。

对于它的价值,我更喜欢使用命名约定。将接口放在 Animation 中,并将实现放在 AnimationImpl (或类似)中。这样您就可以引用功能名称。

于 2009-07-16T13:40:17.907 回答
1

我认为即使您将所有内容都声明为接口,循环依赖也可能是不可避免的,因为程序集 Foo 中可能有一个方法接受参数 IBar,而汇编 Bar 中可能有一个方法接受参数 IFoo。

我想说这没有通用的方法,但是您应该根据需要使用“常识”来划分程序集中的接口。

于 2009-07-16T14:07:40.337 回答
-2

用采用泛型类型的方法定义接口怎么样?例如

public interface IThing
{
    int DoMyThing<T>(T variable);
}

如果你需要一些限制T variable,你可以这样做:

int DoMyThing<T>(T variable) where T : IOtherInterface;

IOtherInterface在您的 Interfaces 项目中也定义了Where 。然后,只要您的特定类继承自两者IThingIOtherInterface,您就可以使用该DoMyThing方法并传入特定类的实例,而无需循环依赖。您的代码可能变为:

public interface ICustomButton
{
    void Animate<T>(T strategy) where T : IAnimateable;
}

该接口没有对具体类的引用AnimatorStrategy

于 2009-07-16T13:48:37.897 回答