Styles

lundi 28 septembre 2009

Efficacité des tests unitaires

Les tests unitaires ne sont pas une solution à un problème, mais plutôt le symptôme de notre incapacité à produire du code correct dès le premier jet. Quand la même personne réalise le test unitaire et le code à tester, elle a toujours du mal à s'auto-critiquer, même en voulant honnêtement produire le code le plus propre possible. Un code est beaucoup plus critiqué, explicité, quand ce n'est pas la même personne qui code et qui teste. Cela me rappelle une étude citée par Steve McConnell dans "Code Complete 2nd Edition" qui m'apparut alors comme une révélation :
"Le test logiciel a une efficacité limité quand elle est utilisée seule - le taux moyen de détection d'erreur est seulement de 30 pourcent pour les tests unitaires, 35 pourcents pour les tests d'intégration et 35 pourcents pour des beta-tests de petits volumes. Par contre, l'efficacité des inspections de la conception et du code est de 55 et 60 pourcents. (Jones, Capers. 1996. "Software Defect-Removal Efficiency," IEEE Computer, April 1996)." -- Code Complete, 21.1. Overview of Collaborative Development Practices
L'inspection de code, formelle ou pas, est plus efficace que les tests unitaires et d'intégration. Avec de bonnes checklists, il est très intéressant de provoquer des critiques constructives sur chaque aspect d'une architecture et du code correspondant, en commençant par les plus sensibles. De plus, une personne porte beaucoup plus de soins à son code quand il sait que celui-ci va être inspecté par une autre personne. Une fois le squelette d'une architecture revue, il devient moins critique de relire tout le code développé sur celle-ci. Et on peut accélérer le développement comme nous le rappelle Jamie Zawinski :
"Les tests unitaires semblent biens en principe. Avec un rythme de développement tranquille, c'est certainement la voie à prendre. Mais quand on regarde de plus près, "nous devons aller de zéro à terminé en six semaines", et bien, je ne peux pas le faire à moins d'enlever quelque chose. Et ce que je vais enlever sont tous les trucs qui ne sont pas absolument critiques. Et les tests unitaires ne sont pas critiques. S'il n'y a pas de tests unitaires, le client ne s'en plaindra pas". -- Coders at Work
Quand les délais de livraison sont très courts par rapport à l'ampleur du code à développer, le ratio nombre de fonctionnalités sur le temps devient tel que le respect des délais est entièrement déterminé par la rapidité de frappe des développeurs sur leur clavier.

Et dans ce cas là, s'il n'y a pas de temps pour faire des tests unitaires, autant avoir des codeurs expérimentés codant juste du premier coup, ou sachant trouver la source de n'importe quel problème en un temps fini. Mais quand on en est à ce niveau, c'est qu'on n'est pas sure d'avoir du boulot si le logiciel à produire ne sort pas à la date cible.

Il peut être raisonnable de choisir de coder des solutions "Quick & Dirty" dans une première phase pour pouvoir respecter les délais tout en sachant qu'on contracte une dette technique importante qu'il faudra un jour payer dans une prochaine release sous peine de voir le logiciel se scléroser complètement.

Mais quel projet informatique, une fois parti sur le chemin séduisant du "quick & dirty" est prêt à payer sa dette pour revenir à un système "sain" de corps (le code) et d'esprit (la conception) ? Tant que le paiement des intérêts de la dette technique permette de continuer à développer de nouvelles fonctionnalités dans les temps impartis, qui se soucie de rembourser la dette ? s'il n'y a aucun intérêt business de nettoyer le code et l'architecture, mieux vaux continuer à coder comme avant.

J'ai rarement vu une maintenance d'un logiciel prenant régulièrement du temps sur chaque release pour corriger/mettre au propre des parties du code. J'ai toujours vu des applications devenir de grosses machines à gaz et être à terme refondue entièrement (la dette technique de l'application disparaît alors complètement). C'est peut-être malheureux à dire, mais c'est la sombre réalité du monde de l'informatique : la plupart des applications sur lesquelles nous sommes amenés à intervenir ont une énorme dette technique, et on a rarement l'espoir de voir s'améliorer une application sans que celle-ci soit entièrement refondue.

Il faut s'y faire, et autant apprendre à coder juste et de façon défensive dès le premier coup.

Aucun commentaire: