Outils d'analyse de code de Roger
Le paquetage R roger fournit des outils pour analyser le style de codage et la documentation de scripts R pour le système de correction automatisé Roger l’omnicorrecteur.
Les outils d’analyse statique (ou linters) vérifient que le code et la documentation respectent les bonnes pratiques reconnues en programmation.
Cette page dresse la liste des outils livrés avec roger et fournit pour chacun une description et des exemples d’utilisation.
En un coup d’œil
Les outils requièrent en premier lieu d’évaluer et d’analyser un
fichier de script avec la fonction getSourceData
. L’objet résultant
de cette opération peut ensuite être passé à plusieurs outils
d’analyse statique.
srcData <- getSourceData("script.R")
assignment_style(srcData)
commas_style(srcData)
...
Tous les linters de roger retournent TRUE
si le code respecte
les bonnes pratiques de programmation. Dans le cas contraire, le
résultat FALSE
est accompagné d’un message indiquant la nature de
l’erreur et les lignes où se trouve le code fautif dans le script.
La fonction all_style
simplifie l’analyse style de codage en
exécutant d’un coup tous les linters disponibles.
srcData <- getSourceData("script.R")
all_style(srcData)
Analyse du style de codage
assignment_style
Vérifie que le symbole d’affectation vers la gauche (<-
) est utilisé
pour l’affectation d’une valeur à un objet, et non le symbole
d’égalité (=
).
Code fautif
x = 2
z = c(x = 42, y = 43)
Code conforme
x <- 2
z <- c(x = 42, y = 43)
Justification
La manière correcte et sécuritaire pour affecter une valeur à un objet
dans R est à l’aide du symbole d’affectation <-
(ou, beaucoup plus
rarement, avec ->
). Certes, =
permet aussi d’affecter une valeur à
un objet, mais uniquement au premier niveau d’expressions. Le symbole
d’affectation <-
, lui, est valide partout.
La seconde ligne du code fautif démontre la confusion que peut
engendrer l’utilisation de =
pour l’affectation: la première
utilisation est bel et bien une affectation, mais les deux autres
servent à nommer les arguments d’une fonction.
Les règles de syntaxe de R commandent d’utiliser l’opérateur <-
pour
l’affectation, point. Les bons éditeurs pour programmeurs adaptés à R
fournissent tous un raccourci pour composer le symbole.
close_brace_style
Vérifie que la position des accolades fermantes est conforme aux styles standards.
Code fautif
foo <- function(x, y) {
if (x > 2)
{ z <- 3
y <- y + z}
x^2 + y^3 + z^4
}
Code conforme
foo <- function(x, y)
{
if (x > 2)
{
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
Justification
Voir open_brace_style
.
close_bracket_style
Vérifie la conformité des espaces autour des crochets fermants.
Code fautif
z[1 ]
z[1,]
Code conforme
z[1]
z[1, ]
Justification
Un crochet fermant ne doit pas être précédé d’une espace, sauf si
celle-ci se trouve après une virgule (ce qui est requis par
commas_style
).
close_parenthesis_style
Vérifie la conformité des espaces autour des parenthèses fermantes.
Code fautif
1 + (x + y )
for (i in 1:10 )
Code conforme
1 + (x + y)
for (i in 1:10)
Justification
Il en va des espaces autour des parenthèses dans le code informatique comme il en va en prose. En l’occurrence, jamais d’espace avant une parenthèse fermante.
commas_style
Vérifie qu’une virgule n’est jamais précédée d’une espace, mais toujours suivie d’une, sauf si la virgule se trouve en fin de ligne.
Code fautif
z <- c(42,43)
z <- c(42 ,43)
Code conforme
z <- c(42, 43)
z <- c(42,
43)
Justification
Les espaces après les virgules permettent au code de respirer. Vous placez des espaces après les virgules — mais jamais avant — dans la prose, n’est-ce pas? Eh bien!, faites de même dans votre code informatique et tout le monde s’en portera mieux. Les espaces ne coûtent rien.
comments_style
Vérifie que les marqueurs de commentaires et le texte des commentaires, lorsqu’il y en a, sont séparés par au moins une espace.
Code fautif
##commentaire
##---commentaire
Code conforme
##
## commentaire
##--- commentaire
Justification
Les commentaires sont plus lisibles lorsqu’ils sont séparés des
marqueurs (un ou plusieurs symboles #
, possiblement suivis par
d’autres symboles de ponctuation) par au moins une espace. Dans les
commentaires comme dans le code, les espaces ne coûtent rien.
left_parenthesis_style
Vérifie la conformité des espaces autour des parenthèses gauche (ou ouvrantes).
Code fautif
1 +(x + y)
1 + ( (x + y) + z)
for(i in 1:10)
sqrt (4)
z <- function (x) x^2
Code conforme
1 + (x + y)
1 + ((x + y) + z)
for (i in 1:10)
sqrt(4)
z <- function(x) x^2
Justification
Il en va des espaces autour des parenthèses dans le code informatique comme il en va en prose. En l’occurrence, toujours une espace avant une parenthèse ouvrante, sauf dans un appel de fonction ou au début d’une sous-expression.
Voir
open_parenthesis_style
pour les règles concernant les espaces après une parenthèse ouvrante.
line_length_style
Vérifie que la longueur des lignes de code et de commentaires ne dépasse pas un certain nombre de caractères.
Code fautif
## Une très longue ligne de commentaires qui devrait être scindée sur plusieurs lignes pour éviter de devoir défiler horizontalement.
x <- c(x^2 + y^3 + z^4 + 3 * x * y - 6 * y * z^2 + x * z^3, x^3 + y^2 + z^3 + 3 * x * y)
Code conforme
## Une très longue ligne de commentaires qui devrait être scindée sur
## plusieurs lignes pour éviter de devoir défiler horizontalement.
x <- c(x^2 + y^3 + z^4 + 3 * x * y - 6 * y * z^2 + x * z^3,
x^3 + y^2 + z^3 + 3 * x * y)
Justification
Limiter la longueur des lignes de code à environ 70-80 caractères rend le code plus facile à lire. Notre œil a tendance à sauter à la ligne inférieure en se déplaçant de la gauche vers la droite (c’est d’ailleurs pourquoi les journaux et les magazines sont composés en colonnes de texte étroites). Vous disposez d’un écran très large? Profitez de l’espace horizontal pour afficher des fenêtres côte à côte, pas pour écrire des plus longues lignes de code.
nomagic_style
Vérifie l’absence de nombres magiques dans le code.
Code fautif
fooBar <- 2^32
runif(123)
x[3] * 7 + 2
Code conforme
FOOBAR <- 2^32
SIZE <- 42
runif(SIZE)
BAR <- 7
x[3] * BAR + 2
Justification
Un nombre magique est une constante numérique non nommée ou mal
documentée dans le code source d’un programme. Les nombres magiques
rendent les programmes difficiles à lire, à interpréter et à déboguer.
Par exemple, dans l’expression y <- x + 42
, la constante 42
est un
nombre magique.
Un nombre magique devrait être affecté à une variable portant un nom
significatif. Dans roger, l’affectation du résultat d’une
expression «simple» (consulter ?nomagic_style
pour les détails) à
une variable dont le nom est entièrement en majuscules est
automatiquement reconnue comme la définition d’un nombre magique.
C’est pourquoi, dans les exemples ci-dessus, fooBar <- 2^32
est
fautif, mais pas FOOBAR <- 2^32
.
De plus, les constantes -1, 0, 1, 2 et 100, ainsi que les nombres
employés seuls dans des opérations d’indiçage ne sont pas considérés
comme des nombres magiques. Dans l’expression x[3] * 7 + 2
, seul 7
est donc considéré comme un nombre magique.
open_brace_style
Vérifie que la position des accolades ouvrantes est conforme aux styles standards.
Code fautif
foo <- function(x, y)
{ if (x > 2)
{ z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
Code conforme
foo <- function(x, y)
{
if (x > 2)
{
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
Justification
Le style d’indentation et de positionnement des accolades est un sujet chaud parmi les programmeurs. Tous s’entendent au moins sur un point: il est absolument essentiel d’indenter les blocs de code pour mettre la structure d’un programme en évidence.
roger reconnait deux styles de positionnement des accolades, nommés «R» et «1TBS» dans le paquetage. Dans le style R — aussi connu sous les noms Allman, BSD ou C++ —, les accolades ouvrante et fermante se trouvent sur leur propre ligne, alignées sur le début de l’instruction à laquelle elles se rapportent. C’est le style employé dans les exemples.
Dans le style 1TBS — aussi souvent connu sous le nom K&R — l’accolade ouvrante se trouve sur la même ligne que son instruction, séparée par une espace. L’accolade fermante se trouve quant à elle sur sa propre ligne, alignée sur le début de l’instruction:
foo <- function(x, y) {
if (x > 2) {
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
open_brace_unique_style
Vérifie qu’un seul style de positionnement des accolades est utilisé dans le script.
Code fautif
foo <- function(x, y) {
if (x > 2) {
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
bar <- function(x)
{
x^2
}
Code conforme
foo <- function(x, y)
{
if (x > 2)
{
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
bar <- function(x)
{
x^2
}
ou
foo <- function(x, y) {
if (x > 2) {
z <- 3
y <- y + z
}
x^2 + y^3 + z^4
}
bar <- function(x) {
x^2
}
Justification
Utiliser un style standard de positionnement des accolades dans son code, c’est bien, mais demeurer constant dans le code est encore mieux. Cet outil d’analyse vérifie que l’un ou l’autre des styles R et 1TBS est utilisé dans le script, mais pas les deux.
Voir open_brace_style
pour
plus de détails.
open_bracket_style
Vérifie la conformité des espaces autour des crochets ouvrants.
Code fautif
z[ 1]
z[ , 1]
Code conforme
z[1]
z[, 1]
Justification
Comme les parenthèses ouvrantes, les crochets ouvrants ne doivent jamais être immédiatement suivis d’une espace.
open_parenthesis_style
Vérifie la conformité des espaces autour des parenthèses ouvrantes.
Code fautif
1 + ( x + y)
for ( i in 1:10)
Code conforme
1 + (x + y)
for (i in 1:10)
Justification
Il en va des espaces autour des parenthèses dans le code informatique comme il en va en prose. En l’occurrence, jamais d’espace après une parenthèse ouvrante.
Voir
left_parenthesis_style
pour les règles concernant les espaces avant une parenthèse ouvrante.
ops_spaces_style
Vérifie la conformité des espaces autour des opérateurs infixés et unaires.
Code fautif
x+y
x<-y+ 3
x<- -2
2+!x
Code conforme
x + y
x <- y + 3
x <- -2
2 + !x
Justification
Les espaces autours des opérateurs sont comme les espaces autour des virgules, elles permettent au code de respirer et facilitent la lecture du code.
Les opérateurs infixés binaires doivent être précédés et suivis d’une espace (ou d’un retour à la ligne). Quant aux opérateurs unaires, ils doivent être immédiatement suivis de leur argument.
Remarque: l’opérateur d’affectation <-
est un opérateur infixé
binaire.
trailing_blank_lines_style
Vérifie qu’un script ne contient pas de lignes vides en fin de fichier.
Code fautif
----- <- marqueur du début du fichier
x + y
----- <- marqueur de la fin du fichier
Code conforme
-----
x + y
-----
Justification
Les lignes vides en fin de fichier n’ont pas d’effet sur le code, c’est bien entendu. Sauf que ça ne fait pas propre. Supprimez-les. Les bons éditeurs pour programmeurs peuvent s’en charger pour vous.
trailing_whitespace_style
Vérifie que le script ne contient pas d’espaces inutiles en fin de ligne.
Code fautif
x + y | <- marqueur de la fin de la ligne
Code conforme
x + y|
Justification
Comme les lignes vides en fin de fichier, les espaces inutiles en fin de ligne n’ont aucun autre effet sur le code que de ne pas faire propre. Supprimez les blancs inutiles (espaces et tabulations) à la fin des lignes. Votre éditeur de texte peut sans doute le faire pour vous. Cochez l’option et n’y pensez plus jamais.
unneeded_concatenation_style
Vérifie que la fonction c
est utilisée avec plus d’un argument.
Code fautif
x <- c()
y <- c(42)
Code conforme
x <- numeric(0)
y <- 42
Justification
Dans R, la fonction c
sert à combiner des objets. Combiner rien ou
un objet avec lui-même n’a guère de sens, n’est-ce pas? N’utilisez
donc pas c
sans ou avec un seul argument.
Si vous souhaitez créer un vecteur vide, utilisez numeric(0)
,
logical(0)
ou character(0)
selon le type de vecteur désiré.
Analyse de la documentation
Vérifie qu’une fonction est livrée avec de la documentation en commentaires, ainsi que la présence de certaines sections obligatoires.
any_comments
vérifie que le fichier contient des commentaires non
vides.
any_doc
vérifie que le fichier contient de la documentation,
n’importe qu’elle documentation.
signature_doc
vérifie que la signature de la fonction est présente
dans la documentation.
section_doc
vérifie que la documentation de chaque fonction comporte
une section dont le nom correspond à un motif d’expression régulière.
formals_doc
vérifie que la documentation comporte une description de
chacun des arguments formels d’une fonction.
Code fautif
foo <- function(x, y = 2)
x + y
Code conforme
###
### foo(x, y = 2)
###
## Additionner deux vecteurs
##
## Arguments
##
## x: un vecteur
## y: un autre vecteur
##
## Valeur
##
## Somme de deux vecteurs
##
## Exemples
##
## foo(1:5)
##
foo <- function(x, y = 2)
x + y
Justification
À moins qu’une rubrique d’aide en bonne et due forme n’accompagne une fonction, sa définition devrait toujours être précédée d’un bloc de documentation contenant au minimum:
- la signature de la fonction (son nom suivi, entre parenthèses, de tous les arguments avec leur valeur par défaut, le cas échéant);
- une courte description de ce que fait la fonction (en mode infinitif, de manière à compléter la phrase «Cette fonction permet de…»);
- la liste des arguments, de leur signification et des valeurs admissibles;
- la valeur retournée par la fonction;
- un ou plusieurs exemples d’utilisation de la fonction, selon le niveau de complexité de celle-ci.
Il s’agit de la structure générale des rubriques d’aide de R.