<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/goodpractice-1-0-2-on-cran/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.mango-solutions.com/blog/goodpractice-1-0-2-on-cran"> Mango Solutions</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p> <img sizes="100vw" src="https://i0.wp.com/www.mango-solutions.com/blog/images/3/6/3/d/a/363dad088177bbc55391ad9d4ec67ee1c12ebba5-hannah-blog.png?w=456&ssl=1" data-recalc-dims="1"></p>
<h5>Hannah Frick, Data Scientist</h5>
<p>We are excited to annouce that the <strong>goodpractice</strong> package is now<br>
available on <a rel="nofollow" href="https://cran.r-project.org/package=goodpractice" target="_blank">CRAN</a>. The package gives advice about good practices when building R packages. Advice<br>
includes functions and syntax to avoid, package structure, code<br>
complexity, code formatting, etc.</p>
<p>You can install the CRAN version via</p>
<pre><code>install.packages(&quot;goodpractice&quot;)</code></pre>
<h2>Building R packages</h2>
<p>Building an R package is a great way of encapsulating code,<br>
documentation and data in a single testable and easily distributable<br>
unit.</p>
<p>For a package to be distributed via CRAN, it needs to pass a set of<br>
checks implemented in <code>R CMD check</code>, such as: Is there minimal<br>
documentation, e.g., are all arguments of exported functions documented?<br>
Are all dependencies declared?</p>
<p>These checks are helpful in developing a solid R package but they don’t<br>
check for several other good practices. For example, a package does not<br>
need to contain any tests but is it good practice to include some.<br>
Following a coding standard helps readability. Avoiding overly complex<br>
functions reduces the risk of bugs. Including an URL for bug reports<br>
lets people more easily report bugs if they find any.</p>
<h3>What the <strong>goodpractice</strong> package does</h3>
<p>Tools for automatically checking several of the above mentioned aspects<br>
already exist and the <strong>goodpractice</strong> package bundles the checks from<br>
<a rel="nofollow" href="https://cran.r-project.org/package=rcmdcheck" target="_blank"><strong>rcmdcheck</strong></a> with code<br>
coverage through the <a rel="nofollow" href="https://cran.r-project.org/package=covr" target="_blank"><strong>covr</strong></a><br>
package, source code linting via the<br>
<a rel="nofollow" href="https://cran.r-project.org/package=lintr" target="_blank"><strong>lintr</strong></a> package and<br>
cyclompatic complexity via the<br>
<a rel="nofollow" href="https://cran.r-project.org/package=cyclocomp" target="_blank"><strong>cyclocomp</strong></a> package<br>
and augments it with some further checks on good practice for R package<br>
development such as avoiding <code>T</code> and <code>F</code> in favour of <code>TRUE</code> and<br>
<code>FALSE</code>. It provides advice on which practices to follow and which to<br>
avoid.</p>
<p>You can use <strong>goodpractice</strong> checks as a reminder for you and your<br>
collegues – and if you have custom checks to run, you can make<br>
<strong>goodpractice</strong> run those as well!</p>
<h2>How to use <strong>goodpractice</strong></h2>
<p>The main fuction <code>goodpractice()</code> (and its alias <code>gp()</code>) takes the path<br>
to the source code of a package as its first argument. The<br>
<strong>goodpractice</strong> package contains the source for a simple package which<br>
violates some good practices. We’ll use this for the examples.</p>
<pre><code>library(goodpractice)

# get path to example package
pkg_path &lt;- system.file(&quot;bad1&quot;, package = &quot;goodpractice&quot;)

# run gp() on it
g &lt;- gp(pkg_path)
#> Preparing: covr
#> Warning in MYPREPS[[prep]](state, quiet = quiet): Prep step for test
#> coverage failed.
#> Preparing: cyclocomp
#> Skipping 2 packages ahead of CRAN: callr, remotes
#> Installing 1 packages: stringr
#> 
#>   There is a binary version available but the source version is
#>   later:
#>         binary source needs_compilation
#> stringr  1.3.0  1.3.1             FALSE
#> installing the source package 'stringr'
#> Preparing: description
#> Preparing: lintr
#> Preparing: namespace
#> Preparing: rcmdcheck

# show the result
g
#> ── GP badpackage ──────────────────────────────────────────────────────────
#> 
#> It is good practice to
#> 
#>   ✖ not use &quot;Depends&quot; in DESCRIPTION, as it can cause name
#>     clashes, and poor interaction with other packages. Use
#>     &quot;Imports&quot; instead.
#>   ✖ omit &quot;Date&quot; in DESCRIPTION. It is not required and it gets
#>     invalid quite often. A build date will be added to the package
#>     when you perform `R CMD build` on it.
#>   ✖ add a &quot;URL&quot; field to DESCRIPTION. It helps users find
#>     information about your package online. If your package does
#>     not have a homepage, add an URL to GitHub, or the CRAN package
#>     package page.
#>   ✖ add a &quot;BugReports&quot; field to DESCRIPTION, and point it to a bug
#>     tracker. Many online code hosting services provide bug
#>     trackers for free, https://github.com, https://gitlab.com,
#>     etc.
#>   ✖ omit trailing semicolons from code lines. They are not needed
#>     and most R coding standards forbid them
#> 
#>     R/semicolons.R:4:30
#>     R/semicolons.R:5:29
#>     R/semicolons.R:9:38
#> 
#>   ✖ not import packages as a whole, as this can cause name clashes
#>     between the imported packages. Instead, import only the
#>     specific functions you need.
#>   ✖ fix this R CMD check ERROR: VignetteBuilder package not
#>     declared: ‘knitr’ See section ‘The DESCRIPTION file’ in the
#>     ‘Writing R Extensions’ manual.
#>   ✖ avoid 'T' and 'F', as they are just variables which are set to
#>     the logicals 'TRUE' and 'FALSE' by default, but are not
#>     reserved words and hence can be overwritten by the user.
#>     Hence, one should always use 'TRUE' and 'FALSE' for the
#>     logicals.
#> 
#>     R/tf.R:NA:NA
#>     R/tf.R:NA:NA
#>     R/tf.R:NA:NA
#>     R/tf.R:NA:NA
#>     R/tf.R:NA:NA
#>     ... and 4 more lines
#> 
#> ───────────────────────────────────────────────────────────────────────────</code></pre>
<p>So with this package, we’ve done a few things in the DESCRIPTION file<br>
for which there are reasons not to do them, have unnecessary trailing<br>
semicolons in the code and used <code>T</code> and <code>F</code> for <code>TRUE</code> and <code>FALSE</code>. The<br>
output of <code>gp()</code> will tell you what isn’t considered good practice out of what you have already written. If that is in the R code itself, it will also point you to the location of your faux-pas. In general, the messages are supposed to not only point out to<br>
you <em>what</em> you might want to avoid but also <em>why</em>.</p>
<h3>Custom checks</h3>
<p>The above example tries to run all 230 checks available, to see the full<br>
list use <code>all_checks()</code>. You can customise the set of checks run by<br>
selecting only those default checks you are intersted in and by adding<br>
your own checks.</p>
<p>If you only want to run a subset of the checks, e.g., just the check on<br>
the URL field in the DESCRIPTION, you can specify the checks by name:</p>
<pre><code># what is the name of the check?
grep(&quot;url&quot;, all_checks(), value = TRUE)
#> [1] &quot;description_url&quot;

# run only this check
gp(pkg_path, checks = &quot;description_url&quot;)
#> Preparing: description
#> ── GP badpackage ──────────────────────────────────────────────────────────
#> 
#> It is good practice to
#> 
#>   ✖ add a &quot;URL&quot; field to DESCRIPTION. It helps users find
#>     information about your package online. If your package does
#>     not have a homepage, add an URL to GitHub, or the CRAN package
#>     package page.
#> ───────────────────────────────────────────────────────────────────────────</code></pre>
<p>Additional checks can be used in <code>gp()</code> via the <code>extra_checks</code> argument.<br>
This should be a named list of <code>check</code> objects as returned by the<br>
<code>make_check()</code> function.</p>
<pre><code># make a simple version of the T/F check
check_simple_tf &lt;- make_check(

  description = &quot;TRUE and FALSE is used, not T and F&quot;,
  gp = &quot;avoid 'T' and 'F', use 'TRUE' and 'FALSE' instead.&quot;,
  check = function(state) {
      length(tools::checkTnF(dir = state$path)) == 0
  }
)

gp(pkg_path, checks = c(&quot;description_url&quot;, &quot;simple_tf&quot;),
   extra_checks = list(simple_tf = check_simple_tf))
#> Preparing: description
#> ── GP badpackage ──────────────────────────────────────────────────────────
#> 
#> It is good practice to
#> 
#>   ✖ add a &quot;URL&quot; field to DESCRIPTION. It helps users find
#>     information about your package online. If your package does
#>     not have a homepage, add an URL to GitHub, or the CRAN package
#>     package page.
#>   ✖ avoid 'T' and 'F', use 'TRUE' and 'FALSE' instead.
#> ───────────────────────────────────────────────────────────────────────────</code></pre>
<p>For more details on creating custom checks, please see the vignette<br>
<a rel="nofollow" href="https://mangothecat.github.io/goodpractice/articles/custom_checks.html" target="_blank">Custom<br>
Checks</a>.</p>
<h2>Acknowledgements</h2>
<p>This package was written by <a rel="nofollow" href="https://github.com/gaborcsardi" target="_blank">Gábor<br>
Csárdi</a> with contributions by <a rel="nofollow" href="https://github.com/noamross" target="_blank">Noam<br>
Ross</a>, <a rel="nofollow" href="https://github.com/nfultz" target="_blank">Neal<br>
Fultz</a>, <a rel="nofollow" href="https://github.com/dougmet" target="_blank">Douglas<br>
Ashton</a>, <a rel="nofollow" href="https://github.com/LiNk-NY" target="_blank">Marcel<br>
Ramos</a>, <a rel="nofollow" href="https://github.com/jsta" target="_blank">Joseph<br>
Stachelek</a>, and<br>
<a rel="nofollow" href="https://github.com/hfrick" target="_blank">myself</a>. Special thanks for the input and<br>
feedback to the <a rel="nofollow" href="https://ropensci.org/" target="_blank">rOpenSci</a> leadership team and<br>
community as well as everybody who opened<br>
<a rel="nofollow" href="https://github.com/MangoTheCat/goodpractice/issues" target="_blank">issues</a>!</p>
<h2>Feedback</h2>
<p>If you have any feedback, please consider opening an issue on<br>
<a rel="nofollow" href="https://github.com/MangoTheCat/goodpractice/issues" target="_blank">GitHub</a>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://www.mango-solutions.com/blog/goodpractice-1-0-2-on-cran"> Mango Solutions</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/V5zNx9VT9ek" height="1"></a></div>