mardi 8 janvier 2008

Traductions de quelques "Pratiques de développeur agile"

Vues sur le blog de Juixe, je ne résiste pas à l'envie de traduire les quelques "Pratices of Agile Developer" de son article... (à noter qu'il trouve les premières évidentes et est d'accord avec les secondes).

  • Soignez le mal, pas les symptomes.
  • La meilleure chose pour le développeur n'est pas nécessairement la meilleure chose pour l'utilisateur, et vice versa.
  • La plupart des utilisateurs préfère avoir un bon software aujourd'hui qu'attendre un an pour en avoir un de qualité supérieure.
  • Les itérations et incréments courts (NDT : probablement au niveau des livrables ici) aident le développeur à rester concentré.
  • Les cas-tests unitaires sont un investissement. Investissez intelligemment. Tester des accesseurs ou des méthodes triviales est le plus probablement une perte de temps.
  • S'il y a plusieurs façons de faire, utilisez celle qui sera compréhensible par plus d'un seul développeur.
  • On conçoit une solution logicielle pour l'utilisateur final. Pas pour le développeur d'à côté, ou pire, pour sa base de données.
  • Si l'utilisateur final ne peut pas utiliser votre programme, c'est un bug.
  • Vous pouvez considérer votre code comme une oeuvre d'art, mais personne ne l'exposera au Louvre
  • Mangez des fruits et des légumes avant de programmer.
Commentaires :

La 1.1 est évidente et piquée aux principes de la médecine (et de l'ingénierie, et tout autre domaine un poil rationnel... Du bon sens quoi, comme la plupart).
La 1.3 est moins évidente. Tout dépend de qui l'on appelle "utilisateur", et de sa propre relation avec lui. Par exemple, on pourrait prendre le cas des (nombreuses) entreprises attendant le SP1 de Windows Vista pour migrer vers cet OS.

La 1.4 fait référence à une pratique d'XP consistant à réduire la fréquence de livraison et d'intégration de modifs dans le produit (pratiques de l'xp)
Sur la 1.5, je n'arrive malheureusement plus à retrouver l'interview d'un dev affirmant qu'il concevait le plus souvent ses cas-tests unitaires avant même d'implémenter ses méthodes. En POO, ça peut être effectivement une approche assez saine : basiquement pour chaque méthode, je dois donner ceci et recevoir cela --> on teste au besoin la nature et/ou le contenu de ceci et/ou cela.

La seconde partie (citations avec lesquelles Juixe est en accord...) revient sur plusieurs notions intéressantes :

D'abord, l'importance de l'utilisateur final. C'est pour lui que l'on code, pas pour la machine (Matz développe ce point dans une interview dont on avait parlé). C'est idiot, mais s'en souvenir est capital.

Ensuite, l'importance de la lisibilité d'un code. Pas pour un mini-script système jetable, bien sûr, mais n'importe quel programme susceptible d'être maintenu se doit d'être lisible. Donc entre autres : commenté clairement, indenté, avec une certaine norme d'écriture (si non-imposée par le langage), avec des variables aux noms clairs, etc...

En passant, le coup des fruits et légumes... C'est idiot, hein ? Une bonne hygiène de vie, patati, patata... Pour seul commentaire : il y avait dans la salle machine où j'ai commencé (dans la douleur) l'apprentissage de la programmation, une affiche sympa. On y voyait un homme à la mine décomposée devant sa bécane, un café à la main devant une horloge indiquant une heure avancée de la nuit. Et en texte : "Dude ! It's 4 A.M: Do you REALLY think you gonna find the bug now !? ".

Enfin, la question de l'aspect artistique de la programmation. C'est un vrai sujet, qui compte pas mal pour la communauté Rubyiste d'ailleurs (voir les réalisations de _Why). La citation 2.4 me rappelle ce que j'ai entendu un jour (pendant un séminaire d'un chercheur ou ingénieur hongrois, expert en modélisation mathématique - je crois...) : "Ne tombez pas amoureux de votre modèle. Si on est amoureux de son modèle, on risque d'hésiter à faire certaines choses. Comme le jeter, le déclarer mauvais ou le reprendre en profondeur. Si vraiment un modèle ne marche pas, il faut le détruire et recommencer à zéro. Pas essayer de l'améliorer..." (adaptation approximative selon mes souvenirs). Grosso modo, c'est la même chose pour un code (l'analogie est d'autant plus forte que les modèles mathématiques dont parlait cet éminent savant ont pour vocation directe d'être implémentés...).

Note pour Lefty : un "développeur agile" n'est pas un programmeur capable de coder en équilibre sur son majeur gauche, avec une rose entre les dents le tout sur un skate reposant sur un ballon multicolore : ça, c'est juste un c0uillon !

2 commentaires:

Benjamin Francisoud a dit…

> Si vraiment un modèle ne marche pas, il faut le détruire et recommencer à zéro. Pas essayer de l'améliorer...

Tout le problème est là! Je me retrouve souvent dans ce genre de situations :(
Comment savoir ce qui est le plus rapide ?
1- Ajouter quelques petites choses, faire des refactoring localement
2- Tout jeter et recommencer de zéro

Souvent le "Big Bang refactoring" est beaucoup moins simple qu'il n'y paraissait de prime abord. Le logiciel à refaire est complexe pour une bonne raison, tous ces if/else n'ont pas été ajoutés pour rien, souvent pour régler ces 20% de petits bugs dans les cas limites.

Inversement on peut passer plus de temps à essayer de faire des rustines sur une jambe de bois...

Un excellent article sur le "Big Rewrite" que je te conseille de lire http://www.chadfowler.com/2006/12/27/the-big-rewrite

Dans la majorité des cas je préfère faire du refactoring local et améliorer petit bout par petit bout.
C'est plus long, c'est moins "rewarding" pour le développeur mais je trouve scandaleux de dire aux utilisateurs qu'il n'y aura aucunes évolutions, voir que le logiciel sera indisponible pendant plusieurs semaines/mois avant de leur livrer une nouvelle version qui contient moins de choses que la précédente et qui ne leur apporte rien de nouveau/mieux par rapport à l'ancienne.

Mais bon tout dépend du contexte...

Sobe a dit…

Alors, petite précision, la citation du scientifique hongrois était au sujet de modèles mathématiques (typiquement, une mise en équations différentielles d'un système physique (mécanique des fluides dans le contexte) puis modélisation par éléments/volumes finis, solveur, etc...) : je l'utilise seulement comme une analogie ! En pratique, dans ce domaine, "jeter" un modèle est probablement moins coûteux.

Par ailleurs, il est évident que la réflexion sur le choix : "rewriting ou refactoring ?", est d'une part nécessaire (et peut être longue) et d'autre part dépend très fortement du contexte.

Si ce n'est pas cassé, ne le répare pas. (caricature d'ingénieur courante...)
C'est évident, mais c'est peut-être ce qu'oublie les boîtes produisant les codes dont parle Chad Fowler (une réécriture pour passer à Rails... Pourquoi ??? Pour être dans le "buzz" ? C'est pas sérieux ! Si Rails possède un avantage largement reconnu, c'est sa rentabilité en temps domimplementation, ou sa simplicité : pas ses perfs !)

Dans le cas de produits conséquents en taille et/ou en âge, ça peut effectivement être assez téméraire : j'avais entendu l'exemple d'un code de calcul américain important (environ 20 ans, peut être plus, leader dans sa branche : simulation dans le domaine nucléaire) dont la réécriture totale avait été tentée. Initialement codé en pur procédural (C ou Fortran, je ne me souviens plus) par des physiciens (donc avec une qualité d'implementation assez variable), le code "tournait". Mais un beau jour, conscients des problèmes énormes de maintenance, documentation et autres qui se posent sur ce type de produit, ils ont un beau jour décidé sa réécriture en POO avec C++. Une équipe de développeurs a été engagé spécifiquement dans ce but. Conclusion :
- Quasiment 6 mois de "mise en place"
- Environ 1 an d'implementation.
- 6 mois de tests de non-régression qui foirent, de bugs, etc...
==> Deux ans après le lancement de la réécriture, les clients se sont fait entendre dire qu'ils devaient repasser à la version majeure antérieure, vieille de 2 ans.

Donc effectivement, il faut aussi être raisonnable ^^

Mon modeste avis est le suivant : dans le cas de "gros" code à réécrire, si l'on suppose que l'on est en présence d'une équipe de dev suffisamment étoffée, la réécriture ne doit pas se faire sans la poursuite du développement de la version antérieure sur 2 trunks bien distincts. Sinon, effectivement, il est possible de se retrouver avec un produit longtemps indisponible ou buggé pour se retrouver avec au final une version "light" du produit précédent (ce que l'utilisateur final risque en effet d'assez mal digérer !!!).

Toujours est-il que cette question de la réécriture est assez importante et me paraît assez périlleuse en général !