-
Notifications
You must be signed in to change notification settings - Fork 759
Philosophy
This book espouses a particular philosophy of package development - it is not shared by all R developers, but it is one connected to a specific set of tools that makes package development as easy as possible.
There are three packages we will use extensively:
-
devtools
, which provides a set of R functions that makes package development as easy as possible. -
roxygen2
, which translates source code comments into R's official documentation format -
testthat
, which provides a friendly unit testing framework for R.
Other styles of package development don't use these packages, but in my experience they provide a useful trade off between speed and rigour. That's a theme that we'll see a lot in this chapter: base R provides rigorous tools that guarantee correctness, but tend to be slow. Sometimes you want to be able to iterate more rapidly and the tools we discuss will allow you to do so.
A package doesn't need to be complicated. You can start with a minimal subset of useful features and slowly build up over time. While there are strict requirements if you want to publish a package to the world on CRAN (and many of those requirements are useful even for your own packages), most packages won't end up on CRAN. Packages are really easy to create and use once you have the right set of tools.
Anytime you create some reusable set of functions you should put it in a package. It's the easiest path because packages come with conventions: you don't need to figure them out for yourself. You'll start with just your R code in the R/
directory, and over time you can flesh it out with documentation (in man/
), compiled code (in src/
), data sets (in data/
), and tests (in inst/tests
).
To get started, make sure you have the latest version of R: if you want to submit your work to CRAN, you'll need to make sure you're running all checks with the latest R.
You can install the packages you need for this chapter with:
install.packages("devtools", dependencies = TRUE)
You'll also need to make sure you have the appropriate development tools installed:
-
On windows, download and install Rtools: http://cran.r-project.org/bin/windows/Rtools/. This is not an R package.
-
On mac, make sure you have either XCode (free, available in the app store) or the "Command Line Tools for Xcode" (needs a free apple id, available from http://developer.apple.com/downloads)
-
On linux, make sure you've installed not only R, but the R development devtools. This a linux package called something like
r-base-dev
.
You can check you have everything installed and working by running this code:
library(devtools)
has_devel()
It will print out some compilation code (this is needed to help diagnose problems), but you're only interested in whether it returns TRUE
(everything's ok) or an error (which you need to investigate further).
The goal of the devtools package is to make package development as painless as possible by encoding package building best practices in functions (so you don't have to remember or even know about them), and by minimising the iteration time when you're developing a package.
Most of the devtools functions we will use take a path to the package as their first argument. If the path is omitted, devtools will look in the current working directory - so for that reason, it's good practice to have your working directory set to the package directory.
The functions that you'll use most often are those that facilitate the package development cycle:
-
load_all()
: simulates package installation and loading bysource()
ing all files in theR/
directory, compiling and linking C, C++ and Fortran files in thesrc/
andload()
ing data files in thedata/
directory. More on that in package development -
document()
: extracts documentation from source code comments and createsRd
files in theman/
directory. You can usedev_help()
anddev_example()
instead ofhelp()
andexample()
to preview these files without installing the package. More on that in documentation. -
test()
: runs all unit tests in theinst/test/
directory and reports the results. More on that in testing.
Other functions mimic standard R commands that you run from the command line:
-
build()
is equivalent toR CMD build
and bundles package. See package-basics for more about what a bundled package is. -
install()
is equivalent toR CMD INSTALL
and installs a package into a local library. Learn more about the installation process in package-basics. -
check()
is equivalent toR CMD check
, and runs a large set of automated tests against your package. Read more about checking as part of the release process.
These tools should be more reliable than running the equivalent commands in the terminal (and much easier to use if you're not familiar with the terminal). They do more to ensure that command-line R is running in exactly the same way as your R GUI. They check that you're running the same version of R, with the same library paths, and with a standard collation order. These are things you don't need to worry about most of the time, but if they ever trip you up, it can take hours to figure out the source of the problem. check()
and install()
also run build first, which is recommended best practice.
There are two other functions that you use less commonly, only at the start and the end of package development:
-
create()
creates a new package, and fills it out with the basics (this is thedevtools
equivalent ofpackage.skeleton
) -
release()
checks the package, checks that you've done what the CRAN maintainers expect, uploads to CRAN and drafts an email for the CRAN maintainers