添加实际不使用的接口

时间:2010-05-20 13:22:07

标签: c# java oop

我目前有两个界面(我在这里命名为IAIB):

interface IA {
    int Width;
    int Height;
    ...
}

interface IB {
    int Width;
    int Height;
    ...
}

共享相同的两个属性:它们都具有WidthHeight属性。

我在考虑定义包含IMatrixWidth属性的Height界面是否有任何意义:

interface IMatrix {
    int Width;
    int Height;
}

问题是虽然它们共享两个相同的属性,但我不会在我的任何编码中使用IMatrix的多态性:即,在任何情况下我都不会想要使用IMatrix,我只想使用IAIB。添加IMatrix似乎更像是过度工程而不是其他东西,但我想问你们你们对此事的看法。

由于

8 个答案:

答案 0 :(得分:7)

如果您不会专门使用它,那么我会说您无需添加它。

答案 1 :(得分:6)

如果存在您正在使用或可能合理地希望将来使用的真实关系,那么抽象关系是有意义的。如果关系非常松散(它们恰好有两个属性意味着类似的东西,但在完全不同的上下文中),那么就没有理由提供抽象。

答案 2 :(得分:4)

我认为YAGNI原则适用。如果您不打算在代码中使用IMatrix,那么您不需要它。您可以随时添加它,然后让IAIB实施。你的其他代码(实现这两个接口的具体类)都不应该改变。

答案 3 :(得分:3)

如果您发现自己处于为IAIB编写两个具有相同实现的方法的情况,那么通用接口是个好主意。否则,不需要通用接口。

如果您现在不处于这种情况,您必须评估将来发生的可能性,以及现在是否值得引入通用界面。

答案 4 :(得分:0)

这取决于意图,IMatrix如何发展以及代码的重点是什么。

例如,如果代码真的只关心维度,那么它可以使用IA / IB。但是如果调用代码专注于矩阵运算,那么创建这个子接口并使用它可能是有意义的。如果您以后添加特定于矩阵的属性或操作,例如GetCellValue或类似的,专门处理矩阵的代码所需,然后从一开始就使用IMatrix将使这更容易添加。如果你在真正关于矩阵的代码中使用IA / IB,那么你将不得不重构该代码以将IA / IB更改为IMatrix(可能涉及许多方法签名更改),或者在代码中从IA / IB进行向下转换需要IMatrix。

答案 5 :(得分:0)

公共接口可能有很多原因,IA和IB在其他区域可能有不同的属性和方法,但是如果它们都在某种程度上定义了Matrix,那么通用接口就会很棒。

作为一名伟大的程序员曾经说过:

  

如果可能的话简化一切   接口

我整理了一个解决方案,提供了一个最终可能会是什么样子的例子

class Program
{
    static void Main(string[] args)
    {
        // D derives from C which implements interface IA and IB which 
        // are both derived from IMatrix
        var matrix = new D {Height = 100, Width = 200};

        // Method takes IMatrix
        X(matrix);

        // Method takes IA
        Y(matrix);

        // Method takes IB
        Z(matrix);

        // Method takes D
        LastTest(matrix);

        //
        //  Prints heights and widths 4 times
        //
    }

    static void X(IMatrix x)
    {
        Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n", 
        x.Height, x.Width));
    }

    static void Y(IA x)
    {
        Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n", 
        x.Height, x.Width));
    }

    static void Z(IB x)
    {
        Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n", 
        x.Height, x.Width));
    }

    static void LastTest(D x)
    {
        Console.WriteLine(string.Format("Height: {0}\r\nWidth: {1}\r\n\r\n", 
        x.Height, x.Width));
    }
}

internal interface IMatrix
{
    int Width { get; set; }
    int Height { get; set; }   
}

internal interface IA : IMatrix
{}

internal interface IB : IMatrix
{}

internal class C : IA
{
    public int Width { get; set; }

    public int Height { get; set; }
}

internal class D : IA, IB
{
    public int Width { get; set; }

    public int Height { get; set; }
}

在某些情况下,您可能只需要宽度和高度,在其他情况下,您可能需要完整的IA或IB甚至实现(但应该简化为接口)。

但是,不要过度设计您的软件,考虑域并尝试提取常用部分。

有人可能会问为什么你会有你不使用的东西,IMatrix可能是一个“坏名字”但是你有另一个问题。 未使用代码=死代码,因此应予删除。

答案 6 :(得分:0)

另一个原则是不要重复自己(DRY),接口将在IA中“使用”,IB会扩展它,即使没有方法实际上采用IMatrix(或您决定的任何名称) )。

然而,在这种情况下重复很小,所以除非出现更多的共性(在接口方法或可以在IMatrix上运行的实用程序功能),否则它可能不会“概念性地承载它自身的重量”。

答案 7 :(得分:0)

在您的情况下,请不要设置IMatrix界面。如果没有合同关系来证明它是合理的,那么接口没有任何意义。这就像先建一座桥,然后决定把它放在哪条河上。