knitr::opts_chunk$set(echo = TRUE, eval = FALSE)
The overall goal of the style guide:
Ultimately, the style guide should help us
General principles for deciding the name of a package:
.
) to indicate a collection of extension packages.
Examples include the "gamlss" packages and the "future" packages.Note that the package name and the product name can be stylized differently. Example: tensorflow vs. TensorFlow.
All user-facing interactions should have a functional API.
Function names, argument names, and variable names should use snake_case
.
# Good gs_design_ahr <- function(enroll_rates = ...) {} # Bad gsDesignAHR <- function(enrollRates = ...) {}
This rule also applies to the S3 or R7 method names and argument names,
as they are inherently, functions.
One should still follow the S3 convention to use dot (.
) to
connect the method name and class name.
# Good as_gt.gsDesign <- function(...) {} # Bad as.gt.gsDesign <- function(...) {}
Object-oriented API should be selectively used for low-level abstractions and limited cases in user-facing interactions when appropriate.
Class names defined under an OOP system, for example, S3 or R7,
should use UpperCamelCase
.
This rule intends to indicate the "function" is a class constructor, instead of a (regular) exported or internal function and follows the conventions in R6.
The input argument names and variable names should still use snake_case
.
# Good RangedDoubleOrNULL <- new_class( "RangedDoubleOrNULL", properties = list( value = class_any, min = class_double, max = class_double, min_closed = class_logical, max_closed = class_logical ), ... ) # Bad ranged_double_or_null <- new_class( "ranged_double_or_null", properties = list( value = class_any, min = class_double, max = class_double, min_closed = class_logical, max_closed = class_logical ), ... )
Arguments should be arranged in the order of data, descriptors, details.
This style makes it natural to consistently create chainable operations that form a workflow under either a functional API or object-oriented API, with minimal surprises.
# Functional API design <- create_design(enroll_rates, fail_rates, ...) design |> do_compute_1(detail_1 = ...) |> do_compute_2(detail_2 = ...)
# Object-oriented API design <- Design(enroll_rates, fail_rates, ...) design$do_compute_1(detail_1 = ...)$do_compute_2(detail_2 = ...)
This suggests that if the "data" argument requires multiple inputs, create another function to bundle them as a single object and pass it to the function of interest.
Required arguments should not have a default value. In contrast, optional arguments should have a default value.
Use lower case abbreviations or snake_case
for the enumerated type arguments.
# Bad f <- function(method = c("AHR", "WLR", ...)) {} # Good f <- function(method = c("ahr", "wlr", ...)) {}
# Bad f <- function(approx = c("event driven", "asymptotic", "generalized schoenfeld", ...)) {} # Good f <- function(approx = c("event_driven", "asymptotic", "generalized_schoenfeld", ...)) {}
The reasoning behind this: the strings are used together with function names and argument names, using snake_case
would create a visual consistency.
Whenever possible, set the default value of an enumerated type input in the argument definition. See enumerate possible options.
R code should be formatted using styler with the default tidyverse style.
C/C++ code should be formatted using clang-format. This is doable via the Visual Studio Code C++ extension.
The code formatting can be automatically checked in CI/CD workflows.
The rules should be enforced via a CI/CD workflow for code linting.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.