OVH Cloud OVH Cloud

Microsoft et Java

295 réponses
Avatar
Wykaaa
Microsoft semble reconnaître que Java permet de développer plus
rapidement que C# et qu'il y a moins de failles de sécurité dans Java
que dans .net :
http://dsi.silicon.fr/nouveautes/microsoft-java-forever%E2%80%A6-1366

10 réponses

Avatar
JKB
Le Tue, 21 Jun 2011 20:14:05 +0200,
Aéris écrivait :

Le 21/06/2011 08:50, JKB a écrit :
Qu'est-ce qu'il ne faut pas lire...

JKB



Ben excuse-moi, mais avec mes exemples de code C totalement sûrs bardés
de if dans tous les coins, la complexité moyenne de test est de 2^(nb
appel de fonctions) alors qu'en Java elle est de 0.



Non. Je pense que l'intérêt de cpp t'a échappé.

Ajouter une fonction supplémentaire en Java coûte donc 0 quelque soit la
taille du projet.



Mouarf. Celle-là, je l'encadre tellement elle est belle. C'est pour
ça que dans la plupart des cas, on repart d'une feuille blanche
parce que le bel objet qu'on a sous la main ne contient pas ce qu'il
faut parce que c'est dans l'objet d'à-côté et que si on veut faire
ce que le client demande, il faut une belle fonction toute crade au
milieu pour récupérer les données de l'objet A dans le B. La
programmation objet, c'est assez rapidement infernal. Dire que
l'ajout d'une fonction ne coûte rien me fait juste rigoler. Ça coûte
exactement autant que dans n'importe quel projet.

En C, le coût proportionnel à la taille du projet
(passer de 10 à 11 appels passe la complexité de 2^10 = 1024 à 2^11 > 2048, passer de 30 [qui est la limite généralement admise en taille max
de fonction] à 31 de 1e19 à 2e19…).



Euh... Comment dire... Les bras m'en tombent.

Le code en C devient donc de moins en moins maintenable au fur et à
mesure des évolutions…



Non. Actuellement, je bosse sur un code qui a vingt-deux ans, qui
est en C et en Fortran, et qui est parfaitement maintenable. La
programmation fonctionnelle est justement là pour le rendre
parfaitement maintenable (et largement plus que dans le cas de la
POO).

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
JKB
Le Tue, 21 Jun 2011 20:34:59 +0200,
Yliur écrivait :

>> > Non, ce n'est pas la seule différence. Plus de choses à gérer =>
>> > plus d'erreurs. A moins que tu écrives des programmes sans jamais
>> > aucune erreur ?
>>
>> Alors explique-moi pourquoi les plus belles conneries qui
>> m'aient été données de voir, c'est justement dans des codes Java ?
>
> C'est une expérience considérée comme statistiquement objective ?

Avec quinze ans de pratique sur les deux, je pense que ça
commence à montrer une tendance.



Bah tu es tout seul et rien de vérifiable, même pas de comparaison
dans des conditions objectives, rien... Est-ce que tu prétends que la
réputation du C de produire des programmes illisible est totalement
usurpée ?



Non.

>> > Moins d'attention du développeur gaspillée, moins de pollution
>> > dans le code.
>>
>> Aucun rapport. Si tu ne fais pas attention, tu feras des
>> conneries quel que soit le langage.
>
> Tu ne fais *jamais* de conneries ?

Ai-je prétendu le contraire ?



Et comme personne n'est parfait, la quantité de conneries dépend de la
difficulté et du nombre de trucs à surveiller. Pourquoi il y a plein de
failles dans des logiciels écrits en C ?



Sauf que l'immense majorité des failles sont toujours les mêmes. Je
n'ai jamais prétendu que le C est un langage parfait. Simplement que
les GC et la gestion des erreurs par exceptions sont deux vastes
fumisteries (et à la limite que Java est un bloatware).

Le gros problème du C, c'est qu'il te permet de faire n'importe quoi
parce qu'il part du principe que le programmeur n'est pas tout à
faire débile. Ce qui fait que je fais peut-être moins de conneries
en C que le programmeur lambda, c'est que j'ai appris le C dans un
laboratoire de calcul de la DGA avec des règles de codages strictes.
J'ai donc un certain nombre de réflexes conditionnés que n'a pas le
programmeur de base.

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).

>> > La partie à comprendre en moins en java c'est les destructeurs
>> > (C++),
>>
>> Oui, et on voit les conneries des pointeurs qui ne sont
>> jamais déréférencés avec ce que ça implique, par exemple...
>
> On parle toujours de Java là ? Il y a très peu de choses à
> déréférencer, seulement quelques ressources particulières, comme
> déjà mentionné (gestion de cache par exemple ; même pour ça on peut
> utiliser des références faibles).

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.

> Oui, les développeurs qui ont une formation plus large et/ou plus
> approfondie sont mieux formés et donc plus compétent (enfin en
> supposant qu'ils aient tout assimilé). Tu veux démontrer que les
> développeurs mieux formés sont meilleurs ? Youhou, quelle grande
> découverte. Sauf que toutes ces compétences ne sont pas forcément
> nécessaires. Dans "peu ou prou", il y a "peu" : les développeurs
> n'ont pas besoin de connaître autant de subtilité (ça ne veut pas
> dire rien, mais moins de choses), et surtout pas à s'en préoccuper,
> même s'il savent comment ça fonctionne.

Il y a deux niveaux. Celui où le dev sait que ça se passe
d'une certaine façon même s'il ne doit pas le gérer et celui où le
dev ne pipe mot à ce qu'il fait parce qu'il n'a pas conscience des
mécanismes. Mon expérience me dit que la plupart des devs
java qui n'ont fait que du java sont dans la deuxième catégorie. Et
figure-toi, ça me pose quelques problèmes quand je suis
obligé de passer derrière eux.



De fait il y a moins de choses à comprendre. Pour éviter les fuites de
mémoire il suffit en gros de savoir que ça marche presque tout seul,



Tout étant encore une fois dans le presque.

les exceptions étant une poignée de ressources (dont il faut se
préoccuper de manière particulière dans d'autres langages aussi, comme
les fichiers ou le cache).


Pour ta gouverne, la JVM de Sun outrepasse allègrement les
options de mémoire minimale et maximale. Ne me demande pas pourquoi,
mais c'est un fait. J'ai un processus qui est censé ne pas dépasser
plus d'un Go de mémoire, et il occupe présentement 6 Go de mémoire de
autant de swap (Solaris sparc avec une JVM 1.6 64 bits). La
aussi, la JVM (ou son GC) sait mieux que le dev ce qu'il faut
utiliser comme paramètres. En fait, j'ai de plus en plus l'impression
que Java, c'est le microsoft des langage. Il sait mieux qu'un dev ce
qui est bon pour lui.



S'il y a un gros bug dans la JVM de Solaris, tu le signales aux gens
compétents. Je n'ai jamais vu ce comportement.



Si tu ne me crois pas, teste. Et si tu vois le bug, fais un BR.
Oracle n'en a rien à faire. Ce n'est pas un problème critique.

Je t'ai aussi déjà expliqué que dans la vraie vie, le dev qui
est pressé et dont le compilateur râle colle un gestionnaire
ramasse-tout (c'est aussi vrai en C++) et au final, c'est
contre-productif.



Ben je t'ai déjà répondu que le développeur pressé fera aussi des
conneries en C, c'est pareil.



JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
JKB
Le Tue, 21 Jun 2011 20:38:56 +0200,
Aéris écrivait :

Le 21/06/2011 20:34, Yliur a écrit :
Je t'ai aussi déjà expliqué que dans la vraie vie, le dev qui
> est pressé et dont le compilateur râle colle un gestionnaire
> ramasse-tout (c'est aussi vrai en C++) et au final, c'est
> contre-productif.


Ben je t'ai déjà répondu que le développeur pressé fera aussi des
conneries en C, c'est pareil.




D'autant plus que le gestionnaire collé à l'arrache aura au moins un
gros bénéfice : il est fiable car ne peut pas planter.



Non, il ne peut pas planter. Il peut juste laisser la table de
fraisage dans un état baroque ou faire des choses plus amusantes.
Mais il n'aura pas planté !

Le développeur médiocre en Java ne pourra pas oublier un cas, le
compilateur s'occupant de le rappeler à l'autre le cas échéant.
Et même la solution la plus sale atteindra le but voulu : traiter tous
les cas et rendre le code fiable.

À l'inverse en C, un mauvais dev va justement tout faire de travers et
louper les ¾ des tests. Bilan : un soft instable et non fiable?



Un mauvais codeur C, tu le repères en cinq minutes. Autre question ?

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Aéris
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Le 21/06/2011 21:00, JKB a écrit :
Un mauvais codeur C, tu le repères en cinq minutes. Autre question ?



Ah ? Et pourquoi ne le pourrait-on pas en Java aussi ?
Sans parler que les try-catch-all sont détectables, pas l'absence de
code, donc aucun moyen de détecter un oubli de code de retour en C⁺⁺.

Réactivité en Java : au prochain commit (merci la CI !) avec 100% de
chance de le voir
Réactivité en C : à la prochaine relecture de code, et encore aucune
garantie de détecter le problème…

- --
Aeris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOAO2OAAoJEK8zQvxDY4P98NEH/3q+3bV+xGvBvVF+XLHjQhVt
RtNk9FUm4+bGDh2yz9cNtFXcypfH7ku/wzJN8ESg1LbYkN/fc5jPaVEM+4k4t1Xc
aqMNYhcnRNR4o8vQI++3SeqbF8dkNvG6cxeeabq2z7LWSrX8QTQlR4WtZFJOWZUC
2gRcsId087pMvIc1bff5yfVFSes+R6wtNQ4DUXF8VholLJaZ42BaugI0eQu/2HIu
k5j1xQ9R+eaNEIqyLEaZC0PS3WjIje5V5qIAO1PNaU1rqj/AqWEaysiWZVfPPhbK
h2rBP6M4ql+UpkdMS33MYEDyybDJ6dvPFSr6flMydoatLBTxM755rV2MqlWFlXw =NLb0
-----END PGP SIGNATURE-----
Avatar
Emmanuel Florac
Le Tue, 21 Jun 2011 15:41:12 +0800, ST a écrit:


J'aurais pu écrire :

sub write_to_file
{
return system("echo $_[0] > $_[1]");
}



Ça ne me fait pas rire, parce que j'ai vu ce genre d'horreur dans du code
en prod.

--
entia non sont multiplicanda praeter necessitatem.
John Ponce of Cork.
Avatar
JKB
Le Tue, 21 Jun 2011 21:14:36 +0200,
Aéris écrivait :

Le 21/06/2011 21:00, JKB a écrit :
Un mauvais codeur C, tu le repères en cinq minutes. Autre question ?



Ah ? Et pourquoi ne le pourrait-on pas en Java aussi ?



Parce que c'est un langage plus facile d'accès.

Sans parler que les try-catch-all sont détectables, pas l'absence de
code, donc aucun moyen de détecter un oubli de code de retour en C⁺⁺.



Et ? Tu coupes ce qui t'intéresse. C'est dommage, parce que si tu
peux détecter ton try-catch-all, tu n'as aucun moyen de détecter
comment va remonter ton exception. Enfin passons.

Réactivité en Java : au prochain commit (merci la CI !) avec 100% de
chance de le voir
Réactivité en C : à la prochaine relecture de code, et encore aucune
garantie de détecter le problème…



Rien compris à ta prose. Exprime-toi clairement.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Aéris
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Le 21/06/2011 21:32, JKB a écrit :
Et ? Tu coupes ce qui t'intéresse. C'est dommage, parce que si tu
peux détecter ton try-catch-all, tu n'as aucun moyen de détecter
comment va remonter ton exception. Enfin passons.



Beuh ?
Remonter une exception que j'ai catch-all ?
La plaque ................................................... JKB

Et sachant quelles exceptions sont potentielles sur chaque méthode, je
peux parfaitement remonter toute la pile d'appel sans problème !

> Réactivité en Java : au prochain commit (merci la CI !) avec 100% de
> chance de le voir
> Réactivité en C : à la prochaine relecture de code, et encore aucune
> garantie de détecter le problème…


Rien compris à ta prose. Exprime-toi clairement.



En Java, au prochain commit dans la gestion de conf, l'intégration
continue se déclenchera. Findbug détectera immédiatement le catch-all et
alertera le responsable du projet en plus du commiter.
Le catch-all sera donc détecté à 100% dans les prochaines minutes de la
connerie et sera corrigée avant d'avoir pu se propager ailleurs dans le
code.

La détection d'erreur en Java est donc :
– quasi-immédiate (fonction de la fréquence de commit scm)
— fiable (100% de détection)
— automatique (Jenkins + Maven + Findbugs)
— sans propagation de l'erreur

En C, comme les erreurs ne sont pas explicites :
— aucun moyen de savoir si le retour d'une fonction est un code d'erreur
ou une valeur de retour quelconque
— aucun moyen de savoir quels sont TOUS les codes de retour possibles
— 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.

Même si tu faisais une revue de code juste après l'introduction de
l'erreur, tu n'as aucune certitude de la détecter lors de la revue.
Pire, la proba de détection est dépendante de la compétence du relecteur
et du temps qu'il va y consacrer.
Encore pire, il est rare de faire des revues de code toutes les 10min,
tout au plus 1× par semaine. L'erreur a donc de fortes chances de s'être
propagée dans le code.

En C, la détection sera donc :
— longue (fonction de la fréquence de la revue de code)
— non fiable (aucune certitude de détection de l'erreur)
— manuelle (difficile de détecter l'absence de quelque chose dont on a
pas connaissance)
— avec propagation de l'erreur potentielle


- --
Aeris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOAPuQAAoJEK8zQvxDY4P9sooH/3l1vFH5XqMP5MBFhhmlROuw
5B7iH9BdeWWZZsYggmG3VOfEljo58mN1zlJjWXu983QojNU2EN288C20NfbFgetl
4qrQICbcKd2xEwqe51r1VGONvyaeRbKK5nbhZsddOCcsEIFn+/VX0xyIU7fsI5qg
zQkWlc/3fBFZ2mKdLywLjI5w/NqqRKL1p6NUL1ofmBxhjsIzITOUt6b5IysiZX+6
Eg+uKnmJFQitw3KHY+/qBmgk7+QrB26gy2kZPSL00oQDlQMko6aPLFjWJs/w9dzy
WjMIOfsDi/jQaYRwmeQAn5vtYkcKT8t13pYsshuA0Ak/tGBSsW2tTe+PGw1gXsA =7uiP
-----END PGP SIGNATURE-----
Avatar
Dellara
Yliur a papoté sur Usenet le 21 juin 2011 14:34:

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. Maintenant, c'est toi qui voit.

P.S.:Je sais à qui tu répondais, mais ce n'est pas une raison pour
ignorer les autres lecteurs.
Avatar
JKB
Le Tue, 21 Jun 2011 22:14:14 +0200,
Aéris écrivait :

Le 21/06/2011 21:32, JKB a écrit :
Et ? Tu coupes ce qui t'intéresse. C'est dommage, parce que si tu
peux détecter ton try-catch-all, tu n'as aucun moyen de détecter
comment va remonter ton exception. Enfin passons.



Beuh ?
Remonter une exception que j'ai catch-all ?
La plaque ................................................... JKB

Et sachant quelles exceptions sont potentielles sur chaque méthode, je
peux parfaitement remonter toute la pile d'appel sans problème !



Arrête de te faire plus bête que tu n'es. Si la fonction A appelle
la B qui appelle une palanquée et demi de fonctions imbriquées et
qu'il y a une exception qui arrive là-dedans, tu sais qu'elle
remonte au catch-all tout en haut. Tu ne sais pas de façon simple
qui l'a déclanchée ni pourquoi. Après, tu peux prétendre que le GC
fait tout pour toi dans ton dos. J'ai aussi le droit de prétendre
que c'est idiot.

> Réactivité en Java : au prochain commit (merci la CI !) avec 100% de
> chance de le voir
> Réactivité en C : à la prochaine relecture de code, et encore aucune
> garantie de détecter le problème…


Rien compris à ta prose. Exprime-toi clairement.



En Java, au prochain commit dans la gestion de conf, l'intégration
continue se déclenchera. Findbug détectera immédiatement le catch-all et
alertera le responsable du projet en plus du commiter.
Le catch-all sera donc détecté à 100% dans les prochaines minutes de la
connerie et sera corrigée avant d'avoir pu se propager ailleurs dans le
code.



Et je continue à dire que c'est aussi idiot. Parce que lorsque tu as
un catch-all, rien ne te permet de façon _simple_ d'ajouter toutes
les détections d'erreur à tous les niveaux. Tu sais que tu as un
bout de code écrit par un goret, pas comment le corriger.

La détection d'erreur en Java est donc :
– quasi-immédiate (fonction de la fréquence de commit scm)



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 !

— fiable (100% de détection)



On se contre-fiche de la détection si on ne sait pas comment
corriger facilement.

— automatique (Jenkins + Maven + Findbugs)



En C aussi figure-toi. On n'a pas attendu Java pour pointer les
fonctions qui renvoyaient des valeurs non utilisées.

— sans propagation de l'erreur



Gnî ?

En C, comme les erreurs ne sont pas explicites :
— aucun moyen de savoir si le retour d'une fonction est un code d'erreur
ou une valeur de retour quelconque



Le rapport avec le schmilblick ? Une fonction renvoie une valeur (ou
un ensemble de valeurs passées par pointeur et non par référence
comme tu le disais un peu plus haut). 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.

— aucun moyen de savoir quels sont TOUS les codes de retour possibles



Pardon ? Ces valeurs de retour sont _normalisées_ et parfaitement
_connues_.

— 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.

Même si tu faisais une revue de code juste après l'introduction de
l'erreur, tu n'as aucune certitude de la détecter lors de la revue.



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. Tester la remontée des erreurs en C est un truc qui se fait
à partir de macros. 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.

Pire, la proba de détection est dépendante de la compétence du relecteur
et du temps qu'il va y consacrer.



Non. Avec quelques scripts générant des fichiers d'en-têtes, c'est même
automatique.

Encore pire, il est rare de faire des revues de code toutes les 10min,
tout au plus 1× par semaine. L'erreur a donc de fortes chances de s'être
propagée dans le code.



Encore une fois non. J'ai l'impression de discuter avec un marketeux
javaïste qui n'a aucune idée de ce qu'on est capable de faire dans
tous les autres langages.

En C, la détection sera donc :
— longue (fonction de la fréquence de la revue de code)



Non.

— non fiable (aucune certitude de détection de l'erreur)



Non plus.

— manuelle (difficile de détecter l'absence de quelque chose dont on a
pas connaissance)



Pardon ?

— avec propagation de l'erreur potentielle



Non.

Je te conseille d'aller prendre quelques cours de C/C++ et de
regarder ce qui est à la disposition d'un développeur pour éviter
tous les problèmes que tu indiques. Encore une fois, je ne dis pas
que le C ou le C++ est facile d'accès, simplement que tes arguments
n'en sont pas puisque tout ce que tu pointes peut être fait en C. La
différence est qu'en Java, tu n'as pas à te poser la question.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Aeris Imirhil
On 22 juin, 09:07, JKB wrote:
        Arrête de te faire plus bête que tu n'es. Si la fonct ion A
        la B qui appelle une palanquée et demi de fonctions imb riquées et
        qu'il y a une exception qui arrive là-dedans, tu sais q u'elle
        remonte au catch-all tout en haut. Tu ne sais pas de fa çon simple
        qui l'a déclanchée ni pourquoi.



Je le sais parfaitement, ou en tout cas le type d'erreur levée, via le
typage des exceptions.
Une IOException dénote un soucis de flux, une SQLException une erreur
de bdd, etc.
E si le code est bien conçu, chaque méthode lève des exceptions
suffisamment précises pour être différentiées et traitables.

        Et je continue à dire que c'est aussi idiot. Parce que lorsque tu as
        un catch-all, rien ne te permet de façon _simple_ d'ajo uter toutes
        les détections d'erreur à tous les niveaux.



Gné ? Je ne comprend pas ce que tu dis…
D'autant plus que par sa gestion des exceptions, Java gère déjà les
détections d'erreur à tous les niveaux…
Donc plus simple que « rien à faire », j'ai du mal à imaginer …

Tu sais que tu as un
        bout de code écrit par un goret, pas comment le corrige r.



Idem en C.

        Oui, et ? Elle est détectée, pas corrigée ! La bonn e façon de faire,
        et dans _tous_ les langages, Java compris, c'est de comme ncer 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 co mment
        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 point er 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 écrit e ?

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 l a
fonction « writeToFile » et l'analyse de toutes les valeurs de reto ur
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 q u'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 remon ter
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) », l a
valeur de retour est totalement inutile dans 99% des cas pour la suite
du programme.

        Pardon ? Ces valeurs de retour sont _normalisées_ et pa rfaitement
        _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 T OUS
> 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'a i 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 q ue tu n'as
        aucune idée de la façon dont on fait une revue de cod e 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 erreu r 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é ?

> — manuelle (difficile de détecter l'absence de quelque chose dont o n a
> pas connaissance)

        Pardon ?



Cf exemple du dessus.
Aucune machine n'est capable de dire si le code est correct ou non.
Seul un humain avec l'intégralité de la connaissance du projet peut le
faire (détection et décision très fortement contextuelle)