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, le s
> 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.
On Jul 6, 12:01 pm, Michael Doubez <michael.dou...@free.fr> wrote:
> On 5 juil, 12:07, James Kanze <james.ka...@gmail.com> wrote:
> > On Jul 4, 12:34 pm, "Guillaume Gourdin" <tr...@hotmail.com> 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, le s
> 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.
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, le s
> 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.
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" ) ;
}
On Jul 6, 11:53 am, ld <Laurent.Den...@gmail.com> wrote:
> On 6 juil, 10:24, James Kanze <james.ka...@gmail.com> wrote:
> > On Jul 5, 7:01 pm, Gabriel Dos Reis <g...@cs.tamu.edu> wrote:
> > > James Kanze <james.ka...@gmail.com> 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" ) ;
}
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" ) ;
}
Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
une exception et ou une fin de fichier peut etre une exception
(dependant du contexte).
if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
readString(parser)))
throw parser.error("syntax error: invalid field value");
note que c'est le parser lui-meme que je "throw", car il contient les
informations sur l'etat courant du parsing (history, location, remaining,
context) qui permet de detailler le rapport de l'erreur.
Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
une exception et ou une fin de fichier peut etre une exception
(dependant du contexte).
if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
readString(parser)))
throw parser.error("syntax error: invalid field value");
note que c'est le parser lui-meme que je "throw", car il contient les
informations sur l'etat courant du parsing (history, location, remaining,
context) qui permet de detailler le rapport de l'erreur.
Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
une exception et ou une fin de fichier peut etre une exception
(dependant du contexte).
if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
readString(parser)))
throw parser.error("syntax error: invalid field value");
note que c'est le parser lui-meme que je "throw", car il contient les
informations sur l'etat courant du parsing (history, location, remaining,
context) qui permet de detailler le rapport de l'erreur.
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.
On Jul 6, 2:08 pm, Wykaaa <wyk...@yahoo.fr> 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.
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.
Ma (longue) expérience sur la qualité du code est que, à terme
(c'est-à-dire dans la durée), il est presque toujours préférable
d'utiliser le mécanisme d'exception que les codes retour. C'est beaucoup
plus facile à maintenir et à faire évoluer.
Ma (longue) expérience sur la qualité du code est que, à terme
(c'est-à-dire dans la durée), il est presque toujours préférable
d'utiliser le mécanisme d'exception que les codes retour. C'est beaucoup
plus facile à maintenir et à faire évoluer.
Ma (longue) expérience sur la qualité du code est que, à terme
(c'est-à-dire dans la durée), il est presque toujours préférable
d'utiliser le mécanisme d'exception que les codes retour. C'est beaucoup
plus facile à maintenir et à faire évoluer.
ld writes:
> Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> une exception et ou une fin de fichier peut etre une exception
> (dependant du contexte).
Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
est plus proche de la combinaison d'un flux avec une position dans ce flu x
pour pouvoir faire du backtracking
> if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> readString(parser)))
> throw parser.error("syntax error: invalid field value");
> note que c'est le parser lui-meme que je "throw", car il contient les
> informations sur l'etat courant du parsing (history, location, remainin g,
> context) qui permet de detailler le rapport de l'erreur.
A priori, si j'ai un objet parseur qui a autant d'etat
il ne va pas etre
copiable et ne pourra pas servir comme exception.
Peut-etre que l'avoir
copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Et le throw me semble mal cadrer avec l'idee des combinateurs.
A moins de
vouloir se servir du throw ici comme on servirait en prolog d'un cut avan t
une regle qui n'est jamais acceptee.
Et quel message d'erreur obtient-on
si on n'a jamais d'exception mais que le parsing echoue?
Note que je comprends bien dans ce contexte une exception en cas d'erreur
d'IO, mais la fin de fichier me semble etre un cas ou il faut du
backtracking.
ld <Laurent.Den...@gmail.com> writes:
> Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> une exception et ou une fin de fichier peut etre une exception
> (dependant du contexte).
Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
est plus proche de la combinaison d'un flux avec une position dans ce flu x
pour pouvoir faire du backtracking
> if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> readString(parser)))
> throw parser.error("syntax error: invalid field value");
> note que c'est le parser lui-meme que je "throw", car il contient les
> informations sur l'etat courant du parsing (history, location, remainin g,
> context) qui permet de detailler le rapport de l'erreur.
A priori, si j'ai un objet parseur qui a autant d'etat
il ne va pas etre
copiable et ne pourra pas servir comme exception.
Peut-etre que l'avoir
copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Et le throw me semble mal cadrer avec l'idee des combinateurs.
A moins de
vouloir se servir du throw ici comme on servirait en prolog d'un cut avan t
une regle qui n'est jamais acceptee.
Et quel message d'erreur obtient-on
si on n'a jamais d'exception mais que le parsing echoue?
Note que je comprends bien dans ce contexte une exception en cas d'erreur
d'IO, mais la fin de fichier me semble etre un cas ou il faut du
backtracking.
ld writes:
> Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> une exception et ou une fin de fichier peut etre une exception
> (dependant du contexte).
Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
est plus proche de la combinaison d'un flux avec une position dans ce flu x
pour pouvoir faire du backtracking
> if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> readString(parser)))
> throw parser.error("syntax error: invalid field value");
> note que c'est le parser lui-meme que je "throw", car il contient les
> informations sur l'etat courant du parsing (history, location, remainin g,
> context) qui permet de detailler le rapport de l'erreur.
A priori, si j'ai un objet parseur qui a autant d'etat
il ne va pas etre
copiable et ne pourra pas servir comme exception.
Peut-etre que l'avoir
copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Et le throw me semble mal cadrer avec l'idee des combinateurs.
A moins de
vouloir se servir du throw ici comme on servirait en prolog d'un cut avan t
une regle qui n'est jamais acceptee.
Et quel message d'erreur obtient-on
si on n'a jamais d'exception mais que le parsing echoue?
Note que je comprends bien dans ce contexte une exception en cas d'erreur
d'IO, mais la fin de fichier me semble etre un cas ou il faut du
backtracking.
On 7 juil, 15:37, Jean-Marc Bourguet wrote:
> ld writes:
> > Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> > disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> > une exception et ou une fin de fichier peut etre une exception
> > (dependant du contexte).
>
> Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
> est plus proche de la combinaison d'un flux avec une position dans ce flux
> pour pouvoir faire du backtracking
le backtracking est plutot gere par le parser pour etre independant de
la nature du stream (not seekable).
> > if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> > readString(parser)))
> > throw parser.error("syntax error: invalid field value");
>
> > note que c'est le parser lui-meme que je "throw", car il contient les
> > informations sur l'etat courant du parsing (history, location, remaining,
> > context) qui permet de detailler le rapport de l'erreur.
>
> A priori, si j'ai un objet parseur qui a autant d'etat
il n'a pas "autant" d'etats? je ne comprends pas cette phrase.
> il ne va pas etre copiable et ne pourra pas servir comme exception.
il n'a pas besoin de l'etre (tout comme les streams).
Ce qui veut dire que le try-catch doit etre dans le scope de sa duree de
vie, mais ca parait plutot normal pour un parseur recursif.
> Peut-etre que l'avoir
> copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
> ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
> parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Il ne modifie pas le parseur, ce sont des combinators qui demande au
parseur de valider un input en utilisant des combinator de plus bas
niveau (char ou wchar_t). Et c'est la raison pour laquelle ils ne sont
pas membre. C'est le parseur qui track ou il en est. Libre ensuite de
convertir la validation courante en objet (type).
On 7 juil, 15:37, Jean-Marc Bourguet <j...@bourguet.org> wrote:
> ld <Laurent.Den...@gmail.com> writes:
> > Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> > disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> > une exception et ou une fin de fichier peut etre une exception
> > (dependant du contexte).
>
> Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
> est plus proche de la combinaison d'un flux avec une position dans ce flux
> pour pouvoir faire du backtracking
le backtracking est plutot gere par le parser pour etre independant de
la nature du stream (not seekable).
> > if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> > readString(parser)))
> > throw parser.error("syntax error: invalid field value");
>
> > note que c'est le parser lui-meme que je "throw", car il contient les
> > informations sur l'etat courant du parsing (history, location, remaining,
> > context) qui permet de detailler le rapport de l'erreur.
>
> A priori, si j'ai un objet parseur qui a autant d'etat
il n'a pas "autant" d'etats? je ne comprends pas cette phrase.
> il ne va pas etre copiable et ne pourra pas servir comme exception.
il n'a pas besoin de l'etre (tout comme les streams).
Ce qui veut dire que le try-catch doit etre dans le scope de sa duree de
vie, mais ca parait plutot normal pour un parseur recursif.
> Peut-etre que l'avoir
> copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
> ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
> parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Il ne modifie pas le parseur, ce sont des combinators qui demande au
parseur de valider un input en utilisant des combinator de plus bas
niveau (char ou wchar_t). Et c'est la raison pour laquelle ils ne sont
pas membre. C'est le parseur qui track ou il en est. Libre ensuite de
convertir la validation courante en objet (type).
On 7 juil, 15:37, Jean-Marc Bourguet wrote:
> ld writes:
> > Ceci dit, j'etais peut-etre hors sujet dans mes propos car comme le
> > disais Gaby, je pensais aux "parser combinator" ou un echec n'est pas
> > une exception et ou une fin de fichier peut etre une exception
> > (dependant du contexte).
>
> Mais dans ce cas, l'entree du parseur est quelque d'autres qu'un flux et
> est plus proche de la combinaison d'un flux avec une position dans ce flux
> pour pouvoir faire du backtracking
le backtracking est plutot gere par le parser pour etre independant de
la nature du stream (not seekable).
> > if (! (readInt(parser) || readFloat(parser) || readDate(parser) ||
> > readString(parser)))
> > throw parser.error("syntax error: invalid field value");
>
> > note que c'est le parser lui-meme que je "throw", car il contient les
> > informations sur l'etat courant du parsing (history, location, remaining,
> > context) qui permet de detailler le rapport de l'erreur.
>
> A priori, si j'ai un objet parseur qui a autant d'etat
il n'a pas "autant" d'etats? je ne comprends pas cette phrase.
> il ne va pas etre copiable et ne pourra pas servir comme exception.
il n'a pas besoin de l'etre (tout comme les streams).
Ce qui veut dire que le try-catch doit etre dans le scope de sa duree de
vie, mais ca parait plutot normal pour un parseur recursif.
> Peut-etre que l'avoir
> copiable sert pour le backtracking? Mais ici, j'ai plutot l'impression que
> ce sont les readXXX qui ont pour responsabilite ou de modifie l'etat du
> parseur s'ils reussissent, ou de ne pas le modifier s'ils echouent.
Il ne modifie pas le parseur, ce sont des combinators qui demande au
parseur de valider un input en utilisant des combinator de plus bas
niveau (char ou wchar_t). Et c'est la raison pour laquelle ils ne sont
pas membre. C'est le parseur qui track ou il en est. Libre ensuite de
convertir la validation courante en objet (type).
La première publication sur la *possibilité* d'exceptions en C++
date de 1989 ("Exception Handling for C++", de Koenig et
Stroustrup).
Dans la pratique, dans l'industrie, on n'a pu réelement
commencer à se servir des exceptions que vers 2000.
La première publication sur la *possibilité* d'exceptions en C++
date de 1989 ("Exception Handling for C++", de Koenig et
Stroustrup).
Dans la pratique, dans l'industrie, on n'a pu réelement
commencer à se servir des exceptions que vers 2000.
La première publication sur la *possibilité* d'exceptions en C++
date de 1989 ("Exception Handling for C++", de Koenig et
Stroustrup).
Dans la pratique, dans l'industrie, on n'a pu réelement
commencer à se servir des exceptions que vers 2000.
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é et de
| > maintenabilité.
| > | > | De plus, on peut facilement changer le catch au profit de la capture
| > | > | d'une exception plus générale que l'exception spécifique 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, je gère
| > les erreurs
| > | en C++ sous forme d'exceptions. Toujours.
| > | | C'est deux façons différentes de traiter les erreurs et on est
| > libre de
| > | faire comme on veut mais franchement, de mon point de vu, on a beau avoir
| > | le choix, le code est plus propre et plus flexible avec les exceptions.
| > | | 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'autre.
| >
| > -- 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 des 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 milieux.
-- Gaby
Wykaaa <wykaaa@yahoo.fr> writes:
| Gabriel Dos Reis a écrit :
| > Amrein-Marie Christophe <xxx@freesurf.fr> writes:
| >
| > | Gabriel Dos Reis wrote:
| > | | > Wykaaa <wykaaa@yahoo.fr> writes:
| > | > | > [...]
| > | > | > | C'est une question de méthodologie, de lisibilité et de
| > maintenabilité.
| > | > | De plus, on peut facilement changer le catch au profit de la capture
| > | > | d'une exception plus générale que l'exception spécifique 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, je gère
| > les erreurs
| > | en C++ sous forme d'exceptions. Toujours.
| > | | C'est deux façons différentes de traiter les erreurs et on est
| > libre de
| > | faire comme on veut mais franchement, de mon point de vu, on a beau avoir
| > | le choix, le code est plus propre et plus flexible avec les exceptions.
| > | | 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'autre.
| >
| > -- 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 des 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 milieux.
-- Gaby
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é et de
| > maintenabilité.
| > | > | De plus, on peut facilement changer le catch au profit de la capture
| > | > | d'une exception plus générale que l'exception spécifique 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, je gère
| > les erreurs
| > | en C++ sous forme d'exceptions. Toujours.
| > | | C'est deux façons différentes de traiter les erreurs et on est
| > libre de
| > | faire comme on veut mais franchement, de mon point de vu, on a beau avoir
| > | le choix, le code est plus propre et plus flexible avec les exceptions.
| > | | 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'autre.
| >
| > -- 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 des 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 milieux.
-- Gaby