Beautiful code, because we’re worth it!

Maëlle Salmon

Hello !

  • Why write beautiful code?
  • How do I do it? Tips and tricks

🔗 https://jolicode.netlify.app/

Coffee

Picture by Leonardo Luz on Pexels.

Who am I?

  • rOpenSci (dev guide, newsletter, babeldown and babelquarto packages for multilingual publishing…)

  • Other package development experience, for instance contributing to pkgdown; igraph; glitter, a package to write SPARQL queries; etc. I also created saperlipopette, a package for Git training

Why write beautiful code

Easy-to-read, easy-to-follow code.

Your code is executed by machines, but read by humans who will check and build upon it.

Mascara

Picture by Shiny Diamond on Pexels.

Well-proportioned code

  • Regular spacing between elements

  • Not too wide

  • Not too long: paragraphs, existing and home-made functions

  • Not too stained: just the right amount of comments

Regular spacing

😱

starwars%>%
  select(name,height, mass,homeworld) %>%
  mutate(
    mass= NULL,
    height =height *0.0328084 # convert to feet
  )

Regular spacing

😌

starwars %>%
  select(name, height, mass, homeworld) %>%
  mutate(
    mass = NULL,
    height = height * 0.0328084 # convert to feet
  )

Regular spacing

Follow rules, always the same rules, the same rules as your friends. Example: https://style.tidyverse.org/ How do you do it?

  • You get used to it.

  • The package {styler} does it automatically! Demo.

  • In RStudio IDE, Ctrl+I for indentation.

Not too wide

No more than 80 characters per line, or something similar.

lintr can warn you! Demo

Also an RStudio setting (Code > Display > Show Margin).

Code that’s not too long: paragraphs

As in prose, one paragraph for one idea.

head <- collect_metadata(website)
head_string <- stringify(head)

body <- create_content(website)
body_string <- stringify(body)

Code that’s not too long: homemade functions

Keep the main function body not too long by outsourcing things to well-named functions.

create_content <- function(website) {
  title <- create_title(website)
  page <- create_page(website)
  combine_elements(title = title, page = page)
}

Aside: navigating between functions in RStudio IDE

Demo!

  • Enter + click

  • Search bar

Code that’s not too long: don’t reinvent the wheel!

For example: modifyList()

default_values <- list(a = 1, b = 2)
options <- list(b = 56)
temporary_list <- default_values
temporary_list[names(options)] <- options
options <- temporary_list

options
$a
[1] 1

$b
[1] 56

Code that’s not too long: don’t reinvent the wheel!

Here’s an example: modifyList()

default_values <- list(a = 1, b = 2)
options <- list(b = 56)
options <- modifyList(default_values, options)
options
$a
[1] 1

$b
[1] 56

How to extend your R vocabulary

As few comments as possible

I used to think…

# starwars data
starwars %>%
  # select name and mass
  select(name, mass) %>%
  mutate(
    # add mass2 as double of mass
    mass2 = mass * 2,
    # add mass2_squareed as squared mass2
    mass2_squared = mass2 * mass2
  )

It’s pointless and boring to write, and it can even be dangerous!

As few comments as possible

One comment = like an alert!

If there are too many, we stop reading them.

Feel the urge to add a comment? Take care!

  • Change the name of a variable rather than comment on what it is.

  • Change the structure of complicated code rather than comment on what it does.

Explanatory variables or functions

Meh:

# Use string if x is not missing and a non empty string
if (!is.na(x) && nzchar(x)) {
  use_string(x)
}

Explanatory variables or functions

Yippee:

x_is_not_empty_string <- (!is.na(x) && nzchar(x))
if (x_is_not_empty_string) {
  use_string(x)
}

Possible to define a function rather than a variable, if needed.

Good comments

  • Documenting functions with roxygen2 ;

  • Things you’d like to point out to a code reviewer, such as # This query can not be done via GraphQL, so have to use v3 REST API

  • Comments that provide a table of contents. Demo.

Well-proportioned code

  • Even spacing between elements

  • Not too wide

  • Not too long: paragraphs, existing and home-made functions

  • Not too stained: just the right amount of comments

Clear code

  • Self-explanatory names.

  • Logic tips: early return(), switch().

  • Less code.

Self-explanatory names

  • Follow fashion.

  • Felienne Hermans advises choosing the concepts that go into the name, the words to say it, then putting them together.

  • “The greater the distance between a name’s declaration and its uses, the longer the name should be” (Andrew Gerrand).

  • It’s clear if the person reviewing your code agrees. 😉

Renaming functions

You can even rename existing functions if that clarifies things.

# In utils.R
remove_extension <- function(path) {
  tools::file_path_sans_ext(path)
}

# In other scripts
remove_extension(path)

Simplify logic: early return()

Meh

do_thing <- function(x) {
  if (is.na(x)) {
    NA
  } else {
    x + 1
  }
}

Simplifying logic: early return()

Better!

do_thing <- function(x) {
  if (is.na(x)) {
    return(NA)
  } 
  
  x + 1
}

Simplifying logic: switch()

Meh

if (type == "mean") {
  mean(x)
} else if (type == "median") {
  median(x)
} else if (type == "trimmed") {
  mean(x, trim = .1)
}

Simplifying logic: switch()

Better!

switch(type,
       mean = mean(x),
       median = median(x),
       trimmed = mean(x, trim = .1))

You can even specify a default value (or error!) for other values of the first argument.

Less code, fewer problems!

  • Be strict about what scope.

  • Use trusted external dependencies.

Clear code

  • Self-explanatory names.

  • Logic tips: return() early, switch().

  • Less code.

How can you improve your code?

  • Spring cleaning ;

  • lintr ;

  • Human review.

Spring cleaning

lintr, a fantastic package

Let’s take a look at the documentation!

https://lintr.r-lib.org/reference/index.html

Human review

Read your colleagues’ code and vice versa! https://code-review.tidyverse.org/

Peer review of packages at rOpenSci https://ropensci.org/software-review/

Conclusion

The beauty and clarity of code are as important as its performance.

Easier to check and maintain!

Need for upkeep, maintenance.

References / additional resources

Thanks a lot!

To all of you and to Yani!

https://stylish-code.netlify.app/

Thank you

Picture by Ann H on Pexels.