Preparing Statistical Software with the srr package
srr
stands for Software Review Roclets, and is an R
package containing roclets for general use in helping those developing
and reviewing packages submitted to rOpenSci. At present, the srr
package only contains roclets and associated functions to help those
developing and reviewing packages submitted to rOpenSci’s system for
Statistical Software Review.
This vignette demonstrates how developers are intended to use this
package to document the alignment of their software with rOpenSci’s
standards for statistical
software.
The main functions of the package are constructed as roxygen2
“roclets”, meaning that these functions are
called each time package documentation is updated by calling
devtools::document()
or equivalently
roxygen2::roxygenise()
.
The former is just a wrapper around the latter, to enable documentation
to updated by a single call from within the devtools
package. From here on, this stage of
updating documentation and triggering the srr
roclets will be referred
to as “running
roxygenise
.”
1. The package skeleton
The srr_stats_pkg_skeleton()
function
included with this package differs from
other
package
skeleton
functions. Rather than providing a skeleton from which you can construct
your own package, the srr_stats_pkg_skeleton()
function
generates a skeleton to help developers understand this package works.
This skeleton of a package is intended to be modified to help you
understand which kinds of modifications are allowed, and which generate
errors. The package is by default called "demo"
, is constructed in R’s
tempdir()
,
and looks like this:
library (srr)
d <- srr_stats_pkg_skeleton (pkg_name = "package")
fs::dir_tree (d)
## /tmp/RtmpuwzVqt/package
## ├── DESCRIPTION
## ├── NAMESPACE
## ├── R
## │ ├── RcppExports.R
## │ ├── package-package.R
## │ ├── srr-stats-standards.R
## │ └── test.R
## ├── README.Rmd
## ├── src
## │ ├── RcppExports.cpp
## │ └── cpptest.cpp
## └── tests
## ├── testthat
## │ └── test-a.R
## └── testthat.R
The files listed there mostly exist to illustrate how standards can be
included within code. The format of standards can be seen by examining
any of those files. For example, the test.R
file looks like this:
readLines (file.path (d, "R", "test.R"))
## [1] "#' test_fn"
## [2] "#'"
## [3] "#' A test funtion"
## [4] "#'"
## [5] "#' @srrstats {G1.1, G1.2, G1.3} with some text"
## [6] "#' @srrstats Text can appear before standards {G2.0, G2.1}"
## [7] "#' @srrstatsTODO {RE1.1} standards which are still to be"
## [8] "#' addressed are tagged 'srrstatsTODO'"
## [9] "#'"
## [10] "#' @export"
## [11] "test_fn <- function() {"
## [12] " message(\"This function does nothing\")"
## [13] "}"
That file illustrates some of the
roxygen2
tags defined by this package,
and described in detail below. These tags are parsed whenever package
documentation is updated with
roxygenise()
,
which will produce output like the following:
roxygen2::roxygenise (d)
## Setting `RoxygenNote` to "7.2.3"
## ℹ Loading package
## Writing 'NAMESPACE'
## ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── rOpenSci Statistical Software Standards ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
##
##
##
## ── @srrstats standards (8 / 12):
##
## * [G1.1, G1.2, G1.3, G2.0, G2.1] in function 'test_fn()' on line#11 of file [R/test.R]
## * [RE2.2] on line#2 of file [tests/testthat/test-a.R]
## * [G2.3] in function 'test()' on line#6 of file [src/cpptest.cpp]
## * [G1.4] on line#17 of file [./README.Rmd]
##
##
##
## ── @srrstatsNA standards (1 / 12):
##
## * [RE3.3] on line#5 of file [R/srr-stats-standards.R]
##
##
##
## ── @srrstatsTODO standards (3 / 12):
##
## * [RE4.4] on line#14 of file [R/srr-stats-standards.R]
## * [RE1.1] on line#11 of file [R/test.R]
## * [G1.5] on line#17 of file [./README.Rmd]
##
## ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
##
## Writing 'package-package.Rd'
## Writing 'test_fn.Rd'
## Writing 'NAMESPACE'
The “roclets” contained within this package parse any instances of the
package-specified tags described below, and summarise the output by
listing all locations of each kind of tag. Locations are given as file
and line numbers, and where appropriate, the names of associated
functions. We recommend that developers familiarise themselves with the
system by simply modifying any roxygen2
block in any of the files of this package skeleton, and running
roxygenise()
to see what happens.
2. Enabling srr
roclets for a package
The “roclets” can be enabled for a package by modifying the
DESCRIPTION
file so that the Roxygen
line looks like this:
Roxygen: list (markdown = TRUE, roclets = c ("namespace", "rd", "srr::srr_stats_roclet"))
That will load the “roclets” used by this
package to process standards as documented within your actual code. Note
that you do not need to add, import, or depend upon the srr
package
anywhere else within the DESCRIPTION
file. See the DESCRIPTION
file
of the package skeleton for an example.
4. The srr
workflow
The first step for any developer intending to use this package on the
way to a submission to rOpenSci’s project for peer-reviewing statistical
software is to generate the package skeleton described above, and to try
any and all conceivable ways to modify locations, formats, and other
properties of the roxygen2
tags defined
in this package, in order to understand how these tags are used to
generate the summary results when running
roxygenise
.
Following that initial familiarisation, a typical workflow will involve
the following general steps:
Automatically download and insert lists of general and category-specific standards in your package by running
srr_stats_roxygen()
(in the main package directory). This will by default generate a file in theR/
directory calledsrr-stats-standards.R
, although any alternative name can also be passed to the function (or the file can be renamed after it has initially been created). Each group of standards in this file must always be terminated byNULL
in order to be appropriately parsed by theroxygen2
package.Change your package’s
DESCRIPTION
file to use thesrr
roclets by addingroclets = "srr::srr_stats_roclet"
) to theRoxygen
line, as demonstrated at the outset, as well as in the package skeleton.Run
roxygenise
to confirm that the roclets work on your package. You should initially see only a single list of@srrstatsTODO
standards. All documented standards should appear somewhere in the output. Any missing standards indicate documentation problems, such as missing terminalNULL
values from standards blocks.We recommend as a first step cutting-and-pasting standards to approximate locations within your package’s code where you anticipate these standards being addressed. Multiple copies of any one standard may exist in multiple locations, so you may also repeat standards which you anticipate will be addressed in multiple locations. This should reduce a potentially very long initial list of standards down to several distinct groups of hopefully more manageable size.
Begin addressing the standards by:
Ensuring your code conforms;
Moving each standard to the one or more location(s) where you think your code most directly addresses them;
Modifying the
@srrstatsTODO
tag to@srrstats
Changing the initial text describing the standard itself to a brief description of how your code addresses that standard.
Standards which you deem not to be applicable to your package should be grouped together in a single
roxygen2
block with the titleNA_standards
(as described above, and as generated by thesrr_stats_roxygen()
function). This block must finish with aNULL
statement.Update your documentation as frequently as you like or need, and use the output of the roclets to inform and guide the process of converting all
@srrstatsTODO
tags into either@srrstats
or@srrstatsNA
tags.
Note that we do not recommend copying files from the package
skeleton into your own package for you srr
documentation. The
following lines demonstrate what happens if you insert actual standards
into the package skeleton:
srr_stats_roxygen (category = "regression", # for example
filename = file.path (d, "R", "srr-stats-standards.R"),
overwrite = TRUE)
## ✔ Downloaded general standards
## ✔ Downloaded regression standards
## ℹ Roxygen2-formatted standards written to [srr-stats-standards.R]
roxygen2::roxygenise (d)
## ℹ Loading package
## Error: Standards [G1.1, G1.2, G1.3, G2.0, G2.1, RE2.2, G2.3, G1.4] are listed with both @srrstats and @srrstatsTODO tags.
## Please rectify to ensure these standards are only associated with one tag.
To ensure all standards are first inserted with @srrstatsTODO
tags,
and that there are no duplicates with other tags, please use only the
srr_stats_roxygen()
function.