Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

De l'usage des exceptions

106 réponses
Avatar
Guillaume Gourdin
Bonjour à tous,

selon ma (modeste) expérience, les exceptions en C++sont très largement sous
utilisées, et on en reste (me semble t-il) toujours à la bonne vieille
méthode du retour d'un code d'erreur. Je suis un peu surpris de cet état de
fait, les exceptions étant supposées apporter une gestion plus performantes
des erreurs. J'ai dons quelques questions: est-il vrai que les exceptions
sont sous utilisées? Quels sont vos retours d'expérience? Ou bien y a t'il
une raison plus profonde à la sous-utilisation des exceptions?

Merci!

- Guillaume -

10 réponses

Avatar
Michael Doubez
On 4 juil, 22:21, Fabien LE LEZ wrote:
On Sat, 04 Jul 2009 16:22:43 +0200, Wykaaa :

>> tentative de prendre le cinquième élément d'un tableau qui n'en
>> comporte que trois, etc.
>L'exemple du tableau est plutôt un bug de programmation.

T'es sûr ?

Imagine le cas suivant : j'ai chargé un fichier ligne par ligne dans
un vector<string>. Les spécifications de ce fichier indiquent
clairement qu'il doit contenir 5 lignes. Si le fichier est mal formé,
je ne peux qu'arrêter le programme.

Je pourrais écrire :

if (lignes.size() < 5)
   throw quelque_chose;
f (lignes[4]);

Sauf que... la fonction at() fait déjà ça pour moi ! Pourquoi
réinventer la roue ?



Parceque plus tu t'éloigne de la source, plus il est difficile de
trouver l'origine de l'erreur.

Ton 5 ième élément peut très bien n'être accédé que dans des cas
particulier (donc tu as intérèt à avoir une couverture de test
exhaustive). Et dans le cas où ça arrive, il faut pouvoir retracer
l'erreur au fait que le fichier est mal formé (et pas que les données
sont modifiées entre temps).

D'ailleurs, at() lance une exception qui hérite de std::logic_error c-
à-d une erreur dans la logique interne du programme, par une erreur de
format d'un fichier externe au programme.

--
Michael
Avatar
Gabriel Dos Reis
Wykaaa writes:

| Gabriel Dos Reis a écrit :
| > Amrein-Marie Christophe writes:
| >
| > | Gabriel Dos Reis wrote:
| > | | > Wykaaa writes:
| > | > | > [...]
| > | > | > | C'est une question de méthodologie, de lisibilité e t de
| > maintenabilité.
| > | > | De plus, on peut facilement changer le catch au profit de la capt ure
| > | > | d'une exception plus générale que l'exception spéc ifique qu'on a
| > | > | "attrapé" dans la première version d'un logiciel.
| > | > | > Et il savoir apprécier le cas où un code d'erreur de retour
| > est
| > | > préférable à une exception.
| > | > | > -- Gaby
| > | | Personnellement, depuis que j'ai touché à Java et .Net, j e gère
| > les erreurs
| > | en C++ sous forme d'exceptions. Toujours.
| > | | C'est deux façons différentes de traiter les erreurs et o n est
| > libre de
| > | faire comme on veut mais franchement, de mon point de vu, on a beau a voir
| > | le choix, le code est plus propre et plus flexible avec les exception s.
| > | | A chacun son truc.
| >
| > Une erreur courante chez les nouveaux convertis, c'est de croire que
| > l'un des mécanismes est universellement supérieur à l'au tre.
| >
| > -- Gaby
|
| Ok, mais en l'occurrence c'est le cas.

Parce que tu le dis ? Ou parce que tu offres des arguments rationnels ?

| Je dirai même que le traitement
| par les exceptions est INFINIMENT supérieur à la méthode d es codes
| d'erreurs. D'ailleurs tous les langages "modernes" ont une syntaxe
| pour le traitement des exceptions.

Et donc ?
(offrir != obliger).

| C'est même un critère de choix de langage dans beaucoup de mil ieux.

-- Gaby
Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| ld writes:
|
| > On 6 juil, 10:24, James Kanze wrote:
| > > On Jul 5, 7:01 pm, Gabriel Dos Reis wrote:
| > >
| > > > James Kanze writes:
| > > > [...]
| > > > > > > D'ailleurs, par défaut, les iostream ne lancent pas
| > > > > > > d'exception en cas d'erreur.
| > > > > > C'est un tort !
| > > > > Tu rigoles, non ? Tu ne vas pas dire qu'une erreur de format
| > > > > dans une entrée d'utilisateur est un cas « exceptionnel ». Ou
| > > > > arriver à la fin du fichier.
| > > > À noter cependant que les IOStreams peuvent lever des
| > > > exceptions, si on le désire.
| > >
| > > Certes. Si ça a un sens, c'est une autre question -- une
| > > exception si le eofbit est positionné n'a jamais de sens,
| >
| > Tu viens de donner toi-meme un exemple ou ca a un sens: un parser
| > descendant. Si le parser voit eofbit alors qu'il a des regles "en
| > cours", c'est que le format des donnees est incorrect. Donc dans un
| > cas (regles terminees), le eofbit n'est pas une erreur alors que dans
| > l'autre cas (format invalide), c'est une erreur normalement
| > exceptionnelle. On peut evidement mettre le parseur dans etat special
| > (son propre badbit) et le retouner a tous les etages. Mais comme tu
| > l'as dit, c'est un cas typique ou les exceptions simplifient le code
| > de gestion des erreurs.
|
| Les parseurs que j'ai ecrits devaient de toute maniere gerer le cas
| d'erreur de format et donner un message d'erreur comprehensible par
| l'utilisateur. Faire un cas particulier pour la fin de fichier ne me semb le
| pas simplifier les choses (on peut envisager une exception pour traiter
| l'erreur, mais elle ne sera pas jetee par les streams).

Il y a certaines techniques de « parsing » pour lesquelles, une e rreur
locale est juste un échec d'une certaine règle, mais par forcà ©ment ine
erreur globale -- je crois que c'est ce que voulait dire Laurent.
Un exemple de telles techniques est « parser combinators » -- c'e st
descendant (et récursiv aussi) où les « échecs peuvent être transformés
en succès ».

-- Gaby
Avatar
Gabriel Dos Reis
Michael Doubez writes:

[...]

| En pratique, j'ai pas vu d'exemple de logiciel critique utilisant les
| exceptions mais je sais que MISRA C++ a des recommandations à ce suj et
| (en particulier que la racine du programme doit attraper toutes les
| exceptions).
|
| A noter que meme JSF C++ a bannis les exceptions. Le probabilité d'en
| trouver dans le code d'une fusée est mince.

Oui. Mais la dernière fois que j'ai discuté avec quelqu'un direc tement
impliqué dans la certification des codes, il meurt de l'opportunità © de
pouvoir utiliser les exceptions -- cela lui simplifierait
largement les codes, et la certification d'autres codes (e.g. la
certification de la propogation des codes d'erreur). C'est pour cela
qu'il est prêt à financer des projets pour étudier des mà ©canismes
d'exception avec temps de réponse bornés.

-- Gaby
Avatar
Sylvain SF
James Kanze a écrit :

En général, je crois qu'il y a trois types d'erreur :

-- Les erreurs « attendues ». Dans un certain sens, ce ne sont
pas des erreurs, puisqu'on s'y attend, ou qu'on doit s'y
attendre. Ou plutôt, elles sont des erreurs de la part de
l'utilisateur : des fautes de frappe en entrée, par exemple.
En général, traiter ces erreurs doit faire partie de
l'« algorithme », ce qui fait que la meilleur façon de les
annoncer, c'est par un code de retour.



je suis d'accord mais cela n'exclut pas un traitement local
par exception.
tu indiquais dans un autre post (ce ne sont pas tes mots exacts
mais ce n'est pas important je pense) que le traitement par exceptions
a tendance à être fait à distance de la source de l'erreur; il n'y
a aucun obligation à cela; on peut par exemple imaginer un parser
(traitant d'une ligne fichier ou d'une saisie utilisateur) qui
s'interromprait par exception et retournerait une erreur unique,
ceci afin de simplifier l'écriture du code de sortie.
eg.

int foo(string const& input){
try {
int x1, x2, ...;
input >> x1;
if (!(condition on x1))
throw 1;
input >> x2;
if (!(condition on x2))
throw 2;
...
}
catch (EOFReached eof){
// clean-up, logs, ...
return NN;
}
catch (int err){
// clean-up relevant for all errors, logs, ...
return err;
}
return 0;
}

-- Les erreurs « exceptionnelles ». Ce sont des erreurs
auxquelles on ne s'attend pas normalement, mais qu'on sait
peuvent arriver, et qu'on peut vouloir traiter, mais à un
niveau plus élevé, loin d'où l'erreur est detectée. Ce sont
les erreurs pour lesquelles les exceptions conviennent.



tu mêles deux aspects AMA, le fait que l'erreur soit de faible
probabilité et le fait que son traitement ne soit possible qu'à
un niveau plus élevé.
sur un OS moderne swappant à loisir, je ne m'attends pas à ce
qu'un new échoue par manque de mémoire, pourtant je vais le
tester au plus prêt; d'un autre coté, il y a en effet des
opérations (des séquences) dont le rollback ne peut être fait
qu'en amont (qu'à un niveau assez haut) .

-- Les erreurs « impossible ». Ce sont des erreurs qui ne
peuvent pas arriver, tant que le hardware marche et qu'il
n'y a pas d'erreur dans le code. Une violation d'un
invariant, par exemple, ou une faute de parité mémoire
(panne ou défaillance hardware). En général, devant de
telles erreurs, on ne peut rien, et il faut mieux avorter le
programme le plus vite possible.



tu dis bien "en général", il reste des cas où des erreurs de ce
type (on parlait des VMError, pas spécifiquement de plantes
matérielles irrécupérables) peuvent et doivent être traitées
(par exemple une stack overflow).

Mais une telle classification (encore si généralement reconnu
par les experts) est assez catégorique. D'une part, selon
l'application, la même erreur peut être considérer dans une
catégorie ou dans une autre -- considérons un serveur LDAP, qui
traite des requêtes arbitraires formulées en ASN.1, avec un
parseur à déscent récursif pour les interprêter. Comment
catégoriser un débordement de pile dans le parseur Logiquement,
selon la description ci-dessus, c'est une erreur à laquelle il
faut s'y attendre, puisqu'il faut s'attendre à tout d'un
utilisateur. Pratiquement, en revanche, le seul traitement
possible, c'est d'avorter la requête entière, c-à-d de le
traiter à un niveau bien plus élevé dans la pile d'appels, ce
qui argue très fortement pour une exception. Et dans bien des
cas, pratiquement, on ne va pas pouvoir le detecter, même si
elle se produit, parce qu'on ne sait pas (au niveau C++)
détecter un débordement de pile -- du coup, elle devient
« impossible » (et dans la pratique, sous Windows ou Unix, fera
avorter le programme).



je suis d'accord, mais le même parser ASN.1 en JavaCard (qui
a une pile réduite et ne devrait pas tenter le récursif mais
ne dispose pas non plus d'arithmétique de pointeurs pour
linéariser certains algos etc) devra catcher cette stack
overflow pour mettre de coté une des sous-séquence ASN et
recommencer le parsing.

Et il y a des considérations très pragmatiques aussi dans
certains cas. Des fonctions comme les constructeurs ou les
opérateurs surchargés ne peuvent pas renvoyer un code de retour.



oui, tel l'exemple ci-avant auquel je pensais avant de lire
ces lignes.

Sylvain.
Avatar
James Kanze
On Jul 6, 10:31 pm, Sylvain SF wrote:
James Kanze a écrit :
> En général, je crois qu'il y a trois types d'erreur :



> -- Les erreurs « attendues ». Dans un certain sens, ce ne sont
> pas des erreurs, puisqu'on s'y attend, ou qu'on doit s'y
> attendre. Ou plutôt, elles sont des erreurs de la part de
> l'utilisateur : des fautes de frappe en entrée, par exemple.
> En général, traiter ces erreurs doit faire partie de
> l'« algorithme », ce qui fait que la meilleur façon de les
> annoncer, c'est par un code de retour.



je suis d'accord mais cela n'exclut pas un traitement local
par exception.



Si on n'a pas le choix. En général, un « if », c'est bien plus
clair et plus lisible qu'un bloc de try (et moins contraignant
en ce qui concerne la portée des variables).

tu indiquais dans un autre post (ce ne sont pas tes mots
exacts mais ce n'est pas important je pense) que le traitement
par exceptions a tendance à être fait à distance de la source
de l'erreur; il n'y a aucun obligation à cela;



Il faut quand même un bloc séparé, avec un scope supplémentaire.
Mais sinon, certes, il n'y a aucun obligation : on n'est jamais
obligé à faire simple quand on peut faire compliqué. N'empêche
que l'utilisation d'une exception a un coût signifiant en ce qui
concerne la lisibilité du code ; c'est un coût qu'on accepte si
elle apporte quelque chose de plus par ailleur, comme c'est le
cas si le traitement est éloigné, ou dans le cas des
constructeurs, ou des opérateurs surchargés. Ce n'est pas le cas
pour les utilisations simples, où l'exception n'est qu'une
complication supplémentaire.

on peut par exemple imaginer un parser (traitant d'une ligne
fichier ou d'une saisie utilisateur) qui s'interromprait par
exception et retournerait une erreur unique, ceci afin de
simplifier l'écriture du code de sortie. eg.



On pourrait bien imaginer le cas d'un parseur à déscente
récursive qui avorte le traitement (du fichier, voire même de la
ligne) dans le cas d'erreur. Dans de tels cas, une exception
pour l'erreur pourrait se justifier, puisque l'exception
s'occupe automatiquement de déballer la pile, quelque soit sa
profondeur.

int foo(string const& input){
try {
int x1, x2, ...;
input >> x1;
if (!(condition on x1))
throw 1;
input >> x2;
if (!(condition on x2))
throw 2;
...
}
catch (EOFReached eof){
// clean-up, logs, ...
return NN;
}
catch (int err){
// clean-up relevant for all errors, logs, ...
return err;
}
return 0;
}



C'est déjà trop compliqué pour une seule fonction.

> -- Les erreurs « exceptionnelles ». Ce sont des erreurs
> auxquelles on ne s'attend pas normalement, mais qu'on sait
> peuvent arriver, et qu'on peut vouloir traiter, mais à un
> niveau plus élevé, loin d'où l'erreur est detectée. Ce sont
> les erreurs pour lesquelles les exceptions conviennent.



tu mêles deux aspects AMA, le fait que l'erreur soit de faible
probabilité et le fait que son traitement ne soit possible
qu'à un niveau plus élevé.



C'est pourquoi le « en général ». Dans la pratique, chaque cas
est un cas en soi, et à peu près la seule chose qu'on peut dire
de façon général, c'est « ça dépend ». Souvent (typiqueme nt ?),
les erreurs exceptionnelles sont aussi celles qu'il faut traiter
à un niveau bien plus élevé. Mais c'est sûr qu'il y a des
exceptions : si on ne veut pas continuer dans un parseur à
descente récursive, l'erreur doit bien se propager jusqu'en
haut, et les exceptions me paraît bien indiqué pour ça, même si
l'erreur est attendu.

sur un OS moderne swappant à loisir, je ne m'attends pas à ce
qu'un new échoue par manque de mémoire, pourtant je vais le
tester au plus prêt; d'un autre coté, il y a en effet des
opérations (des séquences) dont le rollback ne peut être fait
qu'en amont (qu'à un niveau assez haut) .



Pourquoi le tester au plus près ? Si new échoue, il lève une
exception. Le rollback se fait dans les destructeurs, au fur et
à mesure qu'on remonte la pile. (Une des vraies forces de C++,
c'est la possibilité d'utiliser les destructeurs pour gerer les
transactions. Si le destructeur est appelé avant commit(), il
effectue un rollback.)

> -- Les erreurs « impossible ». Ce sont des erreurs qui ne
> peuvent pas arriver, tant que le hardware marche et qu'il
> n'y a pas d'erreur dans le code. Une violation d'un
> invariant, par exemple, ou une faute de parité mémoire
> (panne ou défaillance hardware). En général, devant de
> telles erreurs, on ne peut rien, et il faut mieux avorter le
> programme le plus vite possible.



tu dis bien "en général", il reste des cas où des erreurs de ce
type (on parlait des VMError, pas spécifiquement de plantes
matérielles irrécupérables) peuvent et doivent être traitées
(par exemple une stack overflow).



Stack overflow est un problème ardu. Je suis bien d'accord qu'il
y a des cas où une exception serait la meilleur solution -- le
parseur à descente récursive, de nouveau. C'est même mon exemple
préféré d'où le choix est complexe et ambigu. Et qu'une solution
pragmatique s'impose : on choisit la solution la plus simple qui
remplit les critères.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jul 6, 11:53 am, ld wrote:
On 6 juil, 10:24, James Kanze wrote:



> On Jul 5, 7:01 pm, Gabriel Dos Reis wrote:



> > James Kanze writes:
> > [...]
> > > > > D'ailleurs, par défaut, les iostream ne lancent pas
> > > > > d'exception en cas d'erreur.
> > > > C'est un tort !
> > > Tu rigoles, non ? Tu ne vas pas dire qu'une erreur de format
> > > dans une entrée d'utilisateur est un cas « exceptionnel ». Ou
> > > arriver à la fin du fichier.
> > À noter cependant que les IOStreams peuvent lever des
> > exceptions, si on le désire.



> Certes. Si ça a un sens, c'est une autre question -- une
> exception si le eofbit est positionné n'a jamais de sens,



Tu viens de donner toi-meme un exemple ou ca a un sens: un
parser descendant. Si le parser voit eofbit alors qu'il a des
regles "en cours", c'est que le format des donnees est
incorrect.



Tout ce que le eofbit signifie, c'est que le istream a vu la fin
de fichier, peut-être dans son look-ahead à lui. Il n'a de
signification pour le client qu'après l'échec d'une lecture (et
c'est surtout une signification inversée -- s'il n'est pas
positionné, alors que failbit l'est, c'est qu'il y a une erreur
de format dans le fichier). La raison pourquoi il ne fait jamais
de sens qu'il génère une exception, c'est précisement parce
qu'il ne signifie rien pour le client, qu'il peut être
positionné d'une façon un peu aléatoire, non selon ce qu'on
vient de lire (ou qu'on vient d'essayer à lire), mais selon ce
qui suit dans le fichier, et même la façon que istream
fonctionne internellement.

Donc dans un cas (regles terminees), le eofbit n'est pas une
erreur alors que dans l'autre cas (format invalide), c'est une
erreur normalement exceptionnelle. On peut evidement mettre le
parseur dans etat special (son propre badbit) et le retouner a
tous les etages. Mais comme tu l'as dit, c'est un cas typique
ou les exceptions simplifient le code de gestion des erreurs.



Certes, mais même dans ce cas-là, je ne vois pas d'exception en
provenance d'istream. Tout au plus quelque chose du genre :

// Ici, il nous faut un entier...
int quelqueChose ;
source >> quelqueChose ;
if ( ! source ) {
throw ParserError( "integral value needed" ) ;
}

Arriver en haut avec un std::ios::failure et le failbit
positionné dans le flux, et à peu près tout ce que je peux
faire pour signaler l'erreur, c'est de sortir un "?" (comme ed,
dans le temps).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jul 6, 2:08 pm, Wykaaa wrote:
James Kanze a écrit :
>>> D'une part, les exceptions n'existent pas en C, et leur
>>> support en C++ est "récent". Du coup, les gens qui
>>> programment toujours soit en C, soit en C++ "ancien", on du
>>> mal à s'y faire. De plus, beaucoup de bibliothèques, écrites
>>> en C, ne gèrent pas les exceptions.
>> Qu'entends-tu par "récent" ?
>> Ca existait déjà dans le C++ au moins en 1990...



> Ah bon. Dans quel compilateur ? Certainement g++. Ni CFront.
> Ni Zortech.



Dans mon cours C++ de 90, les exceptions étaient déjà traitées
en détail et les compilateurs des constructeurs (Sun, HP, IBM
au moins) les traitaient. Le compilateur Borland les traitait
également. Remarque : Zortech, c'est avant 90 non ? plutôt
88.



La première publication sur la *possibilité* d'exceptions en C++
date de 1989 ("Exception Handling for C++", de Koenig et
Stroustrup). Les premières implémentations (Lucid, je crois)
date de 1992, et pendant longtemps, les exceptions restaient
rare. CFront ne les a jamais supporté (à part une modification
fait par HP pour son propre compilateur), Zortech ne les a
jamais supporté, Borland ne s'est mis à les supporter qu'assez
tardivement, Microsoft et g++ encore plus tardivement (2.8 ou
2.9 pour g++ ? C-à-d environ 1998 ou 1999).

Dans la pratique, dans l'industrie, on n'a pu réelement
commencer à se servir des exceptions que vers 2000 (plus ou
moins un an ou deux, selon les besoins de portabilité et de
fiabilité).

>>> D'autre part, il n'y a pas vraiment de consensus sur
>>> l'étendue d'utilisation des exceptions. Certains pensent
>>> qu'il faut les réserver à des cas vraiment exceptionnels,
>>> qui ne devraient pas se produire lors du déroulement
>>> normal du programme. Exemple : pas assez de mémoire pour
>>> créer un objet, tentative de prendre le cinquième élément
>>> d'un tableau qui n'en comporte que trois, etc.



>> L'exemple du tableau est plutôt un bug de programmation. Ce
>> n'est pas une situation exceptionnelle comme le "pas assez
>> de mémoire".



> Exacte. Dans la plupart des applications, il vaut mieux
> carrément avorter -- la situation ne peut pas se produire, elle
> s'est produite, on ne peut donc plus raisonner sur le code, et
> tout ce qu'on fait risque de rendre la situation pire. (Il y a
> des exceptions, évidemment. Des jeux, par exemple, mais aussi
> probablement certaines services Web non critiques.)



Il faut aussi se préoccuper des systèmes "fault tolerant".



La « fault tolerance » s'acquit grace à la rédundance. En cas
d'erreur, il faut que le processeur en cause se mette hors jeu
le plus rapidement possible, afin que d'autres puissent en
reprendre le relai. C'est l'exemple même où une exception serait
un mauvais choix pour une erreur « impossible ».

[...]
>>> Note aussi que si la fonction appelante comporte directement
>>> le code de traitement d'erreur en cas d'échec de la fonction
>>> appelée, utiliser un code de retour est plus facile. Les
>>> exceptions deviennent utiles s'il faut remonter de plusieurs
>>> appels de fonctions pour trouver le code de traitement
>>> d'erreur.



>> Je ne suis pas d'accord avec ton dernier paragraphe.



> Il a cependant clairement raison. Quelque chose comme :



> if ( someAction() != success ) {
> // traiter l'erreur...
> }



> est bien plus simple à comprendre et à maintenir que quelque
> chose du genre :



> try {
> someAction() ;
> // qui sait quoi de plus...
> } catch ( errorCode ) {
> // traiter erreur concernant someAction
> }



Ben non. Il est préférable d'utiliser la seconde forme.



Absolument pas. Distinquer les « erreurs » d'autres conditions
relève de l'obfuscation. Si l'erreur n'est pas exceptionnelle,
il ne faut pas le traiter comme si elle était.

Et si on veut traiter l'exception au plus proche de sa
survenue, on ne mettra pas "qui sait quoi de plus..." dans le
"try" !



Ce qui impose que someAction() soit dans un bloc à soi, avec son
propre portée. Quelque chose comme :

try {
MyType var = someAction() ;
} catch ...

ne va pas si var doit servir ulterieurement.

[...]
> Exactement. S'il faut gerer l'erreur tout de suite,
> l'utilisation d'une exception est à proscrire. (Il ne faut pas
> oublier qu'en fin de compte, une exception n'est autre chose
> qu'un goto maquillé.)



Oui mais c'est le compilateur qui le gère, ce qui fait toute la
différence...



Oui et non. C'est un cheminement supplémentaire, qu'on ne peut
pas negliger dans l'analyse du code.

Remarque : un if-else, génère aussi, souvent, un goto en
assembleur ainsi qu'un while, si tu vas par là. Ce n'est pas
un argument.



Un if-else est struturé. Le cheminement suite à une exception ne
l'est pas.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jul 6, 2:21 pm, Wykaaa wrote:
Michael Doubez a écrit :



[...]
Votre discussion à tous deux est intéressante mais vous
m'excuserez de jouer les trouble-fêtes car si le logiciel en
question est du guidage de missile ou du pilotage de module
lunaire ou martien, le printf("oh zut, ça a foiré") suivi de
return(ERROR) me paraît un peu léger :-)



Surtout s'il n'y a pas d'écran pour afficher le message:-).

Dans le cas des systèmes critiques, la règle absolue, c'est
d'avorter en cas de vraie erreur (cas normalement
« impossible »).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jul 6, 12:01 pm, Michael Doubez wrote:
On 5 juil, 12:07, James Kanze wrote:



> On Jul 4, 12:34 pm, "Guillaume Gourdin" wrote:



> > selon ma (modeste) expérience, les exceptions en C++sont très
> > largement sous utilisées,



> Ça dépend. D'après mon expérience, elles servent souvent trop.
[snip]
> > Quels sont vos retours d'expérience? Ou bien y a t'il une
> > raison plus profonde à la sous-utilisation des exceptions?



> Mon expérience, c'est, précisement, qu'elles sont sur-utilisées.
> Surtout parmi les programmeurs plus jeunes.



AMA il y a aussi une mode de l'expressivité d'un programme (style DSL)
et comme la gestion d'erreur brise la linéarité de l'expression, les
exceptions sont alors vues comme une solution pour /préserver/ la
lecture du programme en segmentant le programme en "logique
d'application"/"gestion d'erreur".



La linéarité de l'expression de quoi, exactement ? Très peut
d'algorithmes sont linéaire. La question est simplement si le
traitement de l'erreur fait partie de l'algorithme ou non. Ce
qui dépend de l'algorithme, et du type de l'erreur. (Dans la
pratique, quand la gestion de l'erreur ne fait pas partie de
l'algorithme, on a une facheuse tendance à l'oublier
complètement.)

Les exceptions introduisent des arcs supplémentaires dans la
graphe du flux du programme, ce qui complique l'analyse. Il y a
des façons à les traiter autrement, mais elles sont peu connues,
et sont des analyses supplémentaires qu'il faut faire pour
s'assurer la correction du code. C'est un coût supplémentaire.
Dans les cas où les exceptions apportent une reduction des coûts
par ailleurs, bien. Sinon, non.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34