Personal R package development preferences for code style, documentation conventions, and workflow. Complements Posit r-lib skills with specific style choices for minimal comments and neuroimaging package patterns.
Specific style preferences and workflow choices for R package development. Use alongside Posit testing-r-packages for comprehensive guidance.
Functions and variables should be named clearly enough that comments are unnecessary:
# Good: Self-explanatory without comments
calculate_mean_cortical_thickness <- function(surface_data,
region_labels,
exclude_medial_wall = TRUE) {
valid_vertices <- identify_valid_vertices(surface_data, exclude_medial_wall)
regional_means <- compute_regional_means(surface_data, region_labels, valid_vertices)
regional_means
}
# Bad: Needs comments to explain
calc_mct <- function(sd, rl, emw = TRUE) {
# Get valid vertices
vv <- get_vv(sd, emw)
# Calculate means
rm <- calc_rm(sd, rl, vv)
rm
}
# Exception: Comments allowed for workarounds
process_freesurfer_annotation <- function(annot_file) {
# WORKAROUND: FreeSurfer annot files have non-standard header format
# that readBin() misinterprets. Skip first 4 bytes manually.
raw_data <- readBin(annot_file, "raw", n = file.size(annot_file))
data_without_header <- raw_data[-(1:4)]
parse_annotation_data(data_without_header)
}
When comments ARE acceptable:
# Good: Consistent verb-noun pattern
read_freesurfer_surface()
read_freesurfer_annotation()
read_freesurfer_curv()
write_freesurfer_surface()
write_freesurfer_annotation()
# Bad: Inconsistent patterns
fs_read_surface()
read_annot_freesurfer()
freesurfer_curv_read()
Naming conventions:
read_*write_*transform_*, convert_*calculate_*, compute_*is_*, has_*, validate_*Focus on what users need, not implementation details:
# Good: User-focused documentation
#' Read FreeSurfer surface file
#'
#' Reads surface geometry from FreeSurfer format files. Supports both
#' ASCII and binary formats automatically.
#'
#' @param filepath Path to FreeSurfer surface file
#'
#' @return List with two elements:
#' * `vertices` - Nx3 matrix of vertex coordinates
#' * `faces` - Mx3 matrix of face indices (1-indexed)
#'
#' @examples
#' surf <- read_freesurfer_surface("lh.pial")
#' n_vertices <- nrow(surf$vertices)
#'
#' @family freesurfer-io
#' @export
read_freesurfer_surface <- function(filepath) {
# Implementation
}
# Bad: Over-documented with implementation details
#' Read FreeSurfer surface file
#'
#' This function reads a FreeSurfer surface file by first checking
#' if it's binary or ASCII format, then parsing the header to get
#' the number of vertices and faces, and finally reading the data
#' into R matrices using optimized C++ code via Rcpp.
#'
#' The function performs the following steps:
#' 1. Opens file connection
#' 2. Reads magic number
#' 3. Determines format
#' ...
#' [Users don't need implementation details in documentation]
Prioritize realistic examples over abstract descriptions:
# Good: Practical workflow example
#' Calculate cortical thickness statistics
#'
#' @param thickness_file Path to thickness data
#' @param parcellation_file Path to parcellation
#'
#' @examples
#' # Typical neuroimaging workflow
#' thickness <- read_freesurfer_curv("lh.thickness")
#' parcellation <- read_freesurfer_annotation("lh.aparc.annot")
#'
#' # Get mean thickness per region
#' regional_stats <- calculate_regional_thickness(
#' thickness,
#' parcellation,
#' exclude_unknown = TRUE
#' )
#'
#' # Extract specific regions of interest
#' motor_thickness <- regional_stats$thickness[
#' regional_stats$region == "precentral"
#' ]
Vignettes should use skill codex-voice and markdown.
See the r-testing skill for all testing conventions.
NEWS.md should contain information on what has changed in the R-package architecture, not other repository changes. Organize by minor and major (breaking) changes.
# Typical development workflow