25 Deprecation Guidelines

In the normal course of software development, functions, classes, methods, or data objects may need to be removed. Here are some guidelines for ensuring that this process is minimally disruptive to your users.

25.1 What to Deprecate?

Any function, class, method, data, or even package that is no longer used or needed.

25.2 When to Follow These Guidelines?

>|--- Bioconductor development cycle ---------------|>
>|--- o feature introduced --- o feature removed ---|>

Note that if you decide against using a function that you had introduced within the same development cycle, you may simply remove the function without following the standard function deprecation guidelines. It is expected that the devel branch be unstable and be subject to API changes without notice (though you may decide to communicate these changes to your users via the Bioconductor support site).

>| Bioconductor RELEASE_X_Y | Bioconductor development cycle |>
>|-- o feature introduced --|----- o feature removed --------|>

However, if a function was published in at least one release version of Bioconductor, these guidelines must be followed. The process of removing a feature such as a function, class, method, or exported package object takes approximately three release cycles (about 18 months).

25.3 How To Deprecate A Function

25.3.1 Step 1: Deprecate the function

When you first decide to deprecate a function, you should mark it as deprecated in the devel branch. Do this by calling .Deprecated() inside the function. To do this, you must provide a replacement function which should be used in place of the old function. Example:

myOldFunc <- function()
{
    .Deprecated("myNewFunc")
    ## use new function, or remainder of myOldFunc
}

This causes a warning to be emitted whenever a user calls myOldFunc(). See ?.Deprecated for more information.

Indicate in the man page of the old function that it has been deprecated, and suggest a replacement function. Be sure the old function is not called in man page examples or vignette code chunks; R CMD check should report this.

\name{MyPkg-deprecated}
\alias{MyPkg-deprecated}
\title{Deprecated functions in package \sQuote{MyPkg}}

\description{
  These functions are provided for compatibility with older versions
  of \sQuote{MyPkg} only, and will be defunct at the next release.
}

\details{

  The following functions are deprecated and will be made defunct; use
  the replacement indicated below:
  \itemize{

    \item{myOldFunc: \code{\link{newFunc}}}

  }
}

25.3.2 Step 2: Mark the function as defunct

In the next release cycle, after your function has been deprecated, it must be made defunct in the devel branch. This means a call to the old function will return an informative error but not run any additional code. Example:

myOldFunc <- function()
{
    .Defunct("myNewFunc")
}

See ?Defunct for more information.

Remove the documentation of the defunct function, and add to a man page such as the following:

\name{MyPkg-defunct}
\alias{myOldFunc}
\title{Defunct functions in package \sQuote{pkg}}
\description{These functions are defunct and no longer available.}

\details{
  Defunct functions are: \code{myOldFunc}
}

25.3.3 Step 3: Remove the function

In the next release cycle, after your function has been marked as defunct, remove it entirely from your package R code and NAMESPACE in the devel branch. Also remove any man page content that documents the function.

Leave the man page from the previous step in place so that

help("MyPkg-defunct")

still shows the list of defunct functions and their appropriate replacements.

25.4 How To Deprecate A Package Dataset

25.4.1 Step 1 - Save a promise object

The initial step of deprecating a dataset is to signal to any users on the devel branch of Bioconductor that the dataset will no longer be used. This can be done using a warning message when the devel user loads the dataset. In order to do this, we first create a promise object with the same name as the dataset name using the delayedAssign function:

delayedAssign(
    x = "pkgDataset",
    value = {
        warning("'pkgDataset' dataset is deprecated; see '?newData'")
        pkgDataset
    }
)

You can also include the dataset as an output after the warning. We then replace the original .Rda dataset file in the package with the promise object and dataset using the save function:

save("pkgDataset", eval.promises = FALSE, file = "data/pkgDataset.Rda")

With the eval.promises argument set to FALSE, we can delay the evaluation of the promise object until the user loads the data with data("pkgDataset", package = "yourPkg"). The user will then get a warning along with the dataset. The warning should include instructions that will point the user to a new dataset or functionality that will replace the data, if necessary.

25.4.2 Step 2 - Update documentation

After the promise object has been saved, we update the documentation to reflect the changes and provide additional details and resources for users as necessary. It is recommended to include a “[Deprecated]” label in the data documentation title.

25.4.3 Step 3 - Defunct the dataset

In the following release cycle, you can update the warning message to indicate that the dataset is defunct and remove it entirely from the promise object i.e., from the expression in the delayedAssign function. We can also update the “[Deprecated]” label in the documentation title to “[Defunct]”.

25.5 How to Deprecate a Package

Please see section on Package End of Life Policy