5

我正在寻找一种干净的方法来对我的代码库进行增量更新,而不会破坏向后兼容性。这可能意味着向类添加新成员,或更改现有成员以提供附加功能。有时我需要以一种会破坏现有代码的方式更改成员(例如,重命名方法或更改其返回类型),因此我宁愿在交付后不触及任何现有类型。

我目前设置的方式是通过继承和多态性,通过创建一个新类来扩展该类的先前“版本”。

类图

其工作方式是根据属性的实际值创建StatusResult(eg ) 的适当版本,并将其作为 的实例返回。StatusResultVersion3ProtocolVersionCommandResult

因为 .NET 似乎没有类版本控制的概念,所以我不得不自己想出:将版本号附加到类名的末尾。这无疑会让你畏缩。我可以很容易地想象自己在放大图表后会抓挠眼睛。但它有效。我可以添加新成员并覆盖现有成员,而无需引入任何代码破坏更改。

有没有更好的方法来版本我的课程?

4

4 回答 4

1

接口的问题在于,一旦发布,它们就基本上是一成不变的。引用 Anders Hejlsburg 的话:

...这就像向接口添加方法一样。发布接口后,它实际上是不可变的,因为它的任何实现都可能具有您想要在下一个版本中添加的方法。所以你必须创建一个新界面。

所以你永远不能只更新一个界面,你需要创建一个全新的界面。当然,您可以让一个类实现两个接口,因此与(例如)多态类相比,您的可维护性工作相当低,您的代码将随着时间的推移在多个类之间展开。

多个接口还允许您以类没有的方式删除方法(当然,您可以弃用它们,但这可能会在几次迭代后导致非常嘈杂的智能感知)

我个人倾向于在每个程序集版本中拥有完全独立的界面版本。

也就是说...

v 0.1.0.0

interface IExample
{
    String DoSomething();
}

v 0.2.0.0

interface IExample
{
    void DoSomethingElse();
}

您如何在幕后实现它们取决于您,但很可能是相同的类,但执行相似工作的方法略有不同(否则,为什么要使用相同的接口?)

所有旧代码都应该引用0.1.x.x,新代码将引用0.2.x.x。唯一的问题是当您发现(例如)安全漏洞并且需要将修复程序反向移植到早期版本时。这就是一个不错的 VCS 的用武之地(个人偏好是 TFS,但 SVN 或其他任何支持分支/合并的东西都可以)。

将分支中的修复合并0.20.1分支,然后重新编译以产生 (say) 0.1.1.0

只要你坚持这样的过程:

这给了你:

  • 干净的代码库,没有遗留的混乱
  • 如果没有任何问题,允许客户使用最新版本而无需更改代码
  • 防止客户端使用更新版本的程序集,这些版本确实有重大更改,直到他们重新编译(并且希望适当地更新他们的代码以利用新功能。)
  • 允许您发布以前版本的安全补丁
于 2013-07-21T09:14:59.387 回答
1

考虑现有代码和程序集更新时,通常有两种方法:

  1. 回归测试

    这是非破坏性更改的好方法,您可以简单地重载函数以提供新参数等。Visual Studio 具有一些非常先进的单元测试功能,可以使您的回归测试相对容易和自动化。

  2. 装配版本

    如果您的更改将开始破坏某些东西,例如重写某些实用程序的工作方式,那么是时候使用新的程序集版本了。.NET 非常适合使用程序集版本。您可以将版本化程序集部署到不同的文件夹,以便现有代码可以继续引用旧版本,而新代码可以利用新版本中的功能。

于 2013-05-25T17:02:03.467 回答
0

如果这主要是为了序列化,这可以在 .Net 中使用 DataContractSerializers 和 DataAnnotations 来实现。它们可以将一个对象的不同版本反序列化为同一个对象,以允许对同一类的不同版本进行反序列化,而将无法映射的任何属性留空。

于 2013-05-25T17:42:58.567 回答
0

OP 解决了他的问题,如下评论所示:

最后,我采用了接口的想法,因为它允许我将一个类成员的多个版本保存在一个类文件中。当我需要更新类时,我只需添加新接口,隐藏已更改的成员,并更改我的一些方法的返回类型。由于多态性,这不会破坏向后兼容性。

于 2013-05-25T17:06:29.927 回答