41

我正在更新一个旧包并缩短一堆非常长的函数名称。如何让用户知道旧功能已被弃用?我记录了所有内容,roxygen2所以我想知道#' @alias我应该使用什么?想法?

4

4 回答 4

55

即使您只是缩短函数名称,我仍然会像对包的公共 API 的任何更改一样大张旗鼓地对待它:随着新函数的引入,旧函数的弃用/失效阶段。

在第一阶段,对于要缩短名称的每个函数(我们称之为它transmute_my_carefully_crafted_data_structure_into_gold),您保留一个具有该签名的函数,但将所有实际代码移动到新命名的函数中(我们称之为它alchemy)。

最初:

transmute_my_carefully_crafted_data_structure_into_gold <- function(lead, alpha=NULL, beta=3) {
  # TODO: figure out how to create gold
  # look like we are doing something
  Sys.sleep(10)
  return("gold")
}

首次使用新名称发布:

transmute_my_carefully_crafted_data_structure_into_gold <- function(lead, alpha=NULL, beta=3) {
  .Deprecated("alchemy") #include a package argument, too
  alchemy(lead=lead, alpha=alpha, beta=beta)
}

alchemy <- function(lead, alpha=NULL, beta=3) {
  # TODO: figure out how to create gold
  # look like we are doing something
  Sys.sleep(10)
  return("gold")
}

因此,这transmute_my_carefully_crafted_data_structure_into_gold从 . 周围的薄包装开始alchemy,并带有额外的.Deprecated调用。

> transmute_my_carefully_crafted_data_structure_into_gold()
[1] "gold"
Warning message:
'transmute_my_carefully_crafted_data_structure_into_gold' is deprecated.
Use 'alchemy' instead.
See help("Deprecated") 
> alchemy()
[1] "gold"

如果您对 进行更改alchemy,它仍然存在,transmute_my_carefully_crafted_data_structure_into_gold因为它只是调用前者。但是,您不会更改transmute_my_carefully_crafted_data_structure_into_gold即使更改的签名alchemy;在这种情况下,您需要尽可能地将旧参数映射到新参数中。

在以后的版本中,您可以更改.Deprecated.Defunct.

> transmute_my_carefully_crafted_data_structure_into_gold()
Error: 'transmute_my_carefully_crafted_data_structure_into_gold' is defunct.
Use 'alchemy' instead.
See help("Defunct")

请注意,这是一个错误并停止;它不会继续调用alchemy

您可以在以后的某个版本中完全删除此功能,但我会将其保留在此状态作为路标。

您提到使用 roxygen。当您第一次过渡到弃用时,您可以将@rdname 更改为 package-deprecated,在描述的开头添加一行说明它已弃用,将新功能添加到 @seealso。当它更改为 defunct 时,将 @rdname 更改为 package-defunct。

于 2012-04-13T17:39:44.307 回答
23

我想“正确”的答案取决于你想要什么。在我看来:

  1. Jeff 和 Brandon 的方法的问题在于,您的索引将列出两个函数名称,并且没有说明哪个是首选名称。此外,如果没有某种 .Deprecated 调用,用户就更不可能知道调用该函数的首选方式是什么。
  2. Brian 方法的问题在于,我不清楚将多个函数列为已弃用的过程。

因此,请在下面输入我的示例。在另一个位置,我定义了函数的“好”版本(例如炼金术、latinSquareDigram)。在这里,我定义了我想要为其生成弃用警告的所有旧的“坏”版本。我遵循了 car 包的方法,并将我所有的函数调用更改为不推荐使用的版本,以使用 ... 作为参数。这帮助我避免了一堆杂乱的@param 语句。我还使用了@name 和@docType 指令使“yourPackageName-deprecated”出现在索引中。也许有人有更好的方法来做到这一点?

现在,每个已弃用的函数仍会显示在索引中,但在它们旁边会显示“yourPackageName 包中已弃用的函数”,并且对它们的任何调用都会产生弃用警告。要将它们从索引中删除,可以删除 @aliases 指令,但随后您将拥有用户级未记录的代码对象,我认为这是错误的形式。

#' Deprecated function(s) in the yourPackageName package
#' 
#' These functions are provided for compatibility with older version of
#' the yourPackageName package.  They may eventually be completely
#' removed.
#' @rdname yourPackageName-deprecated
#' @name yourPackageName-deprecated
#' @param ... Parameters to be passed to the modern version of the function
#' @docType package
#' @export  latinsquare.digram Conv3Dto2D Conv2Dto3D dist3D.l
#' @aliases latinsquare.digram Conv3Dto2D Conv2Dto3D dist3D.l
#' @section Details:
#' \tabular{rl}{
#'   \code{latinsquare.digram} \tab now a synonym for \code{\link{latinSquareDigram}}\cr
#'   \code{Conv3Dto2D} \tab now a synonym for \code{\link{conv3Dto2D}}\cr
#'   \code{Conv2Dto3D} \tab now a synonym for \code{\link{conv2Dto3D}}\cr
#'   \code{dist3D.l} \tab now a synonym for \code{\link{dist3D}}\cr
#' }
#'  
latinsquare.digram <- function(...) {
  .Deprecated("latinSquareDigram",package="yourPackageName")
  latinSquareDigram(...)
}
Conv3Dto2D <- function(...) {
  .Deprecated("conv3Dto2D",package="yourPackageName")
  conv3Dto2D(...)
}
Conv2Dto3D <- function(...) {
  .Deprecated("conv2Dto3D",package="yourPackageName")
  conv2Dto3D(...)
}
dist3D.l <- function(...) {
  .Deprecated("dist3D",package="yourPackageName")
  dist3D(...)
}
NULL
于 2012-12-26T05:57:14.437 回答
4

我有一段时间遇到这个问题,无法找到一个好的解决方案。然后我发现了这个。尽管如此,对于简单的情况,上述答案过于复杂:1)添加一个别名,以便旧代码不会停止工作,2)别名必须与内置文档一起使用,以及 3)它应该用roxygen2完成。

首先,添加一个函数的副本:

old_function_name = new_function_name

然后,在哪里new_function_name()定义,添加到roxygen2:

#' @export new_function_name old_function_name
#' @aliases old_function_name

现在旧函数可以工作,因为它只是新函数的副本,而文档可以工作,因为您设置了别名。旧版本也被导出,因为它包含在@export.

于 2015-11-10T17:04:19.610 回答
3

在将过长的函数名称转换为较短版本的情况下,我建议将两个名称导出为同一个函数(参见@Br​​andon 的评论)。这将允许旧代码继续工作,同时为新用户提供更方便的选择。

在我看来,将某些内容标记为.Deprecated(请参阅@GSEE)的唯一原因是您计划从根本上更改功能或停止在未来版本中支持某些功能。如果是这种情况,您可以使用.Defunctor .Deprecated

于 2012-04-11T15:33:31.597 回答