07 mai 2010

AutoBoxing : la fausse bonne idée ?

Java 5 apporte son lot de nouveautés, entre autre l'autoBoxing. Sauf qu'il ne s'agit pas d'une évolution au sein de la JVM mais uniquement au niveau de la syntaxe et du compilateur, donc écrire :

Double d = ...;
truc.setValue( d ); // signature : public void setValue( double );

se traduit (en pseudo-code) dans le .class compilé par
Double d = ...;
truc.setValue( d.doubleValue() );

Un effet de bord particulièrement indésirable apparaît lorsqu'on attaque alors du code généré (par exemple) pour un service web. Une donnée xs:double qui va porter un minocurs=0 (optionnelle) sera traduite par le générateur wsdl2java en Double, alors que la même donnée obligatoire donnera un primitif double.

Le résultat, c'est qu'en cas de mauvaise lecture du WSDL, rien ne signalera au développeur qui fait son setValue( d ) qu'il prend le risque d'un bon gros NullPointerException. Pire, si le WSDL change, le code continue de compiler sans sourciller mais devient fragile. Je rencontre ce problème depuis quelques temps sur plusieurs projets.

Par ailleurs, le problème n'est pas si évident à diagnostiquer, car la NullPointerException indique une ligne en apparence anodine. Il faut faire preuve de pas mal d'imagination pour aller comparer (faute de mieux) le type du paramètre et de la variable passée, en remettant en cause le bon sens du compilateur...

Comme quoi, à vouloir tout simplifier on peut se tirer une balle dans le pied.


2 commentaires:

Julien a dit…

Sans compter les créations d'objets inutiles lorsqu'une même donnée est un coup typée en type simple et un coup en wrapper associé puis réutiliser en type simple.

double tva = .....;
double prixHT = ....;
calculerPrixTT(prixHT , tva);

avec la déclaration :
Double calculerPrixTT(Double prixHT , Double tauxTva) {
return prixHT * tauxTva;
}

Rien n'indique clairement que des objets Double seront créés pour rien par exemple.

PS : Ce code est juste pour l'exemple puisqu'il faudrait utiliser des BigDecimal plutôt.

Nicolas De Loof a dit…

Je viens de noter que le compilo d'Eclipse propose une option "Boxing and Unboxing conversion" qui permet de lever une erreur si l'autoboxing est utilisé. On peut donc interdire son utilisation au développeur du projet.
C'est peut être une bonne raison pour changer le compilo utilisé par maven ! (http://maven.apache.org/plugins/maven-compiler-plugin/non-javac-compilers.html)