Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Exo Débutant POO] Gestion sûre des codes d'erreur

23 juin 2017 à 12:36:39

Cet exercice consiste à écrire une classe permettant de gérer les codes d'erreur retournés par les fonctions, de manière sûre. Il est inspire de la video C++Now 2017: Kirk Shoop “Errors: forgotten, but not gone".

Contexte

De nombreuses fonctions des bibliothèques C gèrent les erreurs en retournant un code d'erreur (un entier) ou un booléen (true = succès, false = échec). Si la fonction réussie, cela retourne une valeur spécifique "no error" (souvent 0 ou -1), sinon cela retourne une valeur correspondant à l'erreur. (La liste des codes d'erreur est souvent donne dans la documentation ou sous forme de constante).

// fonction C
int doSomething();

// appel correct
int error = doSomething();
if (error != NoError) {
    // gere l'erreur
}

Cette facon de gérer les erreurs est très critiquable (voir Retour de fonctions ou exceptions ?), puisqu'il est facile de ne pas vérifier si une fonction retourne une erreur.

// appel incorrect !
doSomething();

Ce type de problème est facile a trouver lors d'une analyse statique, il suffit de détecter que la valeur de la fonction n'est pas utilisée.

Mais le problème se pose quand même lorsque la valeur retournée est affectée à une variable, mais n'est pas vérifiée. 

void foo() {
    int error = doSomething();
    error = doSomething();// l'erreur n'est pas vérifiée avant de changer la valeur
}

void bar() {
    int error = doSomething();
} // l'erreur n'est pas vérifiée avant de quitter la fonction

Le but de cet exercice est d'écrire une classe qui oblige à vérifier les erreurs.

L'API

La classe SafeCodeError est une classe à sémantique de valeur, non copiable, modifiable par affectation, constructible par défaut ou avec un code d'erreur. Lorsque l'objet est détruit ou qu'un code d'erreur change, la classe lance une exception. La fonction membre release permet de réinitialiser l'erreur, pour indiquer que l'erreur a été prise en compte. La fonction membre errorCode retourne le code d'erreur.

Le code d'erreur est un entier de type int.

Note : normalement, lancer une exception dans un destructeur est une pratique qui n'est pas recommandée. Dans un vrai code, cette classe serait utilisée pour détecter des erreurs du développeur, donc avec une assertion plutot qu'une exception. Mais pour écrire des tests unitaires détectant une assertion, c'est compliqué sans framework de test. C'est pour cela que dans cet exercice, vous utiliserez une exception. Mais n'oubliez pas que dans un vrai code, vous devriez faire autrement.

Etape 1 : ecrire l'API

- [Question débutant] Dans la description de la classe SafeCodeError, que signifie "constructible par défaut" ? Donner la signature de cette fonction.

- [Question débutant] Dans la description de la classe SafeCodeError, que signifie "constructible avec un code d'erreur" ? Donner la signature de cette fonction.

- [Question débutant] Dans la description de la classe SafeCodeError, quelle est la signature de la fonction release ?

- [Question débutant] Dans la description de la classe SafeCodeError, quelle est la signature de la fonction errorCode ?

- [Question intermédiaire] Dans la description de la classe SafeCodeError, que signifie "non copiable" ? Donner la signature des fonctions correspondantes. (Pour commencer, considérer que la classe n'est pas déplaçable).

- [Question intermédiaire] Dans la description de la classe SafeCodeError, que signifie "modifiable par affectation" ? Donner la signature des fonctions correspondantes.

- [Question avancée] Dans la description de la classe SafeCodeError, que signifie "classe a sémantique de valeur" ? Qu'est ce que cela implique concernant l'héritage ? L'utilisation de fonctions virtuelles ?

----------------

- Ecrire la déclaration (c'est à dire uniquement la partie publique de ce qui est dans le fichier .h) de la classe SafeCodeError en se basant sur la description donnée.

class SafeCodeError {
public:
    // default constructor
    SafeCodeError();

    ...
};

Etape 2 : ecrire les tests unitaires

Note : pour cet exercice, il n'est pas nécessaire d'utiliser une bibliothèque de tests. Utiliser simplement assert et créer une fonction pour chaque test.

void test_defaultContructor() {
    // tester le constructeur par défaut
}

void test_xxx() {
    ...
}

...

int main() {
    test_defaultContructor();
    test_xxx();
    ...
}

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError est constructible par défaut.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError est constructible avec un code d'erreur.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError est affectable.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError  ne lance pas d'exception lorsqu'elle contient un code d'erreur nul et qu'elle est détruite.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError  ne lance pas d'exception lorsqu'elle contient un code d'erreur nul et qu'une nouvelle valeur est affectée.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError  lance une exception lorsqu'elle contient un code d'erreur non nul et qu'elle est détruite.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError lance une exception lorsqu'elle contient un code d'erreur non nul et qu'une nouvelle valeur est affectée.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError ne lance pas d'exception lors d'un appel à la fonction release.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError retourne un code d'erreur nul après un appel a la fonction release.

- [Question débutant] écrire un test unitaire pour vérifier que la classe SafeCodeError ne lance pas d'exception lors de sa destruction ou d'une affectation, après un appel à la fonction release.

Etape 3 : implementation

Note : l'implémentation consiste a écrire le code des fonctions membres et la partie privée de la déclaration de la classe.

- [Question débutant] que contient la partie privée de la déclaration de la classe ?

- [Question débutant] Ecrire l'implémentation du constructeur par défaut.

- [Question débutant] Ecrire l'implémentation du constructeur avec un paramètre.

- [Question débutant] Ecrire l'implémentation du destructeur.

- [Question débutant] Ecrire l'implémentation de l'opérateur d'affectation.

- [Question débutant] Ecrire l'implémentation des autres fonctions.

-
Edité par gbdivers 23 juin 2017 à 15:23:09

  • Partager sur Facebook
  • Partager sur Twitter
23 juin 2017 à 15:17:59

Bonjour,

dans la première étape, il y a deux fois la même question :

Dans la description de la classe SafeCodeError, que signifie "constructible avec un code d'erreur" ? Donner la signature de cette fonction.

l'une question débutant, l'autre question intermédiaire. Est-ce une erreur ??

-
Edité par cauld 23 juin 2017 à 15:18:28

  • Partager sur Facebook
  • Partager sur Twitter
23 juin 2017 à 15:23:30

Oui, c'est une erreur de copier-coller. C'est corrige, merci.
  • Partager sur Facebook
  • Partager sur Twitter