Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 15/03/2017, à 03:07

Destroyers

[C++] conception d'un système d'exception

Bonjour,

Je suis actuellement en train de développer une petite bibliothèque en C++ pour m'entraîner, et je me rend compte que pour un code propre, il faut que je gère des erreurs en interne, j'ai notamment besoin de lever des exceptions.
Cependant, je ne sais pas trop comment m'y prendre, s'il y a des conventions, des règles (pour de la clarté, de la ré-utilisabilité, ou surtout de la maintenance...).

Globalement, j'hésite entre deux architectures :
- soit créer MaClasse_Exception (une pour chaque classe de mon projet, héritant évidement de std::exception) depuis lesquelles dériveront plein de sous classes décrivant chacune un problème précis.
- soit créer une seule classe d'Exception dont le message d'erreur est passé en argument pour connaître le problème.

Quels sont les avantages et défauts de chacune des deux méthodes ?
Pour la première méthode, devrais-je alors coder toutes ces exceptions dans le même fichier ? Dans le fichier de la classe correspondante ? dans une multitude de fichiers (gloup, la lib à 40 fichiers ...) ?

J'aimerais aussi savoir s'il est correct de créer une classe intermédiaire (pourquoi pas abstraite ?) permettant d'ajouter quelques méthodes (notamment log() ).
std::exception ---> Loggable_Exception ---> MyException
Un ami d'Epitech m'a assuré que c'était une mauvaise idée car l'utilisateur devrait alors avoir un bloc catch pour attraper un Loggable_Exception... Et alors ? j'ai pas bien saisi en quoi cela pouvait poser problème. Il me propose plutôt d'utiliser une fonction (non membre) log() dans le catch. ça me paraît moins propre :3

Avant dernier point : j'aimerais savoir s'il peut être plus intéressant ou non d'utiliser des exceptions définies dans <stdexcept> (lesquelles et pourquoi, du coups ^^ ) plutôt que directement std::exception. S'il faut en utiliser plusieurs différents j'avoue que ça grossirait mon code car il faudrait que j'applique à chacun mes classes d'exceptions intermédiaires ...

Dernier point (mais un peu hors sujet) : puisque je parle d'erreurs, il y en a certaines que j'aimerais stocker dans des flags en attribut de certaines classes. Peut il être pertinent de mettre ces flags en mutable ? Par exemple : Une classe File a une méthode remove (supprimant un fichier sur le disque sans que cela impacte l'instance de File) qui est donc déclarée const. Mais imaginons que ladite instance de FIle a son attribut _path vide (""). Ça me paraît trop anodin pour envoyer une exception : au pire, la fonction remove() n'aura aucun effet, mais l'utilisateur doit avoir un moyen de savoir pourquoi le fichier n'a pas été supprimé, c'est pourquoi je voudrais mettre ces flags... Alors mieux vaut il retirer le const ? Mettre de flag en mutable ? Faire autrement ?
(PS, si mutable ne sert pas à ça, alors je ne comprend pas trop dans quelles circonstances il serait justifié qu'un attribut soit mutable).

Je vous remercie d'avance.

Hors ligne

#2 Le 15/03/2017, à 08:12

Compte anonymisé

Re : [C++] conception d'un système d'exception

Ne te casse pas la tête : crée une classe de base pour les exceptions de ton programme, puis dans chaque fichier, déclare les exceptions spécifiques. Par exemple, dans un fichier qui gère des mots de passe, tu peux déclarer une WrongPasswordException qui dérive de ton exception de base. C'est comme ça que j'ai vu faire plein de projets, et ça me paraît très propre et clair.

Le système d'exceptions est justement fait pour utiliser l'héritage de classes : si tu crées une unique classe d'exception, tu ne pourras pas attraper les exceptions spécifiques ; un bloc catch devra obligatoirement recevoir toutes les exceptions, et si besoin les repasser ensuite au bloc supérieur après avoir lu le message d'erreur. Bien sûr, tout est cassé si tu changes ce message d'erreur. Et c'est sûrement une plaie à coder, illisible, verbeux et fragile. Utilise l'héritage, c'est fait pour ça !

J'ai pas bien compris à quoi servirait la classe abstraite : si tu veux ajouter une fonction à toutes tes exceptions, ajoute-la dans l'exception de base, avec un comportement générique. Par exemple, si elle doit retourner un message d'erreur, la classe de base renverra "erreur générique" et les sous-classes pourront changer ce message.

A quoi doit servir la fonction log() ?

Quant à la classe File, je pense qu'essayer de supprimer un fichier inexistant est une erreur à part entière qui mérite de lever une exception. Si elle n'est finalement pas importante pour l'appelant, il ajoutera un bloc catch vide. Soit l'erreur n'est pas importante et on ne la signale pas, soit on a besoin de la signaler et dans ce cas il faut une exception. Ajouter une valeur à vérifier, c'est du C et c'est dommage d'en revenir à ça alors que tu as un système d'exceptions pour t'aider. D'ailleurs, toutes les libs standard de tous les langages que j'ai essayés levaient une exception dans ce cas.

#3 Le 15/03/2017, à 15:38

Destroyers

Re : [C++] conception d'un système d'exception

Ah bon je ne crée même pas de classe d'exception mère spécifique à une classe ? (Comme vu ici). Très bien, ça sera plus simple alors. Moi je pensais plutôt faire un truc du genre :
std::exception ---> loggable_Exception (ma classe de base pour toutes les autres exceptions) ---> File_Exception ---> Invalid_Argument
                                                                                                                                                                                  ---> Autre_Erreur
                                                                                                                                                   ---> Autre_Classe ---> Invalid_Argument
                                                                                                                                                                                ---> Encore_Un_Autre_Problème
Mais si j'ai bien compris tu me proposes plutôt de ne pas faire le 3eme héritage et de passer directement aux 4emes.

Boah si j'avais pensé à faire une classe abstraite c'est par ce qu'en général je pense qu'on ne lance pas d'exception non spécialisée donc peu importe qu'elle soit abstraite ou non, mais soit avoir un comportement générique me va aussi (et c'est finalement ce que font toutes les exceptions ^^).

La fonction log() sert à enregistrer l'exception dans un fichier (pour avoir une sorte d'historique lors d'une exécution pour faire de la maintenance). En fait pour être plus précis, mon exception prend en paramètre la fonction et le fichier.cpp (grâce à la macro __FILE__) où l'exception à été levée, donc log() permet de tout ranger dans un fichier texte.

Non je n'essaie pas de supprimer un fichier inexistant, je dis que l'instance de File n'a pas initialisé sa variable _path, et donc il est normal que les méthodes où il y a besoin de ce path envoient des erreurs. Seulement erreur ou exception ? Toi tu dis exception, admettons ^^

Hors ligne

#4 Le 16/03/2017, à 21:43

Destroyers

Re : [C++] conception d'un système d'exception

Ah oui, Je travaille un peu avec errno aussi. Est ce une mauvaise pratique, sachant qu'il s'agit de lire soi même une erreur ?

Hors ligne