2009-07-06 29 views
5

我将一个开源Java库转换为C#,C#中有许多标记为弃用的方法和类。这个项目是一个以干净的石板开始的机会,所以我打算完全删除它们。但是,从事较大型项目的新人,我担心情况会再次出现。由于大部分敏捷开发都是围绕现在的工作进行的,如果需要进行重构,似乎API的弃用必定是一个常见问题。即使我不完全确定项目的未来方向,我是否可以采取预防性措施来避免/尽量减少API弃用?敏捷实践避免不推荐使用的代码?

回答

15

我不确定你能做多少事情。需求会发生变化,如果您绝对必须确保API的客户端不会被更新的API版本所破坏,那么您将只依赖于弃用代码,直到您认为没有人使用弃用的代码。

在代码中放置[Obsolete]属性会导致编译器在引用过时的方法时创建警告。这样API的客户端,如果他们努力修复他们的编译器警告,可以逐渐转向新的方法,而不会让所有的东西都破坏新版本。

它的有用的,如果您使用ObsoleteAttribute的覆盖,这需要字符串:

[Obsolete("Foo is deprecated. Use Bar instead for munging widgets.")] 

<轻浮>

也许你可以创建一个TimeBombAttribute:

[TimeBomb(new DateTime(2010,1,1), "Foo will blow up! Better use Bar, or else."] 

在你的代码,反映对于具有timebomb属性的方法,如果在指定日期之后调用它们,则抛出KaboomException。这将确保在2010年1月1日之后没有人使用过时的方法,并且可以很好地清理您的API。 :)

< /轻浮>

+0

+1:API更改是常态,不是一个例外。如果API没有改变,那么你的代码库就已经死了,没有人关心如何适应新的目的。 – 2009-07-08 14:35:03

5

马特说,该Obsolete属性是你的朋友...但每当你应用它,提供了如何更改调用代码的细节。这样你就可以更好地改变人们。您可能还想考虑指定您希望删除哪种版本的方法(可能是下一个主要版本)。

当然,您应该努力确保您不要调用过时的代码 - 特别是在示例代码中。

0

我认为代码的贬低是不断重构和增量开发等敏捷过程的不可避免的副产品。因此,如果您在处理项目时最终得到弃用的代码,那不一定是坏事 - 只是生活中的一个事实。当然,你可能会发现,不是贬低代码,而是保留大量的代码,但将其重构为不同的方法,类等等。

因此,底线:我不会担心在敏捷开发期间不推荐使用代码。如果它在一段时间内达到目的,那么你做的是正确的事情。

1

马特的回答是坚实的建议。我只是想提一提,intially你可能想使用的线沿线的东西:

[Obsolete("Please use ... instead ", false)] 

一旦你的代码移植,假更改为true,然后编译器会把所有的方法调用一个错误。

2

由于大部分敏捷开发的,如果需要

这不是敏捷围绕着使现在的东西的工作和重构之后。这是在敏捷标签下伪装的牛仔编码。

理想的是,无论你完成,是完成,根据任何定义你做。国防部通常会沿着“重构功能推动,测试和相关代码”的方式陈述某些事情。当然,如果你正在研究一次性原型,你可以有一个更放松的国防部。

API修改是一个困难的野兽。如果它们只是您正在修改的项目内部API,最好的方法是尽早重构。如果您需要更改内部API,请继续并同时更改所有API客户端。通过这种方式,重构债务不会变得非常大,您不必使用弃用。

对于已发布的API,您可能需要维护一些源代码和二进制兼容性,至少要等到下一个主要版本发布时为止。在维护兼容性的同时,标记旧API不再适用。与内部API一样,您应该尽快修复内部代码,以免使用弃用的API。

1

关注乔希布洛赫的“How to Design a Good API and Why It Matters

最重要的是W/R/T折旧是知道“有疑问时,离开它。”观看视频以获得澄清,但这与必须支持永久提供的内容有关。如果你真的期望这个API被重用,那么你就是在有效地设定你的决定。

我认为API设计以敏捷的方式来做是一件非常棘手的事情,因为您期望它可以以许多不同的方式重用。您必须担心打破依赖于您的其他人,因此尽管可以完成,但如果没有从其他团队快速转向,正确的设计就很难实现。当然,这里的弃用会对此有所帮助,但我认为YAGNI在涉及API时是一种更好的设计启发式。

1

API设计的经验法则是关注它的功能,而不是它如何实现。一旦你知道最终目标,找出你需要的绝对最小输入并使用它。避免将自己的对象作为参数传递,只传递数据。

从执行中分离配置。例如,也许你有一个图像编码器/解码器。

而是拨打电话一样的:

Encoder.Encode(bytes, width, height, compression_type, compression_ratio, palette, etc etc); 

让它

Encoder.setCompressionType(compression_type); 
Encoder.setCompressionType(compression_ratio); 
etc,etc 
Encoder.Encode(bytes, width, height); 

这样,添加或删除设置是不太可能打破现有的实现。

0

对于弃用,基本上有3种类型的API:内部,外部和公共。

内部是当你的团队唯一的代码工作。贬低这些API并不是什么大不了的事情。你的团队是唯一使用它的团队,所以他们不会长久,有改变他们的压力,人们不害怕改变他们,并且人们知道如何改变他们。

外部是当它有相同的代码库,但不同的团队正在使用它。这可能是一家大公司的一些通用库,或者是一个流行的开源库。关键是,人们可以选择他们编译的代码版本。弃用API的难易程度取决于组织的规模和沟通程度。国际海事组织,它的反对者的作业更新旧代码,而不是标记它已弃用,并让警告飞过整个代码库。为什么弃用者而不是弃权者?因为这位记者是知道的;他们知道变化和原因。

这两种情况很简单。只要有向后兼容性,通常你可以做任何你想做的事情,自己更新客户端,或者说服维护者去做。

然后有公共api的。这些基本上是外部API,客户端没有太多的控制权,比如web API。这些难以置信地更新或弃用。大多数不会注意到它的破坏,不会有人来修复它,不会得到它的变化的通知,并将只有修复它一旦它的破坏(他们已经大吼打破它,当然)。

我不得不做上述几次,这是一件很麻烦的事情。我认为你能做的最好的是有意破坏它,等一下,然后恢复它。当然,你首先发出通常的警告和弃用声明,但是 - 相信我 - 在事情中断之前什么都不会发生。

我还没有尝试的想法是让人们注册运行小测试的简单应用程序。当您想要进行API更新时,请运行外部测试并联系受影响的人员。

0

另一种流行的方法是让客户依赖(网络)服务。这里有一些构造允许你为你的服务进行版本管理并允许客户执行查找。这增加了更多移动部件和复杂度,但如果您正在考虑翻译大量版本并且必须支持生产中的多个版本,这会有所帮助。

This article做了很好的解释问题和方法。