Foto de Matheus Bertelli en Pexels.
La única forma de escribir buen código es escribir primero toneladas de código de mierda. Sentir vergüenza por el código malo te impide llegar al código bueno.
Presentaré una colección de cosas muy útiles que he aprendido en los últimos años.
Después de cada sección haré un resumen y te pediré que comentes.
Después, elige una cosa para mejorar en tu paquete.
Conoce al paquete cli
variable <- 42
cli::cli_alert_info("Set {.field parameter} to {.val {variable}}")
#> ℹ Set parameter to 42
¿Cómo controlar la verbosidad?
argumento en cada función 😩
cli_alert_info <- function(...) {
if (!getOption("usethis.quiet", default = FALSE)) {
cli::cli_alert_info(...)
}
}
Para leer más: https://ropensci.org/blog/2024/02/06/verbosity-control-packages/
🧰 ¿Hay mensajes en tu paquete que podrías mejorar?
Consejos sobre el contenido en el guía de estilo de tidyverse con ejemplos.
Interfaz con cli::cli_abort()
🧰 Revisa los mensajes de error de tu paquete (busca stop() y equivalentes). ¿Podrían mejorarse algunos de ellos aplicando la guía de la tidyverse?
Tal vez con AI: https://simonpcouch.github.io/chores/reference/cli_helper.html
Documenta el tipo de argumento.
Comprueba los argumentos. rlang::arg_match() por ejemplo.
Más información: Comprobar las entradas de tus funciones en R por Hugo Gruson, Sam Abbott, Carl Pearson.
🧰 ¿Tu paquete documenta y valida los argumentos? Mejora esto en una sola función o más.
stop() 🎤Por favor, escribi en el chat
¿Esta dependencia provoca alegría? 😉
Más información: Dependencias: Mentalidad y antecedentes en el libro R Packages de Hadley Wickham y Jenny Bryan.
En la Guía de desarrollo de rOpenSci
curl, httr2, crul, httr. No RCurl. Para un nuevo paquete, httr2 en vez de httr.
jsonlite. No rjson ni RJSONIO.
xml2. No XML
sf, suites espaciales desarrolladas por las comunidades r-spatial y rspatial. No sp, rgdal, maptools, rgeos.
Evaluar la actividad en GitHub de los colaboradores
https://ropensci.org/es/blog/2022/07/01/evaluating-github-activity-for-contributors/
🧰 ¿Hay dependencias que podrías añadir, sustituir o eliminar en tu paquete?
Feature creep: “ampliación o adición excesiva y continua de nuevas funciones en un producto” https://en.wikipedia.org/wiki/Feature_creep
Está bien dividir el paquete.
Está bien decir no a las peticiones de funciones. Ejemplo
🧰 ¿Hay peticiones de funciones a las que te gustaría decir que no? Guardar respuesta como Respuesta GitHub?
stop() 🎤Por favor, escribi en el chat
“DAMP (descriptive and meaningful phrases)”
“DRY (don’t repeat yourself)”
¡Un intercambio!
El código está cubierto por el código de tests, ¡así que podemos asumir más riesgos!
Autónomas.
Se pueden ejecutar de forma interactiva. testthat::test_path().
Sin “fugas”. {withr}. withr::local_options(), withr::local_tempdir()…
{saperlipopette} https://github.com/ropensci-training/saperlipopette/blob/main/tests/testthat/test-exo-blame.R
{babelquarto} https://github.com/ropensci-review-tools/babelquarto/blob/main/tests/testthat/test-render.R
🧰 ¿Algunas de tus tests tienen código de nivel superior? ¿Puedes crear archivos y funciones de ayuda, y repetir la creación de objetos en cada prueba?
Mi código
is_internet_down <- function() {
!curl::has_internet()
}
my_complicated_code <- function() {
if (is_internet_down()) {
message("No internet! Le sigh")
}
# blablablabla
}
¿Cómo comprobar el mensaje?
En el test,
test_that("my_complicated_code() notes the absence of internet", {
local_mocked_bindings(is_internet_down = function(...) TRUE)
expect_message(my_complicated_code(), "No internet")
})
Para leer más: https://www.tidyverse.org/blog/2023/10/testthat-3-2-0/#mocking
y https://testthat.r-lib.org/dev/articles/challenging-tests.html
🧰 ¿tienes una situación de este tipo para probar?
stop() 🎤Por favor, publica en el chat
Llaves de API, etc.
.Renviron {keyring}!
# Usuari@, 1 vez para cada ordenador
keyring::key_set("deepl")
# Usuari@, cada vez que usa tu paquete
Sys.setenv(DEEPL_API_KEY = keyring::key_get("deepl"))
# Tu paquete
Sys.getenv("DEEPL_API_KEY")
🧰 ¿Podés aconsejar keyring en la documentación de tu paquete?
https://blog.r-hub.io/2024/02/28/key-advantages-of-using-keyring/
En el paquete para usuarios y usuarias: data/
En el paquete para el paquete: R/sysdata.rda
Desde el paquete: carpetas de usuari@s: tools::R_user_dir(). Demo!
tools::R_user_dir()¿Cómo buscar ejemplos?
tools::R_user_dir()Ejemplo 1 https://github.com/matt-dray/tamRgo + https://www.rostrum.blog/posts/2022-11-13-tamrgo/
Ejemplo 2 https://github.com/search?q=repo%3Aropensci%2Fcomtradr%20R_user_dir&type=code
🧰 ¿Tiene tu paquete algo que guardar entre las sesiones?
En la misma sesión, las mismas computaciones… caching?!
{memoise}
.a <- function() {
Sys.sleep(5)
"Hola"
}
a <- memoise::memoise(.a)
a()
a()
https://blog.r-hub.io/2021/07/30/cache/
🧰 ¿Podría usar caching tu paquete?
stop() 🎤Por favor, publica en el chat
…¡con tu propio paquete! En salas de Zoom.
Nos reuniremos en XX minutos como grupo para debatir.
¿Comentarios? ¿Preguntas?
Nos vemos en el #package-maintenance canal? 😉