最近,我不得不深入研究 JavaScript 代码弃用的主题。我觉得这个主题没有得到足够的重视,尽管它可能在某些项目中发挥关键作用,尤其是在与大型团队合作或处理外部 API 时。
在 JavaScript 世界里,我不知道有任何真正意义上的行业标准来弃用 JavaScript。它可能因团队、库或供应商而异。
因此,我在这里的目标是总结我对该主题的发现和想法,以及在将 JavaScript 方法标记为已弃用时的一些良好实践。
“弃用”到底意味着什么?
首先,让我们先澄清一下,弃用只是应用于软件功能的一种 **状态**。它表明应该避免使用该功能,通常是因为它已被取代。
弃用也可能意味着该功能将来会被删除。弃用功能而不是立即删除是为了提供向后兼容性,并为使用过该功能的程序员提供时间使其代码符合新标准。
此外,弃用功能表明从现在开始不会再有任何进一步的开发。它不应该比以前版本有任何不同(除非文档明确说明了其他情况)。因此,通常情况下,它应该与弃用操作发生时一样。
它可能在最新版本中有效,也可能无效——没有保证!
但是,由于 JavaScript 世界里并没有严格遵循的真正行业标准,这可能因团队、库或供应商而异。
何时弃用代码,何时删除代码?
需要注意的是,弃用的软件功能或方法仍然是软件的一部分!将“弃用”标签视为代码的只是一种状态。软件功能将来是否会被实际删除取决于该特定软件团队的决定。
在我看来,依赖于外部 API 或库的大型团队或项目应该先弃用,然后在稍后(在合理的时间内,无论您如何定义)删除。至少在实际删除弃用代码之前,进行一次重大版本升级,以便用户有机会适应更改。
您可能想看看 语义化版本控制,它是一套简单规则和要求,规定了版本号的分配和递增方式。给定版本号 MAJOR.MINOR.PATCH
,当您进行不兼容的 API 更改时递增 MAJOR
版本,当您以向后兼容的方式添加功能时递增 MINOR
版本,当您进行向后兼容的错误修复时递增 PATCH
版本。
如果您的软件正在快速更改和发展,并且您正在弃用某个功能,请尝试与项目经理沟通,看看该功能是否预计将来会复活。如果您选择弃用而不是删除,如果您需要,它可能更容易恢复。
对于使用内部方法和 API 的小型团队或项目,可以直接删除而不是弃用。有时,浪费时间在弃用上没有意义,而只是为了遵循最佳实践而弃用只会增加复杂性。
如何标记方法已弃用
以下是我发现最有用的五种良好实践
- 添加
@deprecated
JSDoc 标志。 - 提及该方法被弃用的版本。
- 确定该方法何时会被删除的时间范围,包括将要删除的版本。否则,根据我的经验,它会永远存在 🙂
- 使用注释来解释实现,以便其他开发人员或您未来的自己能够理解。如果您的用例是编写一个库,而其他人将其用作其工作的依赖项,那么这一点非常有用。
- 添加一条控制台警告消息,指示该函数已弃用。
以下是一个更实际的示例,其中我使用了所有五种实践
/**
* A magic method that multiples digits.
*
* @deprecated [#1] since version 2.3 [#2].
* [#3] Will be deleted in version 3.0.
* [#4] In case you need similar behavior, implement it on you own,
* preferably in vanilla JavaScript
* or use the multiplyTheSameNumber method instead,
* if the same number needs to be multiplied multiple times, like so:
* multiplyDigits([5, 5, 5]) === multiplyTheSameNumber(5, 3)
*
* @param {array} _digits - digits to multiply
*/
function multiplyDigits(_digits) {
console.warn("Calling a depricated method!"); // [#5]
// ....
}
为了避免在控制台警告中重复,或者如果您计划弃用多个方法并且有它们的替换,使用助手可能更方便
/**
* Creating a deprecated / obsolete behavior for methods in a library.
* [Credits]{@link: https://stackoverflow.com/q/21726472/1333836}
*
* @param {function} replacementFunction
* @param {string} oldFnName
* @param {string} newFnName
* @return {function}
*/
const Oboslete = function(replacementFunction, oldFnName, newFnName) {
const wrapper = function() {
console.warn("WARNING! Obsolete function called. Function '" + oldFnName + "' has been deprecated, please use the new '" + newFnName + "' function instead!");
replacementFunction.apply(this, arguments);
}
wrapper.prototype = replacementFunction.prototype;
return wrapper;
}
总结
我建议让您的团队达成一致,并继承最适合您的项目或用例的弃用实践,无论是采用我们这里介绍的实践还是其他实践。
请注意,在某些情况下,删除比弃用更有意义。有时,投入精力来弃用某些东西根本不值得。再说一次,这完全取决于您,以及什么最适合您的项目。
您知道在 JavaScript 中标记方法已弃用时的其他良好实践吗?请在评论中告诉我!
致谢
我在这里分享的想法受到了我在 软件工程 Stack Exchange 和 StackOverflow 上找到的评论的启发。
如果弃用函数被多次调用,确保控制台警告只发出一次可能很好;否则它会无用地塞满控制台。
嗯,无论如何您不应该依赖于弃用函数,所以我会说,警告塞满控制台的烦恼会促使您解决问题源头。此外,如果您必须这样做,您可以设置过滤器来隐藏警告(至少在 Chrome 中可以这样做)。
有用的文章,但可能最好有一个关于如何实际使用您创建的助手的说明,因为它没有解释(哦,还有您在助手名称中拼错了,应该是 Obsolete)。
当版本为 0.x.x 时,不需要弃用,因为该版本还没有稳定的 API,因此该方法可以直接删除。
其中一些取决于您的用户是谁。
如果您有一个仅由您自己的开发人员使用的内部库,那么一个简短的正常 -> 已弃用 -> 删除周期就可以了。如果您有一个在很多地方使用的库,那么您可以随意弃用,但不要删除。
相反,您发布一个新库,并使用一个新名称。新库明确声明它不支持旧库的函数 X,并且 Y 和 Z 的语法已经改变。
新库还应该有一个代码迁移指南。
旧库的最后一个版本会指向新库,以及不兼容性自述文件。
我已经经常被 Apple 的这种做法所困扰。旧程序在新的操作系统版本上无法运行,因为他们已经从标准库中删除了函数。
如果一个库具有某种可选的日志记录功能,这可能很有用。在一个级别上,它只记录库是否被使用(而不是只被加载)。在更详细的级别上,它记录了调用了哪些函数。如果库或它的父调用程序具有网络意识,则可以将其安装为休眠函数。在每个月的第一天,它会向开发人员的服务器发送一个 UDP 数据包,“您需要日志吗?”服务器会以“不,休眠 X 天/月/年/永远”或“是,记录与正则表达式 {expression} 匹配的 X% 的调用”做出响应。
这使您可以查看人们是否仍在使用库,尽管它已弃用。
包装函数不应该返回
replacementFunction.apply
的结果吗?