En effet, je pense qu'une exception, comme son nom l'indique, doit être exceptionnelle, et que de plus, une exception et une erreur ne s'adresse pas du tout aux mêmes entités.
Les exceptions ne devrait être misent en oeuvre que lorsqu'un événement qui n'est pas censé se produire survient lors de l'éxécution du code, comme par exemple l'impossibilité d'écrire sur le système de fichiers, de se connecter à une base de données, j'en passe et des meilleures, afin de permettre la mise en oeuvre d'une solution alternative permettant de contourner ou solutionner le problème rencontré, quitte à dégrader la qualité de service offerte par le code.
L'exception est effectivement le moyen le plus pratique et élégant pour pallier à l'indisponibilité de la base de données, en permettant de mettre en oeuvre une alternative de manière très simple au niveau du code, par exemple de la manière suivante :
<?php
...
try
{
$mysql->connect();
}
catch (databaseException $exception)
{
$logger->wrtie($exception->getMessage());
header('Status: 303');
header('Location: http://static.mondomaine.com');
}
...
?>
Cet exemple permet de se rendre compte que le code est le destinataire et le gestionnaire de l'exception, et non le développeur, qui n'a pas son mot à dire lorsque survient l'exception, même si c'est effectivement lui qui a décidé du comportement du code en cas d'exception lors de la phase de conception.
Pour résumé, les exceptions sont donc destinées à être mise en oeuvre lors de l'éxécution du code et leur gestion est assurée par ce dernier, au contraire des erreurs, qui doivent être à mon sens utilisées lors de la conception du code et qui sont à destination du développeur.
En effet, les erreurs doivent servir à avertir le programmeur qu'il n'utilise pas correctement une fonction ou une méthode, qu'elle soit native ou externe au langage, bref, qu'il n'utilise pas le code correctement.
Typiquement, j'utilise les erreurs de la manière suivante :
<?php
...
public function setWith(array $arguments)
{
if (array_key_exists(0, $arguments) === false)
{
trigger_error('Argument must be set at index 0', E_USER_ERROR);
}
else
{
$this->value = $arguments[0];
return parent::setWith($arguments);
}
}
...
?>
Dans ce cas, la cible de l'erreur est clairement le développeur, et c'est à lui, lors de la phase de conception et de test de son code, de prendre les mesures adéquates pour régler le problème, le code ne pouvant se corriger de lui-même.
Cependant, tout cela est sujet à discussion, et reléve énormément de la bataille de chapelle.
L'important, comme dans le cas des conventions de nommage, est de définir les cas d'utilisation respectifs des erreurs et des exceptions le plus tôt possible, de s'y tenir, et de communiquer largement à ce sujet, afin que tous les intervenants sur le code sachent précisement la solution à utiliser en fonction des différents cas de figure.
PHP apporte d'ailleurs à ce sujet son aide, et cela de manière native, en laissant clairement le choix au développeur d'utiliser l'une ou l'autre des philosophies.
La SPL implémente en effet un certain nombre d'exceptions dérivant du type de base Exception
, séparée en deux familles distinctes :
- L'une, composée des dérivées de
RuntimeException
, est spécialement dédiée à la gestion des problèmes survenant lors de l'éxécution du code et il s'agit donc de celle qui a ma préférence. - L'autre, composées des dérivées de
LogicException
, doit plus particulièrement être mise en oeuvre pour gérer les problèmes liés à la conception et la mise en oeuvre du code.
Cependant, comme à son habitude, PHP fait aussi de la merde n'importe quoi puisqu'il arrive souvent qu'il génére des erreurs là ou des exceptions seraient beaucoup plus appropriées.
Malheureusement, la sacro-sainte compatibilité avec les anciennes versions fait qu'il en sera toujours ainsi...
Et vous, vous utilisez les erreurs et les exceptions de quelle manière ?
24 réactions
1 De romualb - 11/03/2010, 13:08
Je suis entièrement d'accord avec toi. Un programme ne devrait comporter aucune erreur. Comme tu le dis si bien, les erreurs sont la conséquence d'une mauvaise programmation, ou d'oublis de la part du développeur.
Les évènements provoquant l'apparition d'erreurs mais indépendantes du programme (accès à une ressource impossible...) sont à ranger dans le cadre des exceptions, qui doivent bien sur être aussi gérées par le développeur.
La cible est différente : une erreur est destinée au développeur, une exception à l'utilisateur du programme.
2 De metagoto - 11/03/2010, 15:36
Je suis globalement de l'avis de l'auteur quant au caractère exceptionnel des exceptions -à utiliser avec parcimonie.
Une exceptions ne devrait être lancée que dans le cas où on rencontre une sévère corruption du flot normal au runtime (j'insiste, car certains voudraient avoir des exceptions pour des parse errors!), rendant impossible (ou non souhaitable) la poursuite des opérations. Résorber cet état "anormal" ne peut se faire parfois que beaucoup plus bas dans la stack des scopes, d'où les catch blocks. Bref, ce sont des considérations très pragmatiques et ces exceptions ne devraient pas se substituer aux bon vieux "error codes" retournés ou passés par référence au fonctions.
3 De Hugo - 11/03/2010, 15:53
Comme tu l'expliques une exception n'est pas une erreur, c'est un cas exceptionnel qui peut survenir et que l'on peut traiter d'une manière différente. Beaucoup de gens font l'amalgame entre exception et erreur.
4 De Eric - 11/03/2010, 17:17
En même temps, vous avez des applications où les erreurs ne sont pas exceptionnelles ? il y a peut être quelque chose à réparer là dedans
Dans l'idéal je ferai trois cas :
- les journaux applicatifs
- les avertissements
- les erreurs
Les journaux applicatifs c'est "à part", c'est par exemple l'historique de connexion. Potentiellement on y met des erreurs, mais on y met aussi des choses tout à fait normal. Ca n'apparait nul part ailleurs et c'est géré par l'application, pas par PHP.
Les avertissements peuvent être fait via des messages. Une conversion de type tendancieuse peut être un avertissement.
Les erreurs par contre sont par nature exceptionnelles, et à ce titre vu qu'on ne sait pas si le programme peut continuer sans risque (ça demande une connaissance du fonctionnel) il faut que ce soit fatal, immédiatement.
Il semble que tu vois une quatrième catégorie, entre l'avertissement et l'erreur : quand le développeur fait quelque chose qu'il ne devrait pas.
Là où je ne suis pas d'accord c'est que les erreurs ne sont pas là que pendant la conception. Il est tout à fait courant de voir des erreurs non détectées en recette et qui arrivent en production. Là on en fait quoi ? Pourquoi la considérer comme un simple message ?
Mais surtout la différence entre "erreur" ou "exception" ce n'est pas tant la destination, c'est l'usage qu'on en fait. Le propre d'une exception c'est de pouvoir être interceptée ailleurs que là où elle est jetée.
J'ai un fichier qui n'existe pas en lecture ? une fonction appelée avec un identifiant nul ? Si j'ai une erreur "classique" je n'ai que deux choix :
- enregistrer un message d'erreur et continuer
- enregistrer un message d'erreur et arrêter
La décision doit être prise au niveau du code appelé, dans les bibliothèques au coeur du programme. Tu as une bibliothèque qui gère des camemberts de statistiques, vas donc me dire si l'erreur d'écriture ou l'erreur d'appel est une erreur fatale ou pas ? vas me dire si c'est une erreur de conception ou un problème système ?
Factuellement tu ne peux pas, du moins la bibliothèque qui gère les camemberts ne le peut pas. Ca dépend du fonctionnel de l'application. Dans certaines ça peut être mineur et "possible", dans d'autres c'est critique entrainant des erreurs graves et "exceptionnel" du au système.
Le mécanisme d'exception est là pour ça : il y a une partie qui est chargée de lancer les erreurs (les exceptions) et c'est dans l'utilisation du code qu'on décide ce qu'on veut faire avec cette erreur (le try/catch). C'est surtout ça le bénéfice des exceptions.
Que ce soient des erreurs d'appel, des erreurs de conception ou des erreurs système, le mécanisme a ses avantages.
Et finalement, si j'utilise des exceptions là où toi tu vois une erreur de conception, qu'est ce que ça change ? La seule conséquence c'est qu'on va avoir l'équivalent d'une erreur fatale. Sinon, sans try/catch, c'est exactement le même comportement qu'une E_ERROR.
Mais de toutes façons, en conception, si j'ai une erreur d'appel ou une erreur de conception, je vais la corriger avant de passer à la suite. Pas besoin pour ça de continuer l'exécution (au contraire, on risquerait de louper l'erreur).
5 De mageekguy - 11/03/2010, 18:16
@Eric:
En phase de conception, les erreurs sont plutôt la régle que l'exception ;).
Plus sérieusement, je ne vois aucun intêret à attraper des erreurs liées à une mauvaise utilisation d'une méthode ou d'une fonction, donc j'utilise des erreurs classiques et non des exceptions pour ce cas de figure.
Par contre, je suis tout à fait d'accord avec toi pour l'utilisation des exceptions dans le cadre d'une bibliothèques externes, puisque cette dernière ne doit pas assumer la responsabilité de la gestion de l'erreur lors de l'éxécution, sous peine de poser des problèmes au développeur qui la mettra en oeuvre.
Cependant, il est de la responsabilité de la bibliothèque d'informer le développeur, à l'aide d'erreur classique, qu'il ne l'utilise pas correctement.
Au final, nous sommes d'accord, même si tu le formules et le justifie d'une manière différente, avec le bémol que tu acceptes de mettre en oeuvre des exceptions dans le cadre de la conception, ce à quoi je ne vois personnellement aucun intêret puisque ce type d'erreur ne peut pas être corrigé par le code et qu'il n'y a donc aucun intérêt à l'attraper (à part dans le cadre d'une application qui permettrait de générer du code dynamiquement, mais, bon, comment dire... ce n'est pas forcément la meilleure des idées).
6 De desfrenes - 12/03/2010, 13:57
"je pense qu'une exception, comme son nom l'indique, doit être exceptionnelle, et que de plus, une exception et une erreur ne s'adresse pas du tout aux mêmes entités."
En python on n'a que les exceptions... ça ne pose pas plus de problème que ça.
"Cependant, comme à son habitude, PHP fait aussi de la merde n'importe quoi puisqu'il arrive souvent qu'il génére des erreurs là ou des exceptions seraient beaucoup plus appropriées."
Raison de plus pour unifier le tout, non ? à condition que ça soit fait de base dans php, pas avec un hack.
7 De mageekguy - 12/03/2010, 14:12
@defresnes:
Je ne dis pas que générer une exception à la place d'une erreur pose problème, puisque comme le dis Eric, au final, du moins pour les E_ERROR, cela revient au même.
Je dis que cela n'a pas de sens, puisqu'une erreur n'a pas à pouvoir être attrapé.
Quand à ta remarque sur PHP, je suis parfaitement d'accord, mais cela tu devais bien t'en douter ;).
8 De NiKo - 12/03/2010, 14:20
Perso, je ne SUPPORTE pas les erreurs, les warnings les fatal, les parse error (vous savez, les messages d'erreur avec du html dedans, n'importe quoi), tout simplement parce qu'on ne peut justement pas les attraper pour réagir en conséquence.
Je rêverai de pouvoir catcher une FatalErrorException ou même soyons fous une ParseErrorException (mais il faudrait pour ça que le parser de PHP soit mieux gaulé et le language dans tout les cas précompilé, beurk), alors j'arrête de rêver tout haut.
Bon après là où je te rejoins entièrement, c'est bien évidemment sur la définition des conventions, histoire au moins qu'il n'y ait qu'un moyen unique dans tout le projet de signifier tel ou tel type d'erreur.
9 De uberVU - social comments - 12/03/2010, 16:49
Social comments and analytics for this post
This post was mentioned on Twitter by InPhoenity: Erreur ou exception ? #php ==> http://goo.gl/cf4f...
10 De mageekguy - 12/03/2010, 17:06
@NiKo:
La directive
html_errors
de tonphp.ini
est ton amie, pour les erreurs au format html.Et je le répete, pour moi, une
, du moins celle voulu par le développeur viatrigger_error()
, ne doit pas être attrapée, puisque de mon point de vue, elles doivent être utilisé pour signaler au développeur une mauvaise utilisation d'une fonction ou d'une méthode.Après tout, si elle est fatal, ce n'est pas pour rien ;).
11 De tight - 12/03/2010, 17:09
"PHP fait aussi (de la merde) n'importe quoi puisqu'il arrive souvent qu'il génére des erreurs là ou des exceptions seraient beaucoup plus appropriées."
+1, je HAIS ces erreurs mal placées !
Rien de plus énervant que d'avoir à écrire une batterie de test avant l'appel à la fonction pour essayer d'éviter l'erreur, alors qu'un simple try / catch ferait l'affaire.
Sur le principe, je me demande d'ailleurs si écrire ces tests à du sens ? Par exemple, avant d'écrire dans un fichier, je teste pour voir s'il existe et si j'ai les droits d'écriture ... mais qui me dit que le fichier n'a pas été supprimé entre temps ?
12 De mageekguy - 12/03/2010, 17:14
@tight:
C'est pour cela que l'Homme a inventé le lock de fichier :).
Et c'est également valable pour les clefs étrangères en base de données...
13 De Olivier - 12/03/2010, 18:05
Bof bof. Comme le dit un des commentateurs, il n'y a pas d'erreur en python. Ça veut dire que tu peux toujours attraper les erreurs, fatales ou pas. Ça n'a aucun sens de générer une erreur, comme N1k0 le souligne.
Donc les exceptions n'ont rien d'exceptionnel, au contraire! Quand tu lèves une exception, tu dis juste: "là, je peux plus continuer, démerde toi". C'est à la fonction appelante de se débrouiller.
14 De desfrenes - 13/03/2010, 03:03
"Beaucoup de gens font l'amalgame entre exception et erreur."
Oui c'est sur... par exemple tous ceux qui viennent d'un autre langage et qui se disent en arrivant sur php: "Erreurs != exceptions.... wtf ???"
On aurait pas pu avoir ce débat pour un autre langage que php. Étant donné ses antécédents (n'est-ce pas fch...), ça devrait mettre la puce à l'oreille.
On a pas affaire à une distinction super intelligente entre 2 systèmes de gestion d'erreurs qui répondraient à des besoins fondamentalement différents.Ce n'est pas le cas: les exceptions répondent très bien aux besoins, y compris celui de l'exemple plus haut. C'est juste le résultat de l'évolution du langage d'un mode procédural à un mode objet. On ajoute des fonctionnalités sans casser les anciennes... pour l'instant. Éventuellement ça disparaitra un jour comme disparaitront les magic_quotes.
Non, franchement... avoir ces deux systèmes côte à côte c'est juste une des multiples raisons qui font dire par ailleurs que finalement... php c'est de la merde.
15 De mageekguy - 13/03/2010, 11:29
@desfresnes:
Justement, de mon point de vue, si.
Les erreurs pour les erreurs de mise en oeuvre au niveau du code.
Les exceptions pour gérer les incidents lors de l'éxécution du code.
Ca n'a de mon point de vue aucun sens de générer une exception pour une erreur de parsing ou parce qu'un argument du mauvais type est passé à une méthode, puisque ce type d'erreur doit être corrigé avant la mise en oeuvre du code.
16 De desfrenes - 13/03/2010, 13:53
Je n'aurai jamais cru que tu défendrais un jour une des nombreuses bizarreries de php.
"erreur de parsing"
détectée avant exécution, donc pas grand chose à voir avec la choucroute.
"Ca n'a de mon point de vue aucun sens"
gérer deux mécanismes d'erreurs ça en a plus ? C'est quand même *très* personnel comme sens.
"parce qu'un argument du mauvais type est passé à une méthode"
Il y a les exceptions de la SPL, c'est fait pour ça. (InvalidArgumentException, BadFunctionCallException, etc). Je ne vois pas l'intérêt en 2010 de ne pas les utiliser. Un peu de nostalgie peut-être ?
"ce type d'erreur doit être corrigé avant la mise en oeuvre du code"
Ah oui, et dans un monde idéal un programme ne devrait pas avoir d'erreur... sauf que ça n'existe pas. Et je préfère mille fois que toutes les erreurs non prévues finissent par être attrappées par un gestionnaire qui terminera proprement l'appli sans faire peur à l'utilisateur et préviendra le mainteneur plutôt que de montrer une page blanche et espérer que quelqu'un lise l'error_log. Tu me diras qu'il y a set_error_handler pour ça.... super, faut faire le boulot une deuxième fois avec set_exception_handler.
J'arrête là, je ne crois pas qu'on tombera d'accord. J'aimerai quand même que tu me dises où tu as vu un truc pareil ailleurs que dans PHP et sinon à quel moment ça a pu te manquer.
17 De mageekguy - 13/03/2010, 15:38
@desfresnes:
Si tu arrives à m'expliquer l'intêret de catcher une erreur de conception, on pourra éventuellement tomber d'accord ;).
18 De NiKo - 13/03/2010, 19:41
> La directive html_errors de ton php.ini est ton amie, pour les erreurs au format html.
Non mais quel langage de merde !
> Après tout, si elle est fatal, ce n'est pas pour rien
Ça serait tellement mieux qu'elle ne le soit pas, fatale, justement. Imagine tu veux parser un script php pour valider son executabilité : ben en php, tu peux pas, où alors à grand renfort d'exec ou je ne sais trop quelle autre horreur. C'est con hein ?
Perso je trouve qu'on devrait toujours pouvoir se sortir de n'importe quel situation en attrapant une exception justement. Pour une parse error, ben pour afficher un message d'erreur suivi d'un exit, pourquoi pas, où est le pb ? Qui peut le plus peut le moins non ?
19 De metagoto - 15/03/2010, 06:59
Pour "parser un script php pour valider son executabilité", il y a l'extension Runkit. OK, cette extension est à l'abandon. C'est vrai que cette feature manque cruellement. Par chance, il me semble qu'un mode "sandbox" natif est à l'étude. C'est dans la todo list de php 6. Donc dans 5 ou 6 ans, ça devrait être OK!
A part ça, je suis globalement d'accord avec @desfrenes quand il dit que "php c'est de la merde". Oh et puis @NiKo aussi avec son "Non mais quel langage de merde !". En ce qui me concerne, erreur vs. exception c'est insignifiant, car noyé dans la masse.
Pourquoi ne pas utiliser autre chose que php si vous trouvez ce langage merdique ?
20 De mageekguy - 15/03/2010, 09:18
Pendant un temps, il a existé la fonction
php_check_syntax()
, qui s'acquitait très bien de cette fameuse tâche consistant à vérifier la validité d'un code php.Puis, elle a disparu.
Je n'en ai jamais connu la raison.
Apparament, ca posait des problèmes.
Lesquels ? Bonne question... mais je dirais que ca devait être un méchant hack aux effets de bord pervers et que personne n'a réussit à trouver un correctif passable.
A l'époque ca n'a pas fait grand bruit, c'est passé comme une lettre à la poste et rien n'a plus jamais bougé à ce niveau depuis.
C'est d'ailleurs l'une des raisons d'être de ce blog : Faire bouger et/ou évoluer PHP en faisant réagir la communauté à propos de ses faiblesses, de fonctionnalités qui disparaissent sans raison ou de choix inadéquats de la part des concepteurs.
Je ne dis pas "PHP c'est de la merde" dans le simple but de troller, c'est bien mal me connaître.
Mon but est, entre autre, de faire réagir la communauté au sujet de certain aspect du langage
très merdique chiantmal conçu.Et je me permet de le faire parce que justement je suis un utilisateur de PHP depuis longtemps et que je le connais très bien.
S'il y a bien des gens qui peuvent se permettre de dire que PHP, c'est de la merde, c'est bien ceux qui l'utilisent depuis longtemps professionnellement et qui en connaissent les forces, et il en a pas mal, mais aussi les faiblesses, et dans ce domaine aussi, il n'est pas mauvais du tout non plus.
Et c'est peut être pour la même raison que d'autres reprennent mon discours, sous une forme ou une autre.... ou pas ;).
Evidement, je ne peux pas quantifier mon impact, qui doit être proche du négligeable, mais au moins, j'agis et du coup, je n'ai pas de remords.
21 De desfrenes - 15/03/2010, 12:48
"Pourquoi ne pas utiliser autre chose que php si vous trouvez ce langage merdique?"
Le _langage_ est effectivement merdique, mais le langage n'est pas tout.
22 De metagoto - 16/03/2010, 07:13
"Evidement, je ne peux pas quantifier mon impact, qui doit être proche du négligeable, mais au moins, j'agis et du coup, je n'ai pas de remords."
Moi mon impact est énorme, d'où mon devoir de réserve
Au dela du langage, un peu merdique, on est d'accord @desfrenes, c'est le PHPGroup que je trouve encore plus navrant. Par exemple le vote négatif de la short syntax pour les arrays [machin,truc] ça m'est resté en travers de la gorge.
23 De mageekguy - 16/03/2010, 09:12
@metagoto:
Aaaahhhh le phpGroup... on pourrait en écrire des tonnes à son sujet... mais à la réfléxion, la mailing-list internals parle d'elle-même (malheureusement).
Enfin, ca fait un bon moment que j'ai décroché, alors ca a peut être changé.
24 De tight - 17/03/2010, 09:11
@fch
En fait, mon exemple est nul -.-v
Ce que je voulais dire, c'est que trop souvent, je me retrouve à faire un test et un @ pour lancer une exception derrière, du style
if (false === $file = @fopen('foo', 'r'))
{
throw new ...Exception(...);
}