我正在将一个开源Java库转换为C#,它有许多标记为已弃用的方法和类。这个项目是一个以干净的石板开始的机会,所以我打算完全删除它们。然而,作为大型项目的新手,我很紧张,情况会再次出现。由于敏捷开发的大部分内容都围绕着使某些东西现在正常运行并在以后需要时进行重构,因此API的弃用似乎必然是一个常见的问题。即使我不完全确定项目的未来发展方向,我是否可以采取预防措施来避免/减少API弃用?
答案 0 :(得分: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。 :)
< /轻浮>
答案 1 :(得分:5)
正如Matt所说,Obsolete
属性是你的朋友......但每当你应用它时,都会提供如何更改调用代码的详细信息。这样你就可以更好地改变人们。您可能还需要考虑指定您希望删除该方法的版本(可能是下一个主要版本)。
当然,您应该努力确保您不要调用过时的代码 - 特别是在示例代码中。
答案 2 :(得分:2)
由于敏捷开发的大部分内容都围绕着使某些东西现在正常工作并在以后需要时进行重构
那不敏捷。这是以敏捷标签伪装的牛仔编码。
理想的是,无论你完成什么,完整,根据你所拥有的任何定义。通常情况下,国防部会提出“重构特征,经过测试并重新编码相关代码”的内容。当然,如果你正在研究一次性原型,你可以拥有一个更轻松的国防部。
API修改是一个困难的野兽。如果它们只是您正在修改的项目内部API,那么最好的方法就是尽早进行重构。如果您需要更改内部API,请继续并同时更改所有API客户端。这样,重构债务不会变得非常大,您不必使用弃用。
对于已发布的API,您可能需要保留一些源代码和二进制兼容性保证,至少在下一个主要版本发布之前。标记旧的API已弃用,同时保持兼容性。与内部API一样,您应该尽快修复内部代码,以免使用已弃用的API。
答案 3 :(得分:1)
马特的答案是坚实的建议。我只想提一下,你可能想要使用以下内容:
[Obsolete("Please use ... instead ", false)]
移植代码后,将false更改为true,然后编译器会将对方法的所有调用视为错误。
答案 4 :(得分:1)
观看Josh Bloch的“How to Design a Good API and Why It Matters”
最重要的w / r / t弃用是知道“如有疑问,请将其删除”。观看视频以获得澄清,但这与必须永远支持您提供的内容有关。如果您真实地希望重用API,那么您就可以有效地制定决策。
我认为API设计在敏捷方面是一件非常棘手的事情,因为你期望它可能以多种不同的方式被重用。你必须担心打破依赖你的其他人,所以虽然可以做到,但如果没有得到其他团队的快速转变,很难找到合适的设计。当然,弃用在这方面会有所帮助,但我认为 YAGNI 在API方面是更好的设计启发式。
答案 5 :(得分: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);
这样,添加或删除设置就不太可能破坏现有的实现。
答案 6 :(得分:0)
我认为代码弃用是敏捷流程不可避免的副产品,如持续重构和增量开发。因此,如果您在处理项目时最终使用已弃用的代码,那么这不一定是件坏事 - 只是生活中的一个事实。当然,您可能会发现,不是弃用代码,而是最终保留大量代码,但将其重构为不同的方法,类等。
所以,底线:我不担心在敏捷开发过程中弃用代码。如果它暂时服务于它的目的,你做的是正确的。
答案 7 :(得分:0)
对于弃用,基本上有3种类型的API:内部,外部和公共。
内部是其唯一的团队处理代码的时候。弃用这些API并不是什么大问题。你的团队是唯一一个使用它的团队,所以他们不会长久,有改变它们的压力,人们不怕改变它们,人们知道如何改变它们。
外部是它的相同代码库,但不同的团队正在使用它。这可能是大公司中的一些常见库,或者是流行的开源库。关键是,人们可以选择他们编译的代码版本。弃用API的难易程度取决于组织的规模以及它们的沟通情况。 IMO,它是 deprecator的工作来更新旧代码,而不是标记为已弃用,并让警告在整个代码库中传播。为什么使用贬值者而不是弃用者?因为展开者是知道的;他们知道改变了什么,为什么会改变。
这两种情况非常简单。只要有向后兼容性,您通常可以做任何您喜欢的事情,自己更新客户端,或说服维护人员这样做。
然后有公共api。这些基本上是客户端无法控制的外部API,例如Web API。这些都非常难以更新或弃用。大多数人不会注意到它已损坏,不会有人修复它,也不会收到通知它会发生变化,并且只会修复它一旦它被破坏(在他们大喊大叫之后) >你打破它,当然)。
我必须做几次上面的事情,这是一件很麻烦的事。我认为你能做的最好的就是故意将它早点,稍等一下,然后恢复它。当然,你首先发出通常的警告和弃用,但是 - 相信我 - 在事情发生之前什么都不会发生。
我还要尝试的一个想法是让人们注册运行小型测试的简单应用程序。如果要进行API更新,请运行外部测试并联系受影响的人员。
答案 8 :(得分:0)
另一种受欢迎的方法是让客户依赖(网络)服务。有一些构造允许您对服务进行版本控制并允许客户端执行查找。这会在方程中增加更多移动部件和复杂性,但如果您要查看许多版本,并且必须支持生产中的多个版本,则可能会有所帮助。
This article在解释问题和方法方面做得很好。