Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
Oui, et ? Elle est détectée, pas corrigée ! La bonne façon de faire,
et dans _tous_ les langages, Java compris, c'est de commencer par
écrire les bouts de traitement des erreurs et de ne pas déléguer ce
traitement quand on aura du temps pour l'écrire !
Faux
La bonne façon de faire est d'écrire les traitements d'erreur
uniquement là où ils sont utiles (code critique) et de délégué à la
couche du dessus tout ce qu'on ne sait pas traité ou qu'il n'est pas
utile de traiter.
On se contre-fiche de la détection si on ne sait pas comment
corriger facilement.
Euh…
Comment veux-tu corriger quelque chose que tu n'as pas détecté ?
En C aussi figure-toi. On n'a pas attendu Java pour pointer les
fonctions qui renvoyaient des valeurs non utilisées.
Ah, et comment ?
void foo(…) {
int t = writeToFile(filename, data);
}
Est-ce que « t » est un code d'erreur ou la taille réelle écrite ?
void foo(…) {
int t = writeToFile(filename, data);
if ( t == ERROR_FILE_NOT_AVAILABLE ) {
…
}
}
Est-ce que tous les cas d'erreur ont été traité ?
En C, la détection d'erreur est contextuelle (dépend du caractère de
la valeur de retour, de son domaine possible…), et donc non détectable
automatiquement sans erreur.
La seule détection possible devrait analyser en profondeur le code.
Dans l'exemple précédent, elle nécessite la connaissance du code de la
fonction « writeToFile » et l'analyse de toutes les valeurs de retour
possibles.
Et même comme ça, on n'a aucun moyen de différencier « int
writeToFile(char* file, char* data, int* written) » de « int
writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
la 2nde non (taille de l'écriture).
> — sans propagation de l'erreur
Gnî ?
int foo(…) {
if ( bar() == ERROR_BAR_1 ) {
…
}
}
int bar(…) {
if ( fooBar() == ERROR_FOO_BAR_1 ) {
return ERROR_BAR_1;
}
// Oublie de ERROR_FOO_BAR_2
}
Le fait d'avoir oublié le cas ERROR_FOO_BAR_2 dans « bar » fait qu'on
a propagé l'erreur aussi dans « foo ».
Les 2 codes sont à modifier en cas de correction de « bar », sauf que
l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
sur une autre itération de relecture de code.
En Java, au pire, l'ajout d'une exception sur « bar » la fera remonter
jusqu'à ce que le compilateur geule.
La correction de TOUS les morceaux de code impactés se fera sur la
même itération de relecture.
Tu peux déjà te débrouiller
pour que la valeur de retour soit récupérée. Si après, l'utilisateur
ne la traite pas, le problème est strictement le même qu'en Java.
Non.
Tu n'as pas la possibilité de ne pas traiter une exception en Java, le
compilateur t'impose soit de la remonter au-dessus (« throw
FooException ») soit de la try-catch.
Aucune possibilité de rater une erreur ou de ne pas la traiter.
En C, pour faire plaisir à tes moulinettes de code, tu vas donc en
plus devoir au moins lire toutes les valeurs de retour de toutes tes
fonctions, et non uniquement tes codes d'erreur (aucun moyen de les
différencier facilement).
Ce qui complexifie encore le code pour que dalle.
Par exemple dans « int writeToFile(char* filename, char* data) », la
valeur de retour est totalement inutile dans 99% des cas pour la suite
du programme.
Pardon ? Ces valeurs de retour sont _normalisées_ et parfaitement
_connues_.
Ah ?
int foo(…) {
if ( bar() == ERROR_BAR ) {
…
}
}
Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
> — aucun moyen de savoir si TOUTES les fonctions appelantes traitent TOUS
> les cas d'erreur possibles de TOUTES les fonctions appelées
> il est impossible de garantir si le code qu'on a sous les yeux est
> correct ou non et s'il traite correctement les erreurs, et encore moins
> de manière automatisée.
C'est parfaitement possible. C'est même l'hygiène de base du
développeur C et pour ma part, il y a longtemps que j'ai automatisé
la tâche.
Explique-nous, Ô Grand Dieu de la programmation, comment peux-tu
détecter si le code suivant est correct :
int foobar(…) {
bar(1);
if ( foo(…) == ERROR_FOO ) {
…
}
}
Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
» et « int bar(int i) », qu'elles proviennent peut-être d'une
librairie sur étagère ou d'une autre équipe de dev.
Comment fais-tu la différence entre :
int bar(int i) {
…
if ( i > 0 ) return 1;
return -1;
}
qui conduit à un code correct (la valeur de retour n'étant pas
intéressante et pas un code d'erreur pour la suite de notre programme)
et :
int bar(int i) {
…
if ( bar1() == ERROR_BAR1 )
return ERROR_BAR;
return 0;
}
qui conduit à un code incorrect (oubli d'un cas d'erreur)
Ou encore, comment différencies-tu :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
return 0;
}
qui donne un code correct
et :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
if ( foo2() == ERROR_FOO2 )
return ERROR_FOO_1;
return 0;
}
qui le rend incorrect (oubli d'un cas d'erreur) ?
J'attend ton explication avec impatience =)
En fonction du contenu et du comportement des méthodes appelées, ton
code appelant peut être correct… ou pas =)
Donc la détection d'erreur est contextuelle et donc non automatisable.
En Java, la seule connaissance de la signature de la méthode indique
quelles erreurs sont à traiter, le code n'est pas contextuel et est
soit correct (il compile) soit non (il ne compile pas).
L'implémentation interne de la méthode appelée n'influe pas sur la
correction de la méthode appelante.
Euh... Comment dire... Tu viens de prouver en une ligne que tu n'as
aucune idée de la façon dont on fait une revue de code ou des tests
de code.
J'en passe toutes les semaines des revues de code…
Tester la remontée des erreurs en C est un truc qui se fait
à partir de macros.
Cf code du dessus…
Et tu fais comment pour les méthodes que tu n'as pas écrites toi-même
(COTS, librairies d'une autre équipe…) ?
Je ne vais pas passer deux heures à t'expliquer
comment, mais il est très simple de provoquer une erreur en C et de
voir ce qui se passe.
Ça ça s'appelle des tests U.
Et c'est même encore plus simple en Java (JUnit + EasyMock + IoC)Non. Avec quelques scripts générant des fichiers d'en-têtes, c'est même
automatique.
…
Ne me dis quand même pas que tu vas modifier des fichiers de code qui
finiront en prod pour tester ta complétitude et ta fiabilité ?
Oui, et ? Elle est détectée, pas corrigée ! La bonne façon de faire,
et dans _tous_ les langages, Java compris, c'est de commencer par
écrire les bouts de traitement des erreurs et de ne pas déléguer ce
traitement quand on aura du temps pour l'écrire !
Faux
La bonne façon de faire est d'écrire les traitements d'erreur
uniquement là où ils sont utiles (code critique) et de délégué à la
couche du dessus tout ce qu'on ne sait pas traité ou qu'il n'est pas
utile de traiter.
On se contre-fiche de la détection si on ne sait pas comment
corriger facilement.
Euh…
Comment veux-tu corriger quelque chose que tu n'as pas détecté ?
En C aussi figure-toi. On n'a pas attendu Java pour pointer les
fonctions qui renvoyaient des valeurs non utilisées.
Ah, et comment ?
void foo(…) {
int t = writeToFile(filename, data);
}
Est-ce que « t » est un code d'erreur ou la taille réelle écrite ?
void foo(…) {
int t = writeToFile(filename, data);
if ( t == ERROR_FILE_NOT_AVAILABLE ) {
…
}
}
Est-ce que tous les cas d'erreur ont été traité ?
En C, la détection d'erreur est contextuelle (dépend du caractère de
la valeur de retour, de son domaine possible…), et donc non détectable
automatiquement sans erreur.
La seule détection possible devrait analyser en profondeur le code.
Dans l'exemple précédent, elle nécessite la connaissance du code de la
fonction « writeToFile » et l'analyse de toutes les valeurs de retour
possibles.
Et même comme ça, on n'a aucun moyen de différencier « int
writeToFile(char* file, char* data, int* written) » de « int
writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
la 2nde non (taille de l'écriture).
> — sans propagation de l'erreur
Gnî ?
int foo(…) {
if ( bar() == ERROR_BAR_1 ) {
…
}
}
int bar(…) {
if ( fooBar() == ERROR_FOO_BAR_1 ) {
return ERROR_BAR_1;
}
// Oublie de ERROR_FOO_BAR_2
}
Le fait d'avoir oublié le cas ERROR_FOO_BAR_2 dans « bar » fait qu'on
a propagé l'erreur aussi dans « foo ».
Les 2 codes sont à modifier en cas de correction de « bar », sauf que
l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
sur une autre itération de relecture de code.
En Java, au pire, l'ajout d'une exception sur « bar » la fera remonter
jusqu'à ce que le compilateur geule.
La correction de TOUS les morceaux de code impactés se fera sur la
même itération de relecture.
Tu peux déjà te débrouiller
pour que la valeur de retour soit récupérée. Si après, l'utilisateur
ne la traite pas, le problème est strictement le même qu'en Java.
Non.
Tu n'as pas la possibilité de ne pas traiter une exception en Java, le
compilateur t'impose soit de la remonter au-dessus (« throw
FooException ») soit de la try-catch.
Aucune possibilité de rater une erreur ou de ne pas la traiter.
En C, pour faire plaisir à tes moulinettes de code, tu vas donc en
plus devoir au moins lire toutes les valeurs de retour de toutes tes
fonctions, et non uniquement tes codes d'erreur (aucun moyen de les
différencier facilement).
Ce qui complexifie encore le code pour que dalle.
Par exemple dans « int writeToFile(char* filename, char* data) », la
valeur de retour est totalement inutile dans 99% des cas pour la suite
du programme.
Pardon ? Ces valeurs de retour sont _normalisées_ et parfaitement
_connues_.
Ah ?
int foo(…) {
if ( bar() == ERROR_BAR ) {
…
}
}
Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
> — aucun moyen de savoir si TOUTES les fonctions appelantes traitent TOUS
> les cas d'erreur possibles de TOUTES les fonctions appelées
> il est impossible de garantir si le code qu'on a sous les yeux est
> correct ou non et s'il traite correctement les erreurs, et encore moins
> de manière automatisée.
C'est parfaitement possible. C'est même l'hygiène de base du
développeur C et pour ma part, il y a longtemps que j'ai automatisé
la tâche.
Explique-nous, Ô Grand Dieu de la programmation, comment peux-tu
détecter si le code suivant est correct :
int foobar(…) {
bar(1);
if ( foo(…) == ERROR_FOO ) {
…
}
}
Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
» et « int bar(int i) », qu'elles proviennent peut-être d'une
librairie sur étagère ou d'une autre équipe de dev.
Comment fais-tu la différence entre :
int bar(int i) {
…
if ( i > 0 ) return 1;
return -1;
}
qui conduit à un code correct (la valeur de retour n'étant pas
intéressante et pas un code d'erreur pour la suite de notre programme)
et :
int bar(int i) {
…
if ( bar1() == ERROR_BAR1 )
return ERROR_BAR;
return 0;
}
qui conduit à un code incorrect (oubli d'un cas d'erreur)
Ou encore, comment différencies-tu :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
return 0;
}
qui donne un code correct
et :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
if ( foo2() == ERROR_FOO2 )
return ERROR_FOO_1;
return 0;
}
qui le rend incorrect (oubli d'un cas d'erreur) ?
J'attend ton explication avec impatience =)
En fonction du contenu et du comportement des méthodes appelées, ton
code appelant peut être correct… ou pas =)
Donc la détection d'erreur est contextuelle et donc non automatisable.
En Java, la seule connaissance de la signature de la méthode indique
quelles erreurs sont à traiter, le code n'est pas contextuel et est
soit correct (il compile) soit non (il ne compile pas).
L'implémentation interne de la méthode appelée n'influe pas sur la
correction de la méthode appelante.
Euh... Comment dire... Tu viens de prouver en une ligne que tu n'as
aucune idée de la façon dont on fait une revue de code ou des tests
de code.
J'en passe toutes les semaines des revues de code…
Tester la remontée des erreurs en C est un truc qui se fait
à partir de macros.
Cf code du dessus…
Et tu fais comment pour les méthodes que tu n'as pas écrites toi-même
(COTS, librairies d'une autre équipe…) ?
Je ne vais pas passer deux heures à t'expliquer
comment, mais il est très simple de provoquer une erreur en C et de
voir ce qui se passe.
Ça ça s'appelle des tests U.
Et c'est même encore plus simple en Java (JUnit + EasyMock + IoC)
Non. Avec quelques scripts générant des fichiers d'en-têtes, c'est même
automatique.
…
Ne me dis quand même pas que tu vas modifier des fichiers de code qui
finiront en prod pour tester ta complétitude et ta fiabilité ?
Oui, et ? Elle est détectée, pas corrigée ! La bonne façon de faire,
et dans _tous_ les langages, Java compris, c'est de commencer par
écrire les bouts de traitement des erreurs et de ne pas déléguer ce
traitement quand on aura du temps pour l'écrire !
Faux
La bonne façon de faire est d'écrire les traitements d'erreur
uniquement là où ils sont utiles (code critique) et de délégué à la
couche du dessus tout ce qu'on ne sait pas traité ou qu'il n'est pas
utile de traiter.
On se contre-fiche de la détection si on ne sait pas comment
corriger facilement.
Euh…
Comment veux-tu corriger quelque chose que tu n'as pas détecté ?
En C aussi figure-toi. On n'a pas attendu Java pour pointer les
fonctions qui renvoyaient des valeurs non utilisées.
Ah, et comment ?
void foo(…) {
int t = writeToFile(filename, data);
}
Est-ce que « t » est un code d'erreur ou la taille réelle écrite ?
void foo(…) {
int t = writeToFile(filename, data);
if ( t == ERROR_FILE_NOT_AVAILABLE ) {
…
}
}
Est-ce que tous les cas d'erreur ont été traité ?
En C, la détection d'erreur est contextuelle (dépend du caractère de
la valeur de retour, de son domaine possible…), et donc non détectable
automatiquement sans erreur.
La seule détection possible devrait analyser en profondeur le code.
Dans l'exemple précédent, elle nécessite la connaissance du code de la
fonction « writeToFile » et l'analyse de toutes les valeurs de retour
possibles.
Et même comme ça, on n'a aucun moyen de différencier « int
writeToFile(char* file, char* data, int* written) » de « int
writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
la 2nde non (taille de l'écriture).
> — sans propagation de l'erreur
Gnî ?
int foo(…) {
if ( bar() == ERROR_BAR_1 ) {
…
}
}
int bar(…) {
if ( fooBar() == ERROR_FOO_BAR_1 ) {
return ERROR_BAR_1;
}
// Oublie de ERROR_FOO_BAR_2
}
Le fait d'avoir oublié le cas ERROR_FOO_BAR_2 dans « bar » fait qu'on
a propagé l'erreur aussi dans « foo ».
Les 2 codes sont à modifier en cas de correction de « bar », sauf que
l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
sur une autre itération de relecture de code.
En Java, au pire, l'ajout d'une exception sur « bar » la fera remonter
jusqu'à ce que le compilateur geule.
La correction de TOUS les morceaux de code impactés se fera sur la
même itération de relecture.
Tu peux déjà te débrouiller
pour que la valeur de retour soit récupérée. Si après, l'utilisateur
ne la traite pas, le problème est strictement le même qu'en Java.
Non.
Tu n'as pas la possibilité de ne pas traiter une exception en Java, le
compilateur t'impose soit de la remonter au-dessus (« throw
FooException ») soit de la try-catch.
Aucune possibilité de rater une erreur ou de ne pas la traiter.
En C, pour faire plaisir à tes moulinettes de code, tu vas donc en
plus devoir au moins lire toutes les valeurs de retour de toutes tes
fonctions, et non uniquement tes codes d'erreur (aucun moyen de les
différencier facilement).
Ce qui complexifie encore le code pour que dalle.
Par exemple dans « int writeToFile(char* filename, char* data) », la
valeur de retour est totalement inutile dans 99% des cas pour la suite
du programme.
Pardon ? Ces valeurs de retour sont _normalisées_ et parfaitement
_connues_.
Ah ?
int foo(…) {
if ( bar() == ERROR_BAR ) {
…
}
}
Sachant que « bar » provient d'une librairie dont tu n'as pas
forcément les sources, as-tu oublié des cas d'erreur ?
Aucun moyen de le savoir sauf à lire la doc en espérant qu'elle soit
complète…
> — aucun moyen de savoir si TOUTES les fonctions appelantes traitent TOUS
> les cas d'erreur possibles de TOUTES les fonctions appelées
> il est impossible de garantir si le code qu'on a sous les yeux est
> correct ou non et s'il traite correctement les erreurs, et encore moins
> de manière automatisée.
C'est parfaitement possible. C'est même l'hygiène de base du
développeur C et pour ma part, il y a longtemps que j'ai automatisé
la tâche.
Explique-nous, Ô Grand Dieu de la programmation, comment peux-tu
détecter si le code suivant est correct :
int foobar(…) {
bar(1);
if ( foo(…) == ERROR_FOO ) {
…
}
}
Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
» et « int bar(int i) », qu'elles proviennent peut-être d'une
librairie sur étagère ou d'une autre équipe de dev.
Comment fais-tu la différence entre :
int bar(int i) {
…
if ( i > 0 ) return 1;
return -1;
}
qui conduit à un code correct (la valeur de retour n'étant pas
intéressante et pas un code d'erreur pour la suite de notre programme)
et :
int bar(int i) {
…
if ( bar1() == ERROR_BAR1 )
return ERROR_BAR;
return 0;
}
qui conduit à un code incorrect (oubli d'un cas d'erreur)
Ou encore, comment différencies-tu :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
return 0;
}
qui donne un code correct
et :
int foo(…) {
…
if ( foo1() == ERROR_FOO1 )
return ERROR_FOO;
if ( foo2() == ERROR_FOO2 )
return ERROR_FOO_1;
return 0;
}
qui le rend incorrect (oubli d'un cas d'erreur) ?
J'attend ton explication avec impatience =)
En fonction du contenu et du comportement des méthodes appelées, ton
code appelant peut être correct… ou pas =)
Donc la détection d'erreur est contextuelle et donc non automatisable.
En Java, la seule connaissance de la signature de la méthode indique
quelles erreurs sont à traiter, le code n'est pas contextuel et est
soit correct (il compile) soit non (il ne compile pas).
L'implémentation interne de la méthode appelée n'influe pas sur la
correction de la méthode appelante.
Euh... Comment dire... Tu viens de prouver en une ligne que tu n'as
aucune idée de la façon dont on fait une revue de code ou des tests
de code.
J'en passe toutes les semaines des revues de code…
Tester la remontée des erreurs en C est un truc qui se fait
à partir de macros.
Cf code du dessus…
Et tu fais comment pour les méthodes que tu n'as pas écrites toi-même
(COTS, librairies d'une autre équipe…) ?
Je ne vais pas passer deux heures à t'expliquer
comment, mais il est très simple de provoquer une erreur en C et de
voir ce qui se passe.
Ça ça s'appelle des tests U.
Et c'est même encore plus simple en Java (JUnit + EasyMock + IoC)Non. Avec quelques scripts générant des fichiers d'en-têtes, c'est même
automatique.
…
Ne me dis quand même pas que tu vas modifier des fichiers de code qui
finiront en prod pour tester ta complétitude et ta fiabilité ?
> Est-ce que les gens qui
> écrivent Apache (par exemple) sont des grosses quiches ? Ou est-ce
> que le fait qu'il y ait 255 trucs à se rappeler par ligne de code
> peut intervenir ?
Le problème du C n'est _pas_ là. C'est dans les dépassements
de buffer la plupart du temps, dans l'arithmétique des pointeurs (ou
dans les variables non initialisées, mais on a le même dans Java).
>> Lorsqu'il reste un pointeur quelque part qui pointe sur une
>> zone de la mémoire, cette zone n'est pas libérée. C'est un effet
>> pervers du GC, que tu le veuilles ou non. Et ce genre de bêtise est
>> très vite fait.
>
> Pas plus qu'en C. En Java on ne le fait pas partout, on se concentre
> sur les quelques ressources concernées, c'est tout. Et il y en a
> peu. Le cas que tu cites est assez rare.
Et assez pour mettre le bazar.
> Est-ce que les gens qui
> écrivent Apache (par exemple) sont des grosses quiches ? Ou est-ce
> que le fait qu'il y ait 255 trucs à se rappeler par ligne de code
> peut intervenir ?
Le problème du C n'est _pas_ là. C'est dans les dépassements
de buffer la plupart du temps, dans l'arithmétique des pointeurs (ou
dans les variables non initialisées, mais on a le même dans Java).
>> Lorsqu'il reste un pointeur quelque part qui pointe sur une
>> zone de la mémoire, cette zone n'est pas libérée. C'est un effet
>> pervers du GC, que tu le veuilles ou non. Et ce genre de bêtise est
>> très vite fait.
>
> Pas plus qu'en C. En Java on ne le fait pas partout, on se concentre
> sur les quelques ressources concernées, c'est tout. Et il y en a
> peu. Le cas que tu cites est assez rare.
Et assez pour mettre le bazar.
> Est-ce que les gens qui
> écrivent Apache (par exemple) sont des grosses quiches ? Ou est-ce
> que le fait qu'il y ait 255 trucs à se rappeler par ligne de code
> peut intervenir ?
Le problème du C n'est _pas_ là. C'est dans les dépassements
de buffer la plupart du temps, dans l'arithmétique des pointeurs (ou
dans les variables non initialisées, mais on a le même dans Java).
>> Lorsqu'il reste un pointeur quelque part qui pointe sur une
>> zone de la mémoire, cette zone n'est pas libérée. C'est un effet
>> pervers du GC, que tu le veuilles ou non. Et ce genre de bêtise est
>> très vite fait.
>
> Pas plus qu'en C. En Java on ne le fait pas partout, on se concentre
> sur les quelques ressources concernées, c'est tout. Et il y en a
> peu. Le cas que tu cites est assez rare.
Et assez pour mettre le bazar.
> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
Le Tue, 21 Jun 2011 16:46:23 -0400
Dellara a écrit :> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Son nom, tu veux dire ?Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
?
Je ne vois pas bien le rapport avec la première demande. Parce que
c'est difficile de voir à quel message ma réponse est rattachée ?
Le Tue, 21 Jun 2011 16:46:23 -0400
Dellara <paul.pygeon@gmail.com> a écrit :
> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Son nom, tu veux dire ?
Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
?
Je ne vois pas bien le rapport avec la première demande. Parce que
c'est difficile de voir à quel message ma réponse est rattachée ?
Le Tue, 21 Jun 2011 16:46:23 -0400
Dellara a écrit :> Ben je t'ai déjà répondu que le développeur pressé fera aussi des
> conneries en C, c'est pareil.
Tu sais, ce serait beaucoup mieux si tu citais le contribruiteur à
qui tu réponds.
Son nom, tu veux dire ?Cette pratique antédiluvienne consistant à obliger le
lecteur à se taper un fil interminable pour suivre la conversation
est vraiment d'un autre âge.
?
Je ne vois pas bien le rapport avec la première demande. Parce que
c'est difficile de voir à quel message ma réponse est rattachée ?
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
....
return codeErreuraLaCom;
}
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
....
return codeErreuraLaCom;
}
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
....
return codeErreuraLaCom;
}
Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
D'autre part, si tu veux être sûr de ne pas oublier
quelque chose, je te suggère de regarder du côté de switch
> En C, la détection d'erreur est contextuelle (dépend du caractère de
> la valeur de retour, de son domaine possible ), et donc non détecta ble
> automatiquement sans erreur.
Hein ?
> La seule détection possible devrait analyser en profondeur le code.
Exprime-toi en français parce que j'ai beau lire et rel ire cette
phrase, je n'en comprends toujours pas le sens.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la f onction. Point
barre.
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'er reur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est tri vial.
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu as parfaitement le droit de faire autrement, mais c'es t _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour lib érer les
ressources en cas d'erreur. C'est donc vachement compliqu é. CHECK
est une macro triviale et tout à fait maintenable.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
C'est exactement ce que je dis. Et je rajoute que le try- catch-all
est une moisissure du langage.
En C, aucune valeur de retour est inutile.
Pas possible avec le default: du switch. Si ça ne te va s pas, tu
peux aussi utiliser un else{} dans ta close if().
Et si la doc ne correspond pas à la fonction, je te rap pelle que
c'est exactement la même chose en C, C++, Fortran, Algo l, Java ou
tout langage que tu peux imaginer.
On ne parlais pas de ça, mais de codes de retour ignor és. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
> Sachant que tu n'as peut-être pas le source des fonctions « int f oo( )
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
> Comment fais-tu la différence entre :
> int bar(int i) {
>
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme )
> et :
> int bar(int i) {
>
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'obl ige à faire
attention à tes paramètres d'entrée et de sortie.
Argutie.
> Donc la détection d'erreur est contextuelle et donc non automatisable .
Non plus.
plus de détails »
Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
D'autre part, si tu veux être sûr de ne pas oublier
quelque chose, je te suggère de regarder du côté de switch
> En C, la détection d'erreur est contextuelle (dépend du caractère de
> la valeur de retour, de son domaine possible ), et donc non détecta ble
> automatiquement sans erreur.
Hein ?
> La seule détection possible devrait analyser en profondeur le code.
Exprime-toi en français parce que j'ai beau lire et rel ire cette
phrase, je n'en comprends toujours pas le sens.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la f onction. Point
barre.
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'er reur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est tri vial.
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu as parfaitement le droit de faire autrement, mais c'es t _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour lib érer les
ressources en cas d'erreur. C'est donc vachement compliqu é. CHECK
est une macro triviale et tout à fait maintenable.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
C'est exactement ce que je dis. Et je rajoute que le try- catch-all
est une moisissure du langage.
En C, aucune valeur de retour est inutile.
Pas possible avec le default: du switch. Si ça ne te va s pas, tu
peux aussi utiliser un else{} dans ta close if().
Et si la doc ne correspond pas à la fonction, je te rap pelle que
c'est exactement la même chose en C, C++, Fortran, Algo l, Java ou
tout langage que tu peux imaginer.
On ne parlais pas de ça, mais de codes de retour ignor és. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
> Sachant que tu n'as peut-être pas le source des fonctions « int f oo( )
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
> Comment fais-tu la différence entre :
> int bar(int i) {
>
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme )
> et :
> int bar(int i) {
>
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'obl ige à faire
attention à tes paramètres d'entrée et de sortie.
Argutie.
> Donc la détection d'erreur est contextuelle et donc non automatisable .
Non plus.
plus de détails »
Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
D'autre part, si tu veux être sûr de ne pas oublier
quelque chose, je te suggère de regarder du côté de switch
> En C, la détection d'erreur est contextuelle (dépend du caractère de
> la valeur de retour, de son domaine possible ), et donc non détecta ble
> automatiquement sans erreur.
Hein ?
> La seule détection possible devrait analyser en profondeur le code.
Exprime-toi en français parce que j'ai beau lire et rel ire cette
phrase, je n'en comprends toujours pas le sens.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la f onction. Point
barre.
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'er reur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est tri vial.
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu as parfaitement le droit de faire autrement, mais c'es t _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour lib érer les
ressources en cas d'erreur. C'est donc vachement compliqu é. CHECK
est une macro triviale et tout à fait maintenable.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
C'est exactement ce que je dis. Et je rajoute que le try- catch-all
est une moisissure du langage.
En C, aucune valeur de retour est inutile.
Pas possible avec le default: du switch. Si ça ne te va s pas, tu
peux aussi utiliser un else{} dans ta close if().
Et si la doc ne correspond pas à la fonction, je te rap pelle que
c'est exactement la même chose en C, C++, Fortran, Algo l, Java ou
tout langage que tu peux imaginer.
On ne parlais pas de ça, mais de codes de retour ignor és. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
> Sachant que tu n'as peut-être pas le source des fonctions « int f oo( )
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
> Comment fais-tu la différence entre :
> int bar(int i) {
>
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme )
> et :
> int bar(int i) {
>
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'obl ige à faire
attention à tes paramètres d'entrée et de sortie.
Argutie.
> Donc la détection d'erreur est contextuelle et donc non automatisable .
Non plus.
plus de détails »
On 22 juin, 13:09, JKB wrote:Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
Il ne s'agit pas de connaître uniquement le prototype de la fonction
mais la signification exacte de sa valeur de retour : est-ce une
donnée de retour ou un code d'erreur ?
le « int » de « int foo(…) » peut dénoter à la fois un code d'erreur
ou autre chose, et on ne fait pas du tout la même chose en fonction du
cas : dans le 1er la valeur DOIT être traitée, dans le 2nd, elle PEUT
être traitée (fonction de son utilité réelle dans ton code).
« int foo(…) » ne peut me renseigner seule sur l'ensemble des erreurs
potentielles. Son implémentation réelle est nécessaire ou l'accès à sa
doc (qui peut être fausse, inexistante ou incomplète).
« void foo(…) throws FileNotFoundException, IOException » contient en
elle-même toutes les infos nécessaires à un code fiable, y compris les
cas d'erreur à traiter, quelque soit l'état de sa doc (même fausse,
inexistante ou incomplète) ou la disponibilité de son code.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la fonction. Point
barre.
Non, de sa plage de valeur de retour admissible aussi.
Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est trivial.
Je te parle de la valeur de retour.
Aucun moyen de savoir si un « int » est une valeur métier ou un code
de retour…
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
Met tes switch si tu préfères, le problème reste le même.
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu ne comprends vraiment rien au problème toi…
Le problème n'est pas de savoir si « if » est meilleur que « switch »,
mais du nombre de cas à traiter pour être complet…
Le fait de ne pas être totalement couvrant dans « bar » fera qu'après
correction, toutes les méthodes appelantes de « bar » vont aussi
devenir non totalement couvrantes.
Le fait d'avoir oublié un cas dans « bar » fait qu'on en a
automatiquement oublié dans « foo » qui appelle « bar » et que
« foo », correct avec « bar » buggé, deviendra buggé avec « bar » non
buggé.
C'est ça de la propagation d'erreur : en C, le fait de corriger un
bout de code sur la gestion d'erreur t'impacte toutes tes méthodes
appelantes aussi sur la gestion d'erreur !
Tu as parfaitement le droit de faire autrement, mais c'est _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour libérer les
ressources en cas d'erreur. C'est donc vachement compliqué. CHECK
est une macro triviale et tout à fait maintenable.
Et donc tu es strictement équivalent à un catch-all Java…
Et incapable de gérer les types d'erreurs correctement.
int fooBar(…) {
…
return ERROR_FILE_UNVAILABLE;
…
return ERROR_IO_ERROR;
…
}
« CHECK(fooBar(), <...>); » te rend incapable de faire la distinction
entre une erreur fichier (le nom du fichier était incorrect) et
d'écriture (le disque est mort ?), et de réagir différemment en
conséquence.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquementC'est exactement ce que je dis. Et je rajoute que le try-catch-all
est une moisissure du langage.
Qui est strictement équivalente à ta macro « CHECK », la possibilité
de distinguer les types d'erreur en moins…
Si c'est une moississure du langage, ton code est donc une moisissure
de moisissure…
En C, aucune valeur de retour est inutile.
int write(…) {
…
return sizeWritten;
}
Celle-là est inutile potentiellement.
int write(…) {
…
return ERROR_FILE;
…
}
Celle-là est non seulement pas inutile mais en plus doit
OBLIGATOIREMENT être testée après appel !
Pas possible avec le default: du switch. Si ça ne te vas pas, tu
peux aussi utiliser un else{} dans ta close if().
Ce qui est encore plus équivalent à un try-catch en Java…
Et si la doc ne correspond pas à la fonction, je te rappelle que
c'est exactement la même chose en C, C++, Fortran, Algol, Java ou
tout langage que tu peux imaginer.
Faux
Si le mec a dans sa lib une fonction « void foo() throws
FileException », même s'il oublie de documenter l'erreur ou la
documente mal, le compilateur refusera de compiler mon code si je ne
traite pas l'erreur !
En Java, je ne suis pas dépendant des sources ou de la doc, uniquement
du code RÉEL (et non du comportement ou de la doc SUPPOSÉS corrects).
Si le mec a oublié de documenter un cas d'erreur, je serais quand même
obligé de le traiter dans mon code pour compiler !
On ne parlais pas de ça, mais de codes de retour ignorés. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
Cf l'exemple…
Le code est correct ou pas en fonction du comportement réel de la
fonction
Aucune macro ni algo n'est capable de détecter cette erreur !
> Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
Et tu fais comment pour connaître tous les codes de retour possibles
et imaginables ?
Sans être équivalent à un catch-all Java que tu sembles critiquer ?
> Comment fais-tu la différence entre :
> int bar(int i) {
> …
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme)
> et :
> int bar(int i) {
> …
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Le prototype est le même dans les 2 cas : « int bar(int) »Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
Le prototype est toujours le même dans les 2 cas : « int foo(…) »…
Tu es désespérant comme mec…
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'oblige à faire
attention à tes paramètres d'entrée et de sortie.
Non, mon problème est qu'à la vue du prototype d'une fonction en C, je
n'ai :
— Aucun moyen de savoir si elle me retourne un code d'erreur ou un
retour métier ( « int write(…) » peut aussi bien me retourner la
taille écrite qu'un code d'erreur)
— S'il s'agit d'un code d'erreur, l'ensemble des codes d'erreur
possibles afin que je puisse distinguer les types d'erreur pour les
traiter différemment suivant le cas si besoin ( « int write(…) » peut
aussi bien me retourner 0 pour le succès et -1 pour l'erreur que 0
pour le succès, -1 pour un fichier inexistant, -2 pour un fichier sans
droit d'écriture, -3 pour une erreur de flux…)
Argutie.
Cf multiples exemples au-dessus.
Et pour t'en donner un de plus, le code suivant est-il fiable, Ô Grand
Dieu ?
int write(char *file, char *data); // Issu d'une bibliothèque d'une
autre équipe de dev
void foo() {
write("/tmp/bar.txt", "Hello World !");
}
Répond à la question ci-dessus, je te donne les détails après ta
réponse
On 22 juin, 13:09, JKB <j...@koenigsberg.invalid> wrote:
Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
Il ne s'agit pas de connaître uniquement le prototype de la fonction
mais la signification exacte de sa valeur de retour : est-ce une
donnée de retour ou un code d'erreur ?
le « int » de « int foo(…) » peut dénoter à la fois un code d'erreur
ou autre chose, et on ne fait pas du tout la même chose en fonction du
cas : dans le 1er la valeur DOIT être traitée, dans le 2nd, elle PEUT
être traitée (fonction de son utilité réelle dans ton code).
« int foo(…) » ne peut me renseigner seule sur l'ensemble des erreurs
potentielles. Son implémentation réelle est nécessaire ou l'accès à sa
doc (qui peut être fausse, inexistante ou incomplète).
« void foo(…) throws FileNotFoundException, IOException » contient en
elle-même toutes les infos nécessaires à un code fiable, y compris les
cas d'erreur à traiter, quelque soit l'état de sa doc (même fausse,
inexistante ou incomplète) ou la disponibilité de son code.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la fonction. Point
barre.
Non, de sa plage de valeur de retour admissible aussi.
Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est trivial.
Je te parle de la valeur de retour.
Aucun moyen de savoir si un « int » est une valeur métier ou un code
de retour…
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
Met tes switch si tu préfères, le problème reste le même.
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu ne comprends vraiment rien au problème toi…
Le problème n'est pas de savoir si « if » est meilleur que « switch »,
mais du nombre de cas à traiter pour être complet…
Le fait de ne pas être totalement couvrant dans « bar » fera qu'après
correction, toutes les méthodes appelantes de « bar » vont aussi
devenir non totalement couvrantes.
Le fait d'avoir oublié un cas dans « bar » fait qu'on en a
automatiquement oublié dans « foo » qui appelle « bar » et que
« foo », correct avec « bar » buggé, deviendra buggé avec « bar » non
buggé.
C'est ça de la propagation d'erreur : en C, le fait de corriger un
bout de code sur la gestion d'erreur t'impacte toutes tes méthodes
appelantes aussi sur la gestion d'erreur !
Tu as parfaitement le droit de faire autrement, mais c'est _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour libérer les
ressources en cas d'erreur. C'est donc vachement compliqué. CHECK
est une macro triviale et tout à fait maintenable.
Et donc tu es strictement équivalent à un catch-all Java…
Et incapable de gérer les types d'erreurs correctement.
int fooBar(…) {
…
return ERROR_FILE_UNVAILABLE;
…
return ERROR_IO_ERROR;
…
}
« CHECK(fooBar(), <...>); » te rend incapable de faire la distinction
entre une erreur fichier (le nom du fichier était incorrect) et
d'écriture (le disque est mort ?), et de réagir différemment en
conséquence.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquement
C'est exactement ce que je dis. Et je rajoute que le try-catch-all
est une moisissure du langage.
Qui est strictement équivalente à ta macro « CHECK », la possibilité
de distinguer les types d'erreur en moins…
Si c'est une moississure du langage, ton code est donc une moisissure
de moisissure…
En C, aucune valeur de retour est inutile.
int write(…) {
…
return sizeWritten;
}
Celle-là est inutile potentiellement.
int write(…) {
…
return ERROR_FILE;
…
}
Celle-là est non seulement pas inutile mais en plus doit
OBLIGATOIREMENT être testée après appel !
Pas possible avec le default: du switch. Si ça ne te vas pas, tu
peux aussi utiliser un else{} dans ta close if().
Ce qui est encore plus équivalent à un try-catch en Java…
Et si la doc ne correspond pas à la fonction, je te rappelle que
c'est exactement la même chose en C, C++, Fortran, Algol, Java ou
tout langage que tu peux imaginer.
Faux
Si le mec a dans sa lib une fonction « void foo() throws
FileException », même s'il oublie de documenter l'erreur ou la
documente mal, le compilateur refusera de compiler mon code si je ne
traite pas l'erreur !
En Java, je ne suis pas dépendant des sources ou de la doc, uniquement
du code RÉEL (et non du comportement ou de la doc SUPPOSÉS corrects).
Si le mec a oublié de documenter un cas d'erreur, je serais quand même
obligé de le traiter dans mon code pour compiler !
On ne parlais pas de ça, mais de codes de retour ignorés. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
Cf l'exemple…
Le code est correct ou pas en fonction du comportement réel de la
fonction
Aucune macro ni algo n'est capable de détecter cette erreur !
> Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
Et tu fais comment pour connaître tous les codes de retour possibles
et imaginables ?
Sans être équivalent à un catch-all Java que tu sembles critiquer ?
> Comment fais-tu la différence entre :
> int bar(int i) {
> …
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme)
> et :
> int bar(int i) {
> …
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Le prototype est le même dans les 2 cas : « int bar(int) »
Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
Le prototype est toujours le même dans les 2 cas : « int foo(…) »…
Tu es désespérant comme mec…
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'oblige à faire
attention à tes paramètres d'entrée et de sortie.
Non, mon problème est qu'à la vue du prototype d'une fonction en C, je
n'ai :
— Aucun moyen de savoir si elle me retourne un code d'erreur ou un
retour métier ( « int write(…) » peut aussi bien me retourner la
taille écrite qu'un code d'erreur)
— S'il s'agit d'un code d'erreur, l'ensemble des codes d'erreur
possibles afin que je puisse distinguer les types d'erreur pour les
traiter différemment suivant le cas si besoin ( « int write(…) » peut
aussi bien me retourner 0 pour le succès et -1 pour l'erreur que 0
pour le succès, -1 pour un fichier inexistant, -2 pour un fichier sans
droit d'écriture, -3 pour une erreur de flux…)
Argutie.
Cf multiples exemples au-dessus.
Et pour t'en donner un de plus, le code suivant est-il fiable, Ô Grand
Dieu ?
int write(char *file, char *data); // Issu d'une bibliothèque d'une
autre équipe de dev
void foo() {
write("/tmp/bar.txt", "Hello World !");
}
Répond à la question ci-dessus, je te donne les détails après ta
réponse
On 22 juin, 13:09, JKB wrote:Ton exemple est typiquement du goret-codage. D'une part, si tu ne
sais pas quel est la prototype de la fonction, tu ferais bien de ne
pas l'utiliser.
Il ne s'agit pas de connaître uniquement le prototype de la fonction
mais la signification exacte de sa valeur de retour : est-ce une
donnée de retour ou un code d'erreur ?
le « int » de « int foo(…) » peut dénoter à la fois un code d'erreur
ou autre chose, et on ne fait pas du tout la même chose en fonction du
cas : dans le 1er la valeur DOIT être traitée, dans le 2nd, elle PEUT
être traitée (fonction de son utilité réelle dans ton code).
« int foo(…) » ne peut me renseigner seule sur l'ensemble des erreurs
potentielles. Son implémentation réelle est nécessaire ou l'accès à sa
doc (qui peut être fausse, inexistante ou incomplète).
« void foo(…) throws FileNotFoundException, IOException » contient en
elle-même toutes les infos nécessaires à un code fiable, y compris les
cas d'erreur à traiter, quelque soit l'état de sa doc (même fausse,
inexistante ou incomplète) ou la disponibilité de son code.
> Dans l'exemple précédent, elle nécessite la connaissance du code de la
> fonction « writeToFile » et l'analyse de toutes les valeurs de retour
> possibles.
Non. Elle nécessite de connaître le prototype de la fonction. Point
barre.
Non, de sa plage de valeur de retour admissible aussi.
Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
> Et même comme ça, on n'a aucun moyen de différencier « int
> writeToFile(char* file, char* data, int* written) » de « int
> writeToFile(char* file, char* data) », la 1ère ayant un code d'erreur,
> la 2nde non (taille de l'écriture).
Euh, comment dire... En C, peut-être. En C++, c'est trivial.
Je te parle de la valeur de retour.
Aucun moyen de savoir si un « int » est une valeur métier ou un code
de retour…
Parce qu'on ne gère pas ça comme ça. Effectivement, si c'est ton
niveau de programmation C/C++, reste avec Java !
Met tes switch si tu préfères, le problème reste le même.
int
bar()
{
int ios;
switch(ios = fooBar())
{
case 0:
...
break;
case ERROR_FOO_BAR_1:
...
case ERROR_FOO_BAR_2:
...
default:
...
}
return;
}
Tu ne comprends vraiment rien au problème toi…
Le problème n'est pas de savoir si « if » est meilleur que « switch »,
mais du nombre de cas à traiter pour être complet…
Le fait de ne pas être totalement couvrant dans « bar » fera qu'après
correction, toutes les méthodes appelantes de « bar » vont aussi
devenir non totalement couvrantes.
Le fait d'avoir oublié un cas dans « bar » fait qu'on en a
automatiquement oublié dans « foo » qui appelle « bar » et que
« foo », correct avec « bar » buggé, deviendra buggé avec « bar » non
buggé.
C'est ça de la propagation d'erreur : en C, le fait de corriger un
bout de code sur la gestion d'erreur t'impacte toutes tes méthodes
appelantes aussi sur la gestion d'erreur !
Tu as parfaitement le droit de faire autrement, mais c'est _ton_
problème. Pour ta gouverne, avec une macro bien sentie, ce code est
chez moi :
CHECK(fooBar(), <...>);
où <...> contient la liste des trucs à faire pour libérer les
ressources en cas d'erreur. C'est donc vachement compliqué. CHECK
est une macro triviale et tout à fait maintenable.
Et donc tu es strictement équivalent à un catch-all Java…
Et incapable de gérer les types d'erreurs correctement.
int fooBar(…) {
…
return ERROR_FILE_UNVAILABLE;
…
return ERROR_IO_ERROR;
…
}
« CHECK(fooBar(), <...>); » te rend incapable de faire la distinction
entre une erreur fichier (le nom du fichier était incorrect) et
d'écriture (le disque est mort ?), et de réagir différemment en
conséquence.
> Les 2 codes sont à modifier en cas de correction de « bar », sauf que
> l'erreur ne sera détectée que sur « bar », et sur « foo » uniquementC'est exactement ce que je dis. Et je rajoute que le try-catch-all
est une moisissure du langage.
Qui est strictement équivalente à ta macro « CHECK », la possibilité
de distinguer les types d'erreur en moins…
Si c'est une moississure du langage, ton code est donc une moisissure
de moisissure…
En C, aucune valeur de retour est inutile.
int write(…) {
…
return sizeWritten;
}
Celle-là est inutile potentiellement.
int write(…) {
…
return ERROR_FILE;
…
}
Celle-là est non seulement pas inutile mais en plus doit
OBLIGATOIREMENT être testée après appel !
Pas possible avec le default: du switch. Si ça ne te vas pas, tu
peux aussi utiliser un else{} dans ta close if().
Ce qui est encore plus équivalent à un try-catch en Java…
Et si la doc ne correspond pas à la fonction, je te rappelle que
c'est exactement la même chose en C, C++, Fortran, Algol, Java ou
tout langage que tu peux imaginer.
Faux
Si le mec a dans sa lib une fonction « void foo() throws
FileException », même s'il oublie de documenter l'erreur ou la
documente mal, le compilateur refusera de compiler mon code si je ne
traite pas l'erreur !
En Java, je ne suis pas dépendant des sources ou de la doc, uniquement
du code RÉEL (et non du comportement ou de la doc SUPPOSÉS corrects).
Si le mec a oublié de documenter un cas d'erreur, je serais quand même
obligé de le traiter dans mon code pour compiler !
On ne parlais pas de ça, mais de codes de retour ignorés. On peut
détecter ça avec quelques macros. Démerde-toi pour les trouver.
Cf l'exemple…
Le code est correct ou pas en fonction du comportement réel de la
fonction
Aucune macro ni algo n'est capable de détecter cette erreur !
> Sachant que tu n'as peut-être pas le source des fonctions « int foo(…)
> » et « int bar(int i) », qu'elles proviennent peut-être d'une
> librairie sur étagère ou d'une autre équipe de dev.
On s'en fout. On regarde l'appel de la fonction qui peut être une
boîte opaque.
Et tu fais comment pour connaître tous les codes de retour possibles
et imaginables ?
Sans être équivalent à un catch-all Java que tu sembles critiquer ?
> Comment fais-tu la différence entre :
> int bar(int i) {
> …
> if ( i > 0 ) return 1;
> return -1;
> }
> qui conduit à un code correct (la valeur de retour n'étant pas
> intéressante et pas un code d'erreur pour la suite de notre programme)
> et :
> int bar(int i) {
> …
> if ( bar1() == ERROR_BAR1 )
> return ERROR_BAR;
> return 0;
> }
> qui conduit à un code incorrect (oubli d'un cas d'erreur)
Tu relis le prototypage de ta fonction.
Le prototype est le même dans les 2 cas : « int bar(int) »Il n'y a rien à dire. Si tu n'es pas capable de lire un prototype,
tu devrais changer de métier.
Le prototype est toujours le même dans les 2 cas : « int foo(…) »…
Tu es désespérant comme mec…
En fait, ton problème, c'est de
remonter une erreur sur une variable parce que ça t'oblige à faire
attention à tes paramètres d'entrée et de sortie.
Non, mon problème est qu'à la vue du prototype d'une fonction en C, je
n'ai :
— Aucun moyen de savoir si elle me retourne un code d'erreur ou un
retour métier ( « int write(…) » peut aussi bien me retourner la
taille écrite qu'un code d'erreur)
— S'il s'agit d'un code d'erreur, l'ensemble des codes d'erreur
possibles afin que je puisse distinguer les types d'erreur pour les
traiter différemment suivant le cas si besoin ( « int write(…) » peut
aussi bien me retourner 0 pour le succès et -1 pour l'erreur que 0
pour le succès, -1 pour un fichier inexistant, -2 pour un fichier sans
droit d'écriture, -3 pour une erreur de flux…)
Argutie.
Cf multiples exemples au-dessus.
Et pour t'en donner un de plus, le code suivant est-il fiable, Ô Grand
Dieu ?
int write(char *file, char *data); // Issu d'une bibliothèque d'une
autre équipe de dev
void foo() {
write("/tmp/bar.txt", "Hello World !");
}
Répond à la question ci-dessus, je te donne les détails après ta
réponse
Ça, mon grand, c'est spécifié dans le prototype et l'interface.
Je suis désolé, mais je coupe ton blabla totalement i nintéressant.
Je maintiens que tu n'as pas besoin de savoir comment est fichue une
fonction à partir du moment où tu connais son interfa ce.
Te rends-tu compte que ton argument est parfaitement idio te ? Si la
doc est mauvaise, il est _normal_ que le code utilisant l adite
bibliothèque soit buggué.
Et alors ? La seule différence dans ce cas
est que le compilo Java va gueuler, mais ce n'est pas pou r cela que
ton code sera bon.
Et c'est sans compter
que le throw de la signature est peut-être un résidu qui ne sert
plus. Tu n'as _aucun_ moyen de le savoir.
> « void foo( ) throws FileNotFoundException, IOException » contien t en
> elle-même toutes les infos nécessaires à un code fiable, y compri s les
> cas d'erreur à traiter, quelque soit l'état de sa doc (même fauss e,
> inexistante ou incomplète) ou la disponibilité de son code.
Non, parce que tu es _obligé_ de faire confiance à ce tte ligne qui
peut comporter des choses amusantes voire totalement faus ses.
> Non, de sa plage de valeur de retour admissible aussi.
> Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
> si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
Par prototype, j'entendais prototype _et_ interface. Ne f ais pas
semblant de ne pas avoir compris.
Arrête de te raccrocher aux branches, ça commence à se voir. Tu
_dois_ connaître l'interface d'une fonction avant de l' utiliser.
Enfin, c'est préférable.
Non. Je te rappelle que tu prétendais qu'en C, on pouva it rater une
erreur. Je viens de te démontrer que c'est faux (que ce soit avec
des switchs ou avec des if/else).
Je ne vois pas comment tu peux en oublier sachant que tu gères
l'erreur à chaque appel (et de façon automatique avec une macro).
Non, d'autant qu'il n'y a pas de méthode en C.
Mais bien sûr que si. Je ne t'ai pas donné le contenu de la macro en
question. La macro traite les erreurs dans un switch et u ne fois
l'erreur traitée, elle libère les ressources en renda nt la main à
l'appelant. Elle fait exactement ce qu'il faut pour chacu ne des erreurs.
>> > Les 2 codes sont à modifier en cas de correction de « bar », sauf que
Et tu te retrouves _aussi_ à gérer des erreurs qui n' existent plus
parce que le type à laissé un throws bizarre dans le fichier.
Merci, j'ai donné.
Et de le traiter en aveugle ou presque. C'est bien. On a une doc
fausse, un code qui ne compile pas, puis on rajoute un ge stionnaire
d'exception parce que le compilo te le demande... Et tu n e trouves
pas ça aberrant ou casse-gueule ?
Je te rappelle (parce que tu coupes tellement qu'on n'arr ive plus à
suivre) que le problème initial était de savoir si le s valeurs de
retour étaient récupérées ou non. Je prétends q u'avec quelques
macros bien senties tu peux t'en assurer. Il n'était pa s question
initialement de savoir comment elles étaient traitées .
Il y a une doc. C'est l'hypothèse de base. De toute fa çon, même avec
Java, je REFUSE de coder un truc lorsqu'un appel de fonct ion ne
réagit pas comme cela est expliqué dans la DOC.
Moi, mon truc, c'est
le calcul. Et si une fonction est censée tourner avec u n integer*4,
que c'est marqué dans la doc, je suppose que c'est vrai .
Par ailleurs, si la doc ne correspond pas à l'interface réelle de la
fonction, il y a de fortes chances que l'intérieur de l a fonction
elle-même soit légèrement différente, ce qui impl ique non seulement
d'autres erreurs à traiter, mais aussi des fonctionnali tés
différentes.
Bref, mon expérience me dit que lorsqu'un truc n'est
pas conforme à la doc, il vaut mieux ne pas l'utiliser.
Non, tout le monde avait compris (sauf toi visiblement), que
j'entendais pas prototype, prototype _et_ interface.
Et ? La doc n'est pas fait pour les chiens.
> int write(char *file, char *data); // Issu d'une bibliothèque d'une
> autre équipe de dev
> void foo() {
> write("/tmp/bar.txt", "Hello World !");
> }
Code non conforme (et qui ne compilera pas sauf à brico ler la libc).
Par ailleurs, je t'ai dit beaucoup plus haut que l'hygi ène du
développeur C était de récupérer toutes les valeu rs retournées par
une fonction.
Ça, mon grand, c'est spécifié dans le prototype et l'interface.
Je suis désolé, mais je coupe ton blabla totalement i nintéressant.
Je maintiens que tu n'as pas besoin de savoir comment est fichue une
fonction à partir du moment où tu connais son interfa ce.
Te rends-tu compte que ton argument est parfaitement idio te ? Si la
doc est mauvaise, il est _normal_ que le code utilisant l adite
bibliothèque soit buggué.
Et alors ? La seule différence dans ce cas
est que le compilo Java va gueuler, mais ce n'est pas pou r cela que
ton code sera bon.
Et c'est sans compter
que le throw de la signature est peut-être un résidu qui ne sert
plus. Tu n'as _aucun_ moyen de le savoir.
> « void foo( ) throws FileNotFoundException, IOException » contien t en
> elle-même toutes les infos nécessaires à un code fiable, y compri s les
> cas d'erreur à traiter, quelque soit l'état de sa doc (même fauss e,
> inexistante ou incomplète) ou la disponibilité de son code.
Non, parce que tu es _obligé_ de faire confiance à ce tte ligne qui
peut comporter des choses amusantes voire totalement faus ses.
> Non, de sa plage de valeur de retour admissible aussi.
> Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
> si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
Par prototype, j'entendais prototype _et_ interface. Ne f ais pas
semblant de ne pas avoir compris.
Arrête de te raccrocher aux branches, ça commence à se voir. Tu
_dois_ connaître l'interface d'une fonction avant de l' utiliser.
Enfin, c'est préférable.
Non. Je te rappelle que tu prétendais qu'en C, on pouva it rater une
erreur. Je viens de te démontrer que c'est faux (que ce soit avec
des switchs ou avec des if/else).
Je ne vois pas comment tu peux en oublier sachant que tu gères
l'erreur à chaque appel (et de façon automatique avec une macro).
Non, d'autant qu'il n'y a pas de méthode en C.
Mais bien sûr que si. Je ne t'ai pas donné le contenu de la macro en
question. La macro traite les erreurs dans un switch et u ne fois
l'erreur traitée, elle libère les ressources en renda nt la main à
l'appelant. Elle fait exactement ce qu'il faut pour chacu ne des erreurs.
>> > Les 2 codes sont à modifier en cas de correction de « bar », sauf que
Et tu te retrouves _aussi_ à gérer des erreurs qui n' existent plus
parce que le type à laissé un throws bizarre dans le fichier.
Merci, j'ai donné.
Et de le traiter en aveugle ou presque. C'est bien. On a une doc
fausse, un code qui ne compile pas, puis on rajoute un ge stionnaire
d'exception parce que le compilo te le demande... Et tu n e trouves
pas ça aberrant ou casse-gueule ?
Je te rappelle (parce que tu coupes tellement qu'on n'arr ive plus à
suivre) que le problème initial était de savoir si le s valeurs de
retour étaient récupérées ou non. Je prétends q u'avec quelques
macros bien senties tu peux t'en assurer. Il n'était pa s question
initialement de savoir comment elles étaient traitées .
Il y a une doc. C'est l'hypothèse de base. De toute fa çon, même avec
Java, je REFUSE de coder un truc lorsqu'un appel de fonct ion ne
réagit pas comme cela est expliqué dans la DOC.
Moi, mon truc, c'est
le calcul. Et si une fonction est censée tourner avec u n integer*4,
que c'est marqué dans la doc, je suppose que c'est vrai .
Par ailleurs, si la doc ne correspond pas à l'interface réelle de la
fonction, il y a de fortes chances que l'intérieur de l a fonction
elle-même soit légèrement différente, ce qui impl ique non seulement
d'autres erreurs à traiter, mais aussi des fonctionnali tés
différentes.
Bref, mon expérience me dit que lorsqu'un truc n'est
pas conforme à la doc, il vaut mieux ne pas l'utiliser.
Non, tout le monde avait compris (sauf toi visiblement), que
j'entendais pas prototype, prototype _et_ interface.
Et ? La doc n'est pas fait pour les chiens.
> int write(char *file, char *data); // Issu d'une bibliothèque d'une
> autre équipe de dev
> void foo() {
> write("/tmp/bar.txt", "Hello World !");
> }
Code non conforme (et qui ne compilera pas sauf à brico ler la libc).
Par ailleurs, je t'ai dit beaucoup plus haut que l'hygi ène du
développeur C était de récupérer toutes les valeu rs retournées par
une fonction.
Ça, mon grand, c'est spécifié dans le prototype et l'interface.
Je suis désolé, mais je coupe ton blabla totalement i nintéressant.
Je maintiens que tu n'as pas besoin de savoir comment est fichue une
fonction à partir du moment où tu connais son interfa ce.
Te rends-tu compte que ton argument est parfaitement idio te ? Si la
doc est mauvaise, il est _normal_ que le code utilisant l adite
bibliothèque soit buggué.
Et alors ? La seule différence dans ce cas
est que le compilo Java va gueuler, mais ce n'est pas pou r cela que
ton code sera bon.
Et c'est sans compter
que le throw de la signature est peut-être un résidu qui ne sert
plus. Tu n'as _aucun_ moyen de le savoir.
> « void foo( ) throws FileNotFoundException, IOException » contien t en
> elle-même toutes les infos nécessaires à un code fiable, y compri s les
> cas d'erreur à traiter, quelque soit l'état de sa doc (même fauss e,
> inexistante ou incomplète) ou la disponibilité de son code.
Non, parce que tu es _obligé_ de faire confiance à ce tte ligne qui
peut comporter des choses amusantes voire totalement faus ses.
> Non, de sa plage de valeur de retour admissible aussi.
> Si elle peut renvoyer 0 et -1, je n'ai pas le même code à écrire que
> si elle renvoie 0, -1 (ERROR_FILE) et -2 (ERROR_IO).
Par prototype, j'entendais prototype _et_ interface. Ne f ais pas
semblant de ne pas avoir compris.
Arrête de te raccrocher aux branches, ça commence à se voir. Tu
_dois_ connaître l'interface d'une fonction avant de l' utiliser.
Enfin, c'est préférable.
Non. Je te rappelle que tu prétendais qu'en C, on pouva it rater une
erreur. Je viens de te démontrer que c'est faux (que ce soit avec
des switchs ou avec des if/else).
Je ne vois pas comment tu peux en oublier sachant que tu gères
l'erreur à chaque appel (et de façon automatique avec une macro).
Non, d'autant qu'il n'y a pas de méthode en C.
Mais bien sûr que si. Je ne t'ai pas donné le contenu de la macro en
question. La macro traite les erreurs dans un switch et u ne fois
l'erreur traitée, elle libère les ressources en renda nt la main à
l'appelant. Elle fait exactement ce qu'il faut pour chacu ne des erreurs.
>> > Les 2 codes sont à modifier en cas de correction de « bar », sauf que
Et tu te retrouves _aussi_ à gérer des erreurs qui n' existent plus
parce que le type à laissé un throws bizarre dans le fichier.
Merci, j'ai donné.
Et de le traiter en aveugle ou presque. C'est bien. On a une doc
fausse, un code qui ne compile pas, puis on rajoute un ge stionnaire
d'exception parce que le compilo te le demande... Et tu n e trouves
pas ça aberrant ou casse-gueule ?
Je te rappelle (parce que tu coupes tellement qu'on n'arr ive plus à
suivre) que le problème initial était de savoir si le s valeurs de
retour étaient récupérées ou non. Je prétends q u'avec quelques
macros bien senties tu peux t'en assurer. Il n'était pa s question
initialement de savoir comment elles étaient traitées .
Il y a une doc. C'est l'hypothèse de base. De toute fa çon, même avec
Java, je REFUSE de coder un truc lorsqu'un appel de fonct ion ne
réagit pas comme cela est expliqué dans la DOC.
Moi, mon truc, c'est
le calcul. Et si une fonction est censée tourner avec u n integer*4,
que c'est marqué dans la doc, je suppose que c'est vrai .
Par ailleurs, si la doc ne correspond pas à l'interface réelle de la
fonction, il y a de fortes chances que l'intérieur de l a fonction
elle-même soit légèrement différente, ce qui impl ique non seulement
d'autres erreurs à traiter, mais aussi des fonctionnali tés
différentes.
Bref, mon expérience me dit que lorsqu'un truc n'est
pas conforme à la doc, il vaut mieux ne pas l'utiliser.
Non, tout le monde avait compris (sauf toi visiblement), que
j'entendais pas prototype, prototype _et_ interface.
Et ? La doc n'est pas fait pour les chiens.
> int write(char *file, char *data); // Issu d'une bibliothèque d'une
> autre équipe de dev
> void foo() {
> write("/tmp/bar.txt", "Hello World !");
> }
Code non conforme (et qui ne compilera pas sauf à brico ler la libc).
Par ailleurs, je t'ai dit beaucoup plus haut que l'hygi ène du
développeur C était de récupérer toutes les valeu rs retournées par
une fonction.