Skip to content

Commit

Permalink
add scope and references to openstatsguide (#139)
Browse files Browse the repository at this point in the history
* restructure by adding scope and references section

* start with references

* finish first references batch
  • Loading branch information
danielinteractive authored Jun 1, 2024
1 parent 8714c46 commit 80f7ea6
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 74 deletions.
19 changes: 19 additions & 0 deletions computational-statistics.csl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" version="1.0" default-locale="en-US">
<!-- Generated with https://github.com/citation-style-language/utilities/tree/master/generate_dependent_styles/data/springer -->
<info>
<title>Computational Statistics</title>
<title-short>Comput Stat</title-short>
<id>http://www.zotero.org/styles/computational-statistics</id>
<link href="http://www.zotero.org/styles/computational-statistics" rel="self"/>
<link href="http://www.zotero.org/styles/springer-basic-author-date" rel="independent-parent"/>
<link href="http://www.springer.com/cda/content/document/cda_downloaddocument/Key_Style_Points_1.0.pdf" rel="documentation"/>
<link href="http://www.springer.com/cda/content/document/cda_downloaddocument/manuscript-guidelines-1.0.pdf" rel="documentation"/>
<category citation-format="author-date"/>
<category field="science"/>
<issn>0943-4062</issn>
<eissn>1613-9658</eissn>
<updated>2014-05-18T01:40:32+00:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
</style>
166 changes: 92 additions & 74 deletions guide.qmd
Original file line number Diff line number Diff line change
@@ -1,45 +1,61 @@
---
title: "openstatsguide"
subtitle: "version 0.0-1"
date: "10 Mar 2024"
subtitle: "Minimum Viable Good Practices for High Quality Statistical Software Packages"
author: "0.0-2"
author-title: "Version"
date: "31 May 2024"
bibliography: references.bib
nocite: |
@*
csl: computational-statistics.csl
---

*Note: This is a beta release of "openstatsguide" to accompany the useR 2024 abstract submission. It is not yet available interactively via the openstatsware.org website and will undergo further expert input before publication of the first release version 0.1.*

We encourage developers of statistical software packages to follow this minimum set of good practices. They can be easily remembered with the mnemonic bridge sentence:
# Scope

We encourage developers of statistical software packages to follow this minimum set of good practices around:

> "**D**ocumentation, **V**ignettes, **T**ests, **F**unctions, **S**tyle, **L**ife cycle"
These keywords can be easily remembered with the mnemonic bridge sentence:

> "**D**evelopers **V**alue **T**ests **F**or **S**oftware **L**ongevity"
While these principles are rather generic, we focus on functional programming languages and give links to implementations in R, Python and Julia.
While the recommendations are rather generic, we focus on functional programming languages and give links to implementations in R, Python and Julia.

This guide primarily addresses developers of statistical packages. Users interested in assessing the quality of existing statistical packages will find complementary "validation" focused resources valuable, as listed in [References](#references).

# Recommendations

```{r echo=FALSE}
glue_or_drop <- function(doc, img) {
if (identical(doc, "")) {
NULL
} else {
htmltools::tags$td(
htmltools::tags$details(
htmltools::tags$summary(
htmltools::tags$img(src = img, height = 20)
),
doc
)
)
}
if (identical(doc, "")) {
NULL
} else {
htmltools::tags$td(
htmltools::tags$details(
htmltools::tags$summary(
htmltools::tags$img(src = img, height = 20)
),
doc
)
)
}
}
guide_table <- function(r = "", python = "", julia = "") {
contents <- htmltools::tags$html(
glue_or_drop(r, "https://www.r-project.org/logo/Rlogo.svg"),
glue_or_drop(python, "https://s3.dualstack.us-east-2.amazonaws.com/pythondotorg-assets/media/files/python-logo-only.svg"),
glue_or_drop(julia, "https://raw.githubusercontent.com/JuliaLang/julia-logo-graphics/master/images/julia-dots.svg"),
sep = "\n"
)
htmltools::tags$table(
style = htmltools::css(
width = '100%'
),
htmltools::tags$tbody(contents)
)
contents <- htmltools::tags$html(
glue_or_drop(r, "https://www.r-project.org/logo/Rlogo.svg"),
glue_or_drop(python, "https://s3.dualstack.us-east-2.amazonaws.com/pythondotorg-assets/media/files/python-logo-only.svg"),
glue_or_drop(julia, "https://raw.githubusercontent.com/JuliaLang/julia-logo-graphics/master/images/julia-dots.svg"),
sep = "\n"
)
htmltools::tags$table(
style = htmltools::css(
width = "100%"
),
htmltools::tags$tbody(contents)
)
}
```

Expand All @@ -50,11 +66,11 @@ Documentation is important for both users and developers to understand all objec
1. Use **in-line comments** next to functions, classes and other objects to generate their corresponding documentation.

```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("roxygen2", href = "https://roxygen2.r-lib.org/"),
python = htmltools::a("docstrings", href = "https://peps.python.org/pep-0257/"),
julia = htmltools::a("docstrings", href = "https://docs.julialang.org/en/v1/manual/documentation/")
)
guide_table(
r = htmltools::a("roxygen2", href = "https://roxygen2.r-lib.org/"),
python = htmltools::a("docstrings", href = "https://peps.python.org/pep-0257/"),
julia = htmltools::a("docstrings", href = "https://docs.julialang.org/en/v1/manual/documentation/")
)
```
2. Do also **document internal functions** and classes for maintenance by future developers.
Expand All @@ -72,11 +88,11 @@ Vignettes are documents that complement the object documentation by providing a
3. Host your vignettes on a **dedicated website**, which allows users to read the vignettes without installing the package, and simplifies citing the vignettes in other publications.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("pkgdown", href = "https://pkgdown.r-lib.org/"),
python = htmltools::a("Sphinx", href = "https://www.sphinx-doc.org/en/master/"),
julia = htmltools::a("Documenter", href = "https://documenter.juliadocs.org/")
)
guide_table(
r = htmltools::a("pkgdown", href = "https://pkgdown.r-lib.org/"),
python = htmltools::a("Sphinx", href = "https://www.sphinx-doc.org/en/master/"),
julia = htmltools::a("Documenter", href = "https://documenter.juliadocs.org/")
)
```
## Tests
Expand All @@ -88,21 +104,21 @@ Tests are a fundamental safety net and development tool to ensure that your pack
2. Write **functional tests** for all user facing functionality ("black box" testing). These tests ensure that the user API is stable when refactoring internal code.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("testthat", href = "https://testthat.r-lib.org/"),
python = htmltools::a("pytest", href = "https://pytest.org/"),
julia = htmltools::a("Test", href = "https://docs.julialang.org/en/v1/stdlib/Test/")
)
guide_table(
r = htmltools::a("testthat", href = "https://testthat.r-lib.org/"),
python = htmltools::a("pytest", href = "https://pytest.org/"),
julia = htmltools::a("Test", href = "https://docs.julialang.org/en/v1/stdlib/Test/")
)
```
3. In addition, ensure a **good coverage** of your code with your tests as a final check, but only after having unit and functional tests on all levels of the code.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("covr", href = "https://covr.r-lib.org/"),
python = htmltools::a("Coverage.py", href = "https://coverage.readthedocs.io/"),
julia = htmltools::a("Coverage.jl", href = "https://github.com/JuliaCI/Coverage.jl")
)
guide_table(
r = htmltools::a("covr", href = "https://covr.r-lib.org/"),
python = htmltools::a("Coverage.py", href = "https://coverage.readthedocs.io/"),
julia = htmltools::a("Coverage.jl", href = "https://github.com/JuliaCI/Coverage.jl")
)
```
## Functions
Expand All @@ -114,21 +130,21 @@ Function definitions should be short, simple and enforce argument types with ass
2. Use **type hints** or types to explain to the user which argument of the function expects which type of input.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("roxytypes", href = "https://openpharma.github.io/roxytypes/"),
python = htmltools::a("typing", href = "https://docs.python.org/3/library/typing.html"),
julia = htmltools::a("types", href = "https://docs.julialang.org/en/v1/manual/types/")
)
guide_table(
r = htmltools::a("roxytypes", href = "https://openpharma.github.io/roxytypes/"),
python = htmltools::a("typing", href = "https://docs.python.org/3/library/typing.html"),
julia = htmltools::a("types", href = "https://docs.julialang.org/en/v1/manual/types/")
)
```
3. Enforce types and other expected properties of function arguments with **assertions**, which give an early and readable error message to the user instead of failing function code downstream in a less explicable way.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("checkmate", href = "https://mllg.github.io/checkmate/"),
python = htmltools::a("assertpy", href = "https://pypi.org/project/assertpy/"),
julia = htmltools::a("ArgCheck.jl", href = "https://github.com/jw3126/ArgCheck.jl")
)
guide_table(
r = htmltools::a("checkmate", href = "https://mllg.github.io/checkmate/"),
python = htmltools::a("assertpy", href = "https://pypi.org/project/assertpy/"),
julia = htmltools::a("ArgCheck.jl", href = "https://github.com/jw3126/ArgCheck.jl")
)
```
## Style
Expand All @@ -140,21 +156,21 @@ A consistent and readable code style that is language idiomatic should be used a
2. Use a **formatting tool** to automatically implement a consistent and readable code format.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("styler", href = "https://styler.r-lib.org/"),
python = htmltools::a("Autopep8", href = "https://pypi.org/project/autopep8/"),
julia = htmltools::a("JuliaFormatter.jl", href = "https://domluna.github.io/JuliaFormatter.jl/")
)
guide_table(
r = htmltools::a("styler", href = "https://styler.r-lib.org/"),
python = htmltools::a("Autopep8", href = "https://pypi.org/project/autopep8/"),
julia = htmltools::a("JuliaFormatter.jl", href = "https://domluna.github.io/JuliaFormatter.jl/")
)
```
3. Use a **style checking** tool to enforce a consistent and readable code style.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::a("lintr", href = "https://lintr.r-lib.org/"),
python = htmltools::a("Pylint", href = "https://pypi.org/project/pylint/"),
julia = htmltools::p("Enabled in VScode via", htmltools::a("StaticLint.jl", href = "https://github.com/julia-vscode/StaticLint.jl"))
)
guide_table(
r = htmltools::a("lintr", href = "https://lintr.r-lib.org/"),
python = htmltools::a("Pylint", href = "https://pypi.org/project/pylint/"),
julia = htmltools::p("Enabled in VScode via", htmltools::a("StaticLint.jl", href = "https://github.com/julia-vscode/StaticLint.jl"))
)
```
## Life cycle
Expand All @@ -166,15 +182,17 @@ Life cycle management is simplified by reducing dependencies, and should compris
2. Give clear information to users about changes in the package API via maintaining the **change log** and first **deprecating functionality** before removing it.
```{r results="asis", echo=FALSE}
guide_table(
r = htmltools::p(
guide_table(
r = htmltools::p(
htmltools::a("lifecycle", href = "https://cran.r-project.org/web/packages/lifecycle/index.html"),
htmltools::a("fledge", href = "https://fledge.cynkra.com/")
),
python = htmltools::a("deprecation", href = "https://deprecation.readthedocs.io/"),
julia = htmltools::a("workflow", href = "https://invenia.github.io/blog/2022/06/17/deprecating-in-julia/")
)
),
python = htmltools::a("deprecation", href = "https://deprecation.readthedocs.io/"),
julia = htmltools::a("workflow", href = "https://invenia.github.io/blog/2022/06/17/deprecating-in-julia/")
)
```
3. Use a **central repository** for version control, collecting and resolving issues, and managing releases. Include the publication of a **contributing guide** to help onboard new developers and enable community contributions.
# References
110 changes: 110 additions & 0 deletions references.bib
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
@software{ropensci_statsoftware_2021,
author = {Mark Padgham and
Maëlle Salmon and
Noam Ross and
Jakub Nowosad and
Rich FitzJohn and
Yilong Zhang and
Christoph Sax and
Francisco Rodriguez-Sanchez and
François Briatte and
Leonardo Collado-Torres},
title = {{rOpenSci} Statistical Software Peer Review},
month = oct,
year = 2021,
publisher = {Zenodo},
version = {v0.1.0},
doi = {10.5281/zenodo.5556756},
url = {https://doi.org/10.5281/zenodo.5556756}
}

@software{ropensci_devguide_2024,
author = {{rOpenSci} and
Anderson, Brooke and
Chamberlain, Scott and
DeCicco, Laura and
Gustavsen, Julia and
Krystalli, Anna and
Lepore, Mauro and
Mullen, Lincoln and
Ram, Karthik and
Ross, Noam and
Salmon, Maëlle and
Vidoni, Melina and
Riederer, Emily and
Sparks, Adam and
Hollister, Jeff},
title = {{rOpenSci Packages: Development, Maintenance, and
Peer Review}},
month = mar,
year = 2024,
publisher = {Zenodo},
version = {0.9.0},
doi = {10.5281/zenodo.10797633},
url = {https://doi.org/10.5281/zenodo.10797633}
}

@techreport{pharmar_2020,
author = {Juliane Manitz and Andy Nicholls and Paulo Bargo and Doug Kelkhoff and Yilong Zhang and Lyn Taylor and Joe
Rickert and Marly Gotti and Keaven M Anderson},
title = {A Risk-based approach for assessing {R} package accuracy within a validated infrastructure},
year = {2020},
url = {https://www.pharmar.org/white-paper/}
}

@manual{usethis_2024,
title = {{usethis}: Automate Package and Project Setup},
author = {Hadley Wickham and Jennifer Bryan and Malcolm Barrett and Andy Teucher},
year = {2024},
note = {R package version 2.2.3, https://github.com/r-lib/usethis},
url = {https://usethis.r-lib.org}
}

@book{wickham_2023,
title = {R Packages: Organize, Test, Document, and Share Your Code},
author = {Wickham, Hadley and Bryan, Jennifer},
year = {2023},
edition = {2},
publisher = {{O'Reilly Media, Inc.}},
url = {https://r-pkgs.org/}
}

@book{wickham_design,
title = {Tidy design principles},
author = {Wickham, Hadley},
url = {https://design.tidyverse.org/}
}

@book{carpentries_2023,
title = {A Software Carpentries lesson on {R} packaging},
author = {Rodriguez-Sanchez, Pablo and Vreede, Barbara and de Boer, Lieke},
year = {2023},
url = {https://carpentries-incubator.github.io/lesson-R-packaging/}
}

@misc{gswe4rp_2024,
author = {Sabanés Bové, Daniel and Pahlke, Friedrich and Kunzmann, Kevin and Bean, Andrew and
Kelkhoff, Doug and Boileau, Philippe and
Li, Liming and Zhu, Joe and Li, Shuang and Widmer, Lukas A. and Mayer, Michael},
title = {Good Software Engineering Practice for {R} Packages},
year = {2024},
url = {https://rconis.github.io/workshop-r-swe-zrh/}
}

@misc{validation_2024,
author = {{Wikipedia contributors}},
title = {Software verification and validation --- {Wikipedia}{,} The Free Encyclopedia},
year = {2024},
url = {https://en.wikipedia.org/w/index.php?title=Software_verification_and_validation&oldid=1220844793},
note = {[Online; accessed 31-May-2024]}
}

@misc{sabanes_2023,
title = {Improving Software Engineering in Biostatistics: Challenges and Opportunities},
author = {Sabanés Bové, Daniel and Heidi Seibold and Anne-Laure Boulesteix and Juliane Manitz and Alessandro Gasparini and Burak K. Guünhan and Oliver Boix and Armin Schuüler and Sven Fillinger and Sven Nahnsen and Anna E. Jacob and Thomas Jaki},
year = {2023},
eprint = {2301.11791},
archiveprefix = {arXiv},
primaryclass = {stat.CO},
url = {https://arxiv.org/abs/2301.11791}
}

0 comments on commit 80f7ea6

Please sign in to comment.