Menu
Coddy logo textTech

Validateurs et fonctions utilitaires

Fait partie de la section Programmation orientée objet du Journey R de Coddy. Leçon 5 sur 57.

Le constructeur vérifie les types ; un validateur vérifie les valeurs. Par convention, validate_money() prend un objet, appelle stop() avec un message clair pour chaque règle qu’il enfreint, et renvoie l’objet lorsque tout va bien. call. = FALSE exclut l’appel de fonction du message :

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
  if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
  if (nchar(x$currency) != 3) stop("currency must have 3 letters", call. = FALSE)
  x
}
m <- validate_money(new_money(-5, "EUR"))

Sortie :

Error: amount must not be negative
Execution halted

La fonction auxiliaire est la fonction appelée par les autres parties du code. Elle porte le nom de la classe, convertit ses entrées vers les types appropriés, applique les valeurs par défaut et transmet le résultat au constructeur puis au validateur :

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
  if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
  x
}
money <- function(amount, currency = "EUR") {
  validate_money(new_money(as.double(amount), toupper(currency)))
}
m <- money("12", "usd")
cat(m$amount, m$currency)

Résultat :

12 USD

Le code qui lit la saisie de l'utilisateur intercepte les erreurs du validateur avec tryCatch() et affiche conditionMessage(e), le texte passé à stop() :

validate_age <- function(x) {
  if (x$years < 0) stop("age must not be negative", call. = FALSE)
  if (x$years > 150) stop("age is too large", call. = FALSE)
  x
}
age <- function(years) validate_age(structure(list(years = as.double(years)), class = "age"))
for (input in c("30", "-2", "200")) {
  result <- tryCatch(paste("ok", age(input)$years), error = function(e) conditionMessage(e))
  cat(result, "\n")
}

Sortie :

ok 30 
age must not be negative 
age is too large 

Chacune des trois fonctions a une tâche. new_money() est stricte et rapide, pour le code qui possède déjà les bons types. validate_money() contient les règles concernant les valeurs, qui peuvent être nombreuses ou prendre du temps. money() est conviviale et c’est elle que le reste du programme utilise :

new_money()       # types uniquement ; construit l'objet avec structure()
validate_money()  # règles de valeur ; stop() avec un message, sinon return x
money()           # convertit l'entrée, puis validate_money(new_money(...))
challenge icon

Défi

Facile

new_score(points, max) dans Score.R construit un objet score. Complétez les autres fonctions dans le même fichier :

  • validate_score(x) s’arrête avec points must not be negative, max must be positive ou points must not exceed max, vérifiés dans cet ordre, et renvoie sinon x.
  • score(points, max = 100) convertit les deux arguments avec as.double() et renvoie validate_score(new_score(...)).
  • format.score(x, ...) renvoie 45/50 (90%), avec le pourcentage arrondi à l’entier le plus proche.

Utilisez call. = FALSE dans chaque appel à stop(). Le code fourni lit les lignes 45 50, affiche le score formaté, ou error: suivi du message.

Votre code doit être placé dans Score.R. main.R contient le code fourni pour les entrées et sorties et ne peut pas être modifié.

Essayez vous-même

source("Score.R")

# Code d'entrée/sortie fourni : le garder tel quel
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- tryCatch(score(p[1], p[2]), error = function(e) conditionMessage(e))
  if (is.character(s)) cat("error: ", s, "\n", sep = "") else cat(format(s), "\n", sep = "")
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur R en ligne