Developing Packages R
This skill covers building robust R packages with modern patterns and best practices.
Dependency Strategy
When to Add Dependencies vs Base R
Add dependency when:
- •Significant functionality gain
- •Maintenance burden reduction
- •User experience improvement
- •Complex implementation (regex, dates, web)
Use base R when:
- •Simple utility functions
- •Package will be widely used (minimize deps)
- •Dependency is large for small benefit
- •Base R solution is straightforward
See dependency-decisions.md for example decisions.
Tidyverse Dependency Guidelines
| Category | Packages | Guidance |
|---|---|---|
| Core (usually worth it) | dplyr, purrr, stringr, tidyr | Complex manipulation, functional programming |
| Specialized (evaluate carefully) | lubridate, forcats, readr, ggplot2 | Only if heavy usage |
| Heavy (use sparingly) | tidyverse, shiny | Meta-package or interactive apps only |
API Design Patterns
Modern Tidyverse API
See api-design.md for:
- •Use
.byfor per-operation grouping - •Use
{{ }}for user-provided columns - •Use
...for flexible arguments - •Return consistent types (tibbles, not data.frames)
Input Validation Strategy
Validation level depends on function type:
| Function Type | Validation Level |
|---|---|
| User-facing | Comprehensive - check all inputs |
| Internal | Minimal - assume valid, check invariants |
| vctrs-based | Type-stable - automatic checking |
See validation-patterns.md for examples.
Error Handling Patterns
Good error messages are:
- •Specific - say what went wrong
- •Actionable - say how to fix it
- •Traceable - include function context
See error-handling.md for:
- •cli package for user-friendly messages
- •rlang for developer tools
- •Including function name in errors
Internal vs Exported Functions
Export Function When:
- •Users will call it directly
- •Other packages might want to extend it
- •Part of the core package functionality
- •Stable API that won't change often
Keep Function Internal When:
- •Implementation detail that may change
- •Only used within package
- •Complex implementation helpers
- •Would clutter user-facing API
See internal-vs-exported.md for examples.
Testing Strategy
Testing Levels
| Level | Purpose | Example |
|---|---|---|
| Unit tests | Individual functions | Edge cases, error handling |
| Integration tests | Workflow combinations | End-to-end pipelines |
| Property-based tests | Invariants | Function properties hold |
See testing-patterns.md for examples.
Documentation Priorities
Must Document:
- •All exported functions
- •Complex algorithms or formulas
- •Non-obvious parameter interactions
- •Examples of typical usage
Can Skip Documentation:
- •Simple internal helpers
- •Obvious parameter meanings
- •Functions that just call other functions
source: Sarah Johnson's gist https://gist.github.com/sj-io/3828d64d0969f2a0f05297e59e6c15ad