8

我正在尝试构建一个框架,允许人们通过实现接口来扩展我们的核心功能。下面是这个接口的一个简化示例。

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

最近,我们决定修改这个接口(我知道我不应该破坏依赖代码,但事实是我们还没有任何第三方实现这个接口,所以我们有机会“重做”正确实现此接口)。

我们需要在这个界面中再添加 2 个参数,我们的软件才能正常工作。我们正在考虑的两种方法是将它们添加到签名中,如下所示:

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, bool p4, DateTime p5);
}

或通过创建这样的参数对象

public class MyParameters
{
    public bool p4 { get; set; }
    public DateTime p5 { get; set; }
}

并将它们添加到方法的末尾,如下所示:

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, MyParameters p4);
}

我正在寻找某种指导,说明哪种方式是“最”正确的继续方式。我可以看到这两个类别的优缺点,但我不希望我的偏见导致我走错路。

我的一些主要担忧是:

  • 软件的可扩展性——我希望用户能够通过实现接口来做我还没有想到的事情
  • 可维护性 - 理想情况下,我不想再接触负责再次调用 GetData() 的代码
  • 清洁 API - 我不希望我得到的解决方案让第 3 方开发人员畏缩

我什至不知道在网上问什么问题来获得这个问题的指导。我有一种感觉,答案是“取决于”(取决于 p1-p5 与 GetData() 函数的目的之间的相关性),但有人可以指出我应该问的问题列表以帮助我评估一种解决方案是否比另一种更好?

相关: 帖子 1 帖子 2

4

2 回答 2

2

为什么不一路走:

public Interface IParameters
{
    string p1 {get; set;}
    char p2 {get; set;}
    double p3 {get; set;}
    bool p4 { get; set; }
    DateTime p5 { get; set; }
}

public interface MyInterface
{
    IData GetData(IParameters p);
}
于 2012-12-19T05:35:17.557 回答
2

让我试着回答这个问题。让我们评估您的选择:

1)如果如下界面

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

被打破:

a) 并且根本不应该使用,那么你应该强制实现者重写它。所以改变方法定义。

public interface MyInterface
{
    IData GetData(something else);
}

b) 但是你只需要鼓励用户使用新的定义,然后你可以创建一个新的重载告诉他们第一个已经过时了。

public interface MyInterface
{
    //xml to tell them this is deprecated.
    IData GetData(string p1, char p2, double p3);
    IData GetData(string p1, char p2, double p3, and whatever);
}

关于你的新定义,没有任何人可以在不了解模型的情况下给出一站式解决方案,但你问自己,

I)“如果组合起来,参数本身可以代表一个实体吗?在现实世界中拥有一个参数单元是否意味着什么? ”如果是这样,那就这样吧。如果没有,不要。我认为当你处于这种两难境地时,你应该依靠这种抽象层次的思考。我不确定泡吧bool p4DateTime p5. 你应该将那些本身代表现实生活中的东西的参数组合在一起。如果这些组合都没有意义,那么就这样吧。将这种俱乐部留给这种合乎逻辑的思维方式,您将获得更大的成功。请注意,您将自己的定义留给其他程序员,为了简化他们的工作,您的方法签名应该非常合乎逻辑。

II)类可以做更多的事情而不是仅仅持有一组数据吗?类应该是这里的选项。

III)我只需要控制类定义而不是它的实现吗?在这种情况下,只需定义输入的公共接口,并将实现留给客户。

IV)未来对我的接口的修改是否应该不会破坏现有的实现?重载是你的出路。

假设您有两个选择,将签名展平,或加入俱乐部。

1) 没有泡吧:

a) 更少的代码,减少另一层。

b) 无需公开另一个类。

2) 泡吧:

a) 更好地理解模型以进入函数 - 你的意图很明确。

b) 如果您需要添加可选的细节来构建新形成的类,将来易于扩展。假设你有一堂课

class Input {
    string p1; char p2; double p3;

    public Input(string p1, char p2, double p3){
    }
}

和界面

public interface MyInterface
{
    IData GetData(Input p1);
}

现在您可能想要添加可选的详细信息,例如 bool 和 DateTime。由于它们是可选的,因此您不必在构造函数中强制它。您仍然可以拥有相同的构造函数,并授予用户在构造函数之外根据需要进行修改的权限。

class Input {
    string p1; char p2; double p3; bool p4; DateTime p5;

    public Input(string p1, char p2, double p3){
    }
}

界面仍然可以相同。正如我所说的那样,产生这种东西的动力很可悲地取决于你的模型。简而言之,如果一个分组可能意味着什么,就让它成为一个类或接口(取决于谁将控制逻辑)。

于 2012-12-19T12:29:24.340 回答