# install.packages('pak')
::pak('mjfrigaard/shinypak') pak
31 Code style
βWeβre in the business of keystrokes and neuronsβ
During development, it can be challenging to keep the code in your app-package clean and perfectly formatted. Fortunately, the R ecosystem has some excellent tools for making your code functional and easy to read.
31.1 Code style and formatting
The lintr
and styler
packages in R serve related but distinct purposes and have different focuses in their functionality. The primary difference between lintr
and styler
is that styler
can automatically fix any stylistic issues it identifies in your code (rather than just reporting them).
Launch app with the shinypak
package:
launch('31_style')
31.1.1 lintr
lintr
is a static code analysis tool used to identify syntax errors, semantic issues, and violations of stylistic guidelines in your code. The package contains a list of βlintersβ for various potential problems and can be customized according to your needs. lintr is designed to help improve your codeβs quality and readability by generating reports in the βmarkersβ pane. Running lintr
wonβt automatically correct the identified issues (youβll need to fix the linting issues it reports manually).
31.1.2 styler
On the other hand, the purpose of styler
is to ensure consistency in the code formatting, which is crucial if youβre working in a team or contributing to open-source projects (like tidyverse
packages). The styler
package will change your codeβs format according to specified style guidelines. These changes include indentation, spaces, and line breaks that adhere to your style guidelines.
While there is some overlap (both packages can help enforce coding style guidelines), lintr
is a more general tool for code quality, spotting potential issues and bugs. At the same time, styler
focuses on code formatting and can automatically apply fixes. Many developers find combining both can help catch potential issues and ensure a consistent, readable coding style.
31.2 Checking your code
Iβve previously mentioned running devtools::check()
can be overkill for your app-package (especially if itβs not destined for CRAN). A nice alternative to check()
is the goodpractice
package..
goodpractice::gp()
inspects your package and prints any areas that might need βgood practiceβ advice:
library(goodpractice)
<- gp(path = ".")
pkg_checks pkg_checks
Preparing: description
Preparing: lintr
|====================================================================| 100%
Preparing: namespace
Preparing: rcmdcheck
ββ GP sap βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
It is good practice to
β add a "URL" 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 "BugReports" 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.
β avoid long code lines, it is bad for readability. Also, many people prefer
editor windows that are about 80 characters wide. Try make your lines
shorter than 80 characters
data-raw/tidy_movies.R:49:81
R/data.R:4:81
R/data.R:7:81
R/data.R:17:81
R/data.R:21:81
... and 13 more lines
β 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 NOTE: display_type: no visible binding for global
variable
β.rs.invokeShinyPaneViewerβ display_type: no visible binding for global
variable
β.rs.invokeShinyWindowExternalβ display_type: no visible binding for global
variable
β.rs.invokeShinyWindowViewerβ mod_scatter_display_server : <anonymous>: no
visible binding for global
variable βmoviesβ Undefined global functions or variables:
.rs.invokeShinyPaneViewer
.rs.invokeShinyWindowExternal
.rs.invokeShinyWindowViewer movies
We can also check specific components of our package by looking up the available checks in all_checks()
:
grep("import", x = all_checks(), value = TRUE)
[1] "no_import_package_as_a_whole"
[2] "rcmdcheck_undeclared_imports"
[3] "rcmdcheck_imports_not_imported_from"
[4] "rcmdcheck_depends_not_imported_from"
[5] "rcmdcheck_triple_colon_imported_objects_exist"
[6] "rcmdcheck_unexported_base_objects_imported"
[7] "rcmdcheck_unexported_objects_imported"
[8] "rcmdcheck_empty_importfrom_in_namespace"
All of the checks with the rcmdcheck_
prefix are part of the R CMD check
diagnostic, but goodpractice
comes with other checks that are good practices (even if youβre not submitting your package to CRAN).
For example, no_import_package_as_a_whole
checks the practice we covered in managing imports. If we pass the no_import_package_as_a_whole
check as a character vector to the checks
argument:
gp(path = ".", checks = 'no_import_package_as_a_whole')
Only this check is performed:
ββ GP sap βββββββββββββββββββββββββββββββββββββββββββββββββββ
It is good practice to
β not import packages as a whole, as this can cause name clashes between
the imported packages. Instead, import only the specific functions you need.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
31.3 Recap
This chapter covered an introduction to some tools and practices for improving and maintaining the quality of the code in your app-package. Maintaining code style and standards (lintr
and styler
) and performing thorough checks to adhere to best practices (goodpractice
) will ensure efficient and reliable development and deployment for your app.