Modulr is a Dependency Injection (DI) framework for R which allows to break down sequential programs into discrete, modular units that are loosely coupled, simple to develop, test, debug, maintain, reuse, and share.

  • Modulr is designed to ease production of mocks for testing purpose and is therefore well-suited for test-driven development.
  • Modulr offers docstrings-like comments for documenting the internals of a module.
  • Modulr understands R Markdown and Sweave, thanks to Yihui Xie’s knitr package.
  • Modulr takes advantage of semantic versioning to avoid version lock and version promiscuity.
  • Modulr can use GitHub (repositories and gists) to publish and share modules (so-called gears). See modulr/vault for an example.
  • Modulr helps to circumvent errors occurring in a chain of nested dependent modules, showing breadcrumbs.
  • Modulr allows parallelization using futures, thanks to Henrik Bengtsson’s future package.
  • Modulr implements package isolation as an experimental feature: following the philosophy of Jim Hester’s withr package, the ‘with_’ method with_no_packages() can be used to run code with temporarily no loaded or attached R packages.

Please read the documentation and vignettes (browseVignettes(package = "modulr")) to see extended examples in action.

“Hello, world!”

library(modulr)

"foo" %provides% "Hello"
#> [2018-12-02T16:13:53 UTC] Defining 'foo' ... OK

"bar" %provides% "World"
#> [2018-12-02T16:13:53 UTC] Defining 'bar' ... OK

"foobar" %requires% list(
  f = "foo", 
  b = "bar"
) %provides% {
  paste0(f, ", ", tolower(b), "!")
}
#> [2018-12-02T16:13:53 UTC] Defining 'foobar' ... OK

make("foobar")
#> [2018-12-02T16:13:53 UTC] Making 'foobar' ...
#> [2018-12-02T16:13:53 UTC] * Visiting and defining dependencies ...
#> [2018-12-02T16:13:53 UTC] * Constructing dependency graph ... OK
#> [2018-12-02T16:13:53 UTC] * Sorting 2 dependencies with 2 relations ... on 1 layer, OK
#> [2018-12-02T16:13:53 UTC] * Evaluating new and outdated dependencies ...
#> [2018-12-02T16:13:53 UTC] ** Evaluating #1/2 (layer #1/1): 'bar' ...
#> [2018-12-02T16:13:53 UTC] ** Evaluating #2/2 (layer #1/1): 'foo' ...
#> [2018-12-02T16:13:53 UTC] DONE ('foobar' in 0.059 secs)
#> [1] "Hello, world!"

Installation

install.packages("devtools")
devtools::install_github("hadley/devtools")
devtools::install_github("aclemen1/modulr")

If you encounter a clear bug, please file a minimal reproducible example. For questions and other discussion, please use the modulr mailing list.

Real-world applications

 
This is the dependency graph of a module (on the rightmost side) which exposes tidy, exhaustive, statistics-ready, and daily HR data for the University of Lausanne, Switzerland. Although not visible here, many of these modules are reused in other projects. The University of Lausanne has been running modulr in mission critical applications since March 2015.

Code of conduct

In order to have a more open and welcoming community, modulr adheres to a Contributor Code of Conduct. Please adhere to this code of conduct in any interactions you have in the modulr community. It is strictly enforced on all official modulr repositories, websites, and resources. If you encounter someone violating these terms, please let the maintainer know and he will address it as soon as possible.