La sortie que tout le monde attendait…
29 juin 2007 par Alexis KARTMANNEclipse 3.3 est là !
Je viens de terminer la lecture d’Ajax par la pratique, chez O’Reilly.
C’est le genre que bouquin que j’aime lire maintenant, parce que ce n’est pas qu’une collection de bout de code ou une copie de document de référence. Franchement avec un accès internet et vu le nombre de sites d’exemple et de documentation qui existe je ne comprends pas que l’on publie encore des bibles remplis de code source et de verbatim des documentations officielles.
A l’inverse, et contrairement à ce que son titre pourrait laisser croire, Ajax par la pratique est plutôt un guide général, et pas une suite de travaux pratique.
Après une présentation générale, on attaque direct avec une étude de cas sur Google Maps, avec création d’une solution utilisant les même principes. Evidement avec ce sujet, j’était particulièrement intéressé.
Ensuite les principes de base d’Ajax sont présentés, avec du code qui permet de mieux visualiser, et un fil rouge qui est l’intégration d’Ajax dans un site existant.
Les principaux Framework sont présentés (Json, Prototype, Script.aculo.us, Dojo, Atlas, DWR), ainsi que l’intégration avec les environnements de développement web serveur (Java, PHP, Rails, Asp.net).
C’est assez vivant, pas trop technique, mais quand même réservé à un public connaissant au moins html et javascript.
Bref je le conseille à tous ceux qui veulent se lancer dans Ajax et se demandent par où commencer.
Je n’ai pas parlé de XP et de qualité depuis quelques temps, mais cet article pointant vers un de mes vieux billets est très intéressant.
J’ai particulièrement apprécié l’explication sur la sur-qualité, qui est un peu le défaut que j’ai constaté sur certains projets, notamment quand le management à demandé que le produit ne sorte que quand il sera parfait
. Et on se retrouve avec des réponses à des problèmes qui n’en sont pas.
Cela me rappelle une réflexion sur l’innovation, qui n’est le fait d’ajouter sans fin des fonctionnalités, mais plutôt d’enlever celles qui sont futiles pour se concentrer sur l’essentiel.
Ainsi voici donc le secret d’un projet logiciel réussi :
Après un longue pause, voici le retour du feuilleton sur la mise en place de l’eXtreme programming dans une dotcom. Et pour ce grand retour, quel meilleur sujet que la responsabilité collective du code ?
Rappelons que la responsabilité collective du code consiste, dans un projet, à donner à tous les membres de l’équipe le droit de modifié la totalité du code source. C’est donc contraire au principe souvent utilisé de responsabilité individuelle du code, dans lequel chaque développeur est responsable du code qu’il a écrit et reste le seul à avoir le droit et le devoir de le modifier.
La responsabilité collective du code s’est avérée, dans le cas qui nous occupe, l’une des pratiques qui semblait la plus naturelle (à l’opposé du travail en binôme, par exemple), mais dont la mise en place c’est le plus heurté à des barrières psychologiques.
Voyons lesquelles.
Il y a d’abord le caid, le dieu vivant du développement. Tellement bon et conscient de son niveau qu’il ne peut pas laisser les autres toucher à son code. Ou alors il faut qu’il refasse tout derrière.
Alors même s’il souffre d’être le seul à pouvoir toucher son code, il aura du mal à le partager. De la rétention de code, en somme.
De l’autre côté, il y a le programmeur humble (très rare, mais il existe). Face au caid, il est impressionné. Tellement qu’il n’ose même pas imaginer qu’il pourrait faire la même chose.
Alors l’idée qu’il puisse toucher au code de son idole le paralyse.
Le binômage, le binômage. Tout est là. On mélange les niveaux, la connaissance du code se partage, le niveau technique général s’améliore.
Du moins en théorie. Ce fut même globalement le cas. Mais pas sans heurt.
Après la phase initiale de méfiance, la propriété collective code écrit sur le nouveau projet s’instaura sans restriction. Ce ne fut pas le cas de l’existant tout de suite. Mais comme la majorité du travail était lié au nouveau projet ce ne fut pas un problème.
En fonction des scénarios utilisateur et des tâches de développeur, chaque binôme intervenait sur toute les parties du code sans autocensure ni blocage.
Mais on vit apparaitre un nouveau comportement chez les caïds, finalement assez voisin de la rétention de code.
Un binôme réalise une tâche de développement. Par la suite un binôme de caïds doit travailler sur le code, et décide de faire un remaniement. En fait remaniement, c’est presque une réécriture qui est réalisée.
Quelque soit l’humilité du binôme, voir son code complètement réécrit est une sacrée remise en cause.
Le pire, c’est même qu’après un certain temps les caïds commencent à systématiquement remanier le code des autres binôme.
Voyant cela j’étais un peu pessimiste quand à la productivité de l’équipe. En effet quel intérêt de tout refaire systématiquement, autant tout faire faire par les caïds.
En fait le simple fait d’avoir écrit un code et les tests associés rendait quand même le travail de remaniement plus facile pour les caïds que s’il avait du tout faire eu même. Donc la perte de productivité n’était pas si évidente.
Et le remaniement des caïds eut finalement un effet pédagogique. Le fait de voir son code réécrit par les caïds permit aux autres binômes de mieux comprendre ce qu’il fallait faire. De plus le code existant étant souvent la base des nouveaux développements, le fait de laisser les caïds faire du remaniement tend à améliorer la qualité du code.
Finalement si le remaniement des caïds n’a pas eu l’effet dévastateur que l’on pouvait craindre, c’est parce qu’il existait un vrai esprit d’équipe. Mais avant la responsabilité partagée du code, l’esprit était là, mais pas la pratique. Avec la responsabilité partagé, le code est vraiment devenue une œuvre collective, et non plus une collection d’œuvres individuelles.
Dans l’édition du 2/9/2005 de 01 informatique, un article présente Ajax comme “la nouvelle coqueluche du web”.
L’article est assez complet, et expose bien les avantages et les limites de cette technique à la mode.
Les exemples d’utilisation sont centré sur les application Google :
Curieusement ni MSN Mappoint, ni Mapquest, ni Virtual Earth ne sont cités, alors qu’ils offrent les même avantages que Viamichelin.
Mais quoi qu’il en soit, sans Ajax (ou Flash pour Mappy) pour rendre la navigation plus fluide, un site de cartographie n’est plus crédible… Ce qui est dommage, car dans ce domaine une belle interface ne fait pas tout.
Mon frère vient de réaliser un outil de test de site web utilisant le modèle de document de IE6 et javascript. Ce qui permet de tester aussi les parties dynamiques générées sur le client en javascript. Evidement cela reste pour le moment limité à Internet Explorer comme client mais le concept pourrait être porté sous d’autres navigateurs.
Personnellement je n’ai pas testé cet outil mais connaissant l’auteur je ne peux que le recommander…
Bons tests !
Et non cher lecteur, le feuilleton eXtreme Programming n’est pas fini ! J’ai seulement eu d’autres projets quelque peu prenants (nDumbster entre autre).
Parlons donc du remaniement constant (constant refactoring). Il ne s’agit pas de déplacer régulièrement les personnes dans l’open space, même si cette pratique était aussi en vogue dans notre dotcom (on parlait de réorganisation spatiale !), mais de ne pas hésiter à modifier le code afin de le rendre plus propre, plus simple, plus maintenable.
Le remaniement est rendu possible par la présence de tests unitaires suffisants pour permettre des changements plus ou moins profonds dans le code sans risquer d’en perturber le fonctionnement (du moins une fois que tous les tests passent, bien sur). Sans une couverture complète du code par des tests unitaires, le remaniement constant devient une activité proche du saut à l’élastique sans élastique. Je parle de couverture complète, et non pas totale, pour signifier qu’il s’agit d’avoir voir suffisamment de tests pour tester “tout ce qui peut casser”.
Harnaché avec ses tests unitaires, le développeur peut donc se lancer dans les remaniements les plus audacieux, et cela sans le moindre risque. Enfin presque. Du moins nous avons constaté la fin de cette peur de perturber du code existant dont l’effet le plus visible chez nous était la tendance à dupliquer le code plutôt qu’a l’adapter à un nouveau besoin. Nous avions ainsi dans notre code ASP une pléthore de fonctions presque identiques à quelque variation près. Tout le monde avait peur de modifier une fonction existant en introduisant une variable supplémentaire afin d’éviter du code redondant, par exemple.
Refactoring de Martin Fowler, bien qu’illustré par des exemples en Java est très bien adapté à C# (quel hasard !). L’auteur y présente une liste de remaniement unitaire type qui permettent d’améliorer l’architecture d’une application.
Et c’est bien là ce que permet le remaniement constant. A partir de petites améliorations, mais que l’on fait constamment, on obtient une application dont l’architecture est bonne tout au long de sa vie.
C’est bien évidement à l’encontre de l’approche classique, dans laquelle un architecte définira en détail l’architecture de l’application à partir de son cahier des charges. Comme en XP le cahier des charges détaillé n’existe pas, l’architecture détaillé non plus. Disons plutôt qu’on la construit au fur et à mesure.
Ceci ne rend cependant pas inutile tout notion d’architecture, mais change seulement la façon dont on la construit. En fait en XP on construit quasiment en même temps le cahier des charges, l’architecture et le code !
Dans le contexte d’un logiciel dont la définition n’est pas figé, sur un marché changeant, avec des clients ayant du mal à exprimer explicitement leurs besoins, mais capable de formuler précisément des demandes d’évolution, eXtreme Programming s’est révélé efficace. Et le remaniement permet d’obtenir une architecture homogène et non un patchwork de fonctionnalités collés ensembles.
Parmi les effets néfastes du refactoring si l’on n’y prend pas garde, c’est qu’il devient l’excuse du perfectionniste en retard. “D’accord j’ai passé trois jours sur cette tache prévue pour un jour, mais j’ai fait deux jours de refactoring”. Dans ce cas, je rappelle que le remaniement doit être constant, c’est à dire répartie durant les taches de développement, et non pas considéré comme une tache indépendante. On ne fait pas du remaniement sur n’importe quelle partie du code, mais sur une partie de code que l’on doit modifier pour une tâche en cours.
Il y a une bonne comparaison (je crois qu’elle vient de Kent Beck) entre le remaniement et le fait de nettoyer sa cuisine. Il vaut mieux cuisiner dans une cuisine propre (donc développer avec un code propre), mais on peut soit nettoyer sa cuisine avant de cuisiner, soit après avoir cuisiné, soit pendant qu’on cuisine. Et évidement si on nettoie pendant qu’on cuisine, le temps que l’on passe dans la cuisine n’est pas tellement plus long, alors que nettoyer avant de cuisiner risque de prendre plus de temps, surtout les casseroles bien sales ! Bref c’est lorsque l’on remanie son code durant l’écriture que le remaniement est le moins couteux.
Il reste encore quelques pratiques d’eXtreme Programming à traiter avant la fin de ce feuilleton. Si vous avez des questions ou des points que vous voudriez voir traiter, n’hésitez pas. Amis eXtreme Programmers, ne soyez pas triste à l’annonce de la fin proche, j’ai encore d’autres expériences à raconter. Notamment de l’eXtreme Programming en solo !
A suivre…
Pour tester un programme envoyant des emails, on peut utiliser un mock object du composant d’envoi de message, mais on n’est pas certain que les paramètres sont corrects, et il faut un mock object par composant d’envoi de message.
Une autre solution est d’utiliser un serveur vrai SMTP et d’envoyer tous les tests vers une adresse mail dédié. Mais la vérification ne peut être manuelle.
Aucune de ces solutions n’était vraiment satisfaisants quand un contexte d’automatisation des tests, notamment en développement piloté par les tests.
Mais il existe une solution bien plus élégante. Dumbster est une librairie Java qui implémente un vrai serveur SMTP. Par contre les mails reçus sont stockés dans une listes au lieu d’être relayés. Il suffit de l’utiliser dans une librairie de test JUnit pour automatiser complètement le test d’envoi de message. Une bonne nouvelle pour monsieur toto@mail.com qui va arrêter de recevoir des messages bidons (histoire véridique).
Pour les développeurs .Net comme moi, il existe un portage de Dumbster en C#, NDumbster. La version actuellement en ligne n’est pas très fonctionnelle, mais cela devrait changer, notamment grâce au patch que j’ai soumis. Avec cette version, j’ai pu tester un système de gestion de mailling list en quelques heures au lieu de quelques jours (avec en plus des tests automatiques complets).
Ne faites plus d’application envoyant des mails sans ces librairies !
Continuons notre série en parlant un peu d’une pratique qui n’est pas propre à XP, mais tout processus de développement discipliné : l’intégration continue.
Le but est d’éviter un phénomène classique de rétention de source : Un développeur garde du code sur son poste plusieurs jours (semaines/mois ?) sans le réintégrer dans le système de gestion de source. Lorsqu’il effectue la réintégration, il peut passer un long moment à régler les conflits avec d’autres modifications effectué. Et dans certains cas, une réintégration un peu brutale peut provoquer d’autre problèmes (le fameux effet papillon).
Pour éviter cela, l’intégration continue consiste à réintégrer très régulièrement les sources dès que le développeur a atteint un état stable de l’application (c’est à dire dès que ses tests passent).
Un élément nécessaire pour l’intégration continue est l’utilisation d’un outil de gestion de version comme CVS ou Subversion. Dans notre cas, vu l’utilisation de Visual Studio, nous avons naturellement utilisé Visual Source Safe (VSS). VSS était configuré en mode verrou partagé. Cela signifie que plusieurs développeurs peuvent travailler sur le même fichier (C’est un peu comparable au mode de fonctionnement de CVS). C’est lors de la réintégration que l’on gère les conflits éventuels.
Lors de la présentation de l’organisation spatiale, j’avais parlé de la machine de build. Lorsqu’un binôme a terminé une tâche élémentaire, et que tous les tests passent sur sa machine, les sources sont réintégrés dans VSS, puis le binôme se rends devant sur la machine de build, récupère tous les sources de VSS (et pas seulement ceux qu’ils ont modifiés), recompile l’application et lance les tests. Si un problème se produit, ils doivent le corriger avant de retourner à leurs poste (ou de rentrer chez eux).
Lorsque les tests se passent bien sur la machine de build, les binaires sont copié dans un répertoire de livraison et installé sur le serveur de pré-production, avant d’éventuellement mis en production si l’équipe marketing valide cette version. Au départ afin de signaler qu’une livraison a été faite, on utilisait une crécelle, mais le bruit était un peu trop fort et son utilisation n’a pas duré.
Après une réintégration réussie, le binôme peut récupérer sur son poste de travail les dernières versions de code sur VSS, puis démarrer une nouvelle tâche. Et systématiquement avant de commencer à travailler le matin on récupère les dernières versions.
L’utilisation de la machine de build s’est vite généralisé, et finalement peu de problème de conflit ont eu lieu, ce qui fut un grand changement par rapport au passé (alors même qu’il y avait peu de code dont la responsabilité était partagée). Aujourd’hui la machine de build serait sans doute remplacé par un serveur de construction automatique comme CruiseControl.Net.
Malgré cela, l’intégration continue, couplée avec les tests unitaires, est la clé du succès de la responsabilité partagé du code. On en reparlera.
A suivre
Après avoir traité de pratique de gestions de projet, revenons aux pratiques de programmation avec les règles de codage.
Ces règles furent discutées lors d’une réunion de l’équipe, en suivant les principes de simplicité et la contrainte suivante : moins de 10 pages pour les règles complètes, et la possibilité d’une version compacte tenant sur 2 pages que l’on placerait sur chaque poste de développement. L’expérience montrant que les règles trop complexes et nombreuses ne sont jamais suivit, ces contraintes sur la taille réduite en rendaient l’application plus probable. Il est vrai qu’aujourd’hui de nombreux outils permettent de valider automatiquement le respect de règles lors de la compilation ou avant la réintégration de fichier dans le système de gestion de source, mais nous devions faire avec les moyens du bord, à savoir l’équipe (ce qui est d’ailleurs conforme à l’esprit XP, qui privilégie les hommes plutôt que les outils).
A l’issue de la réunion, un document récapitulatif a été rédigé, ainsi qu’un guide synthétique de 2 pages. Placé dans un protège document transparent, ce guide sera utilisé en référence par tous les développeurs.
Mais voyons plus en détails les règles issues de la réunion.
Ce terme désigne la manière de présenter le code dans un but de faciliter la compréhension. Il comprend les méthodes d’indentation et de déclaration de variables.
On choisi d’utiliser le style dit « côte ouest », par opposition à K&R. C’est-à-dire le style supporté par défaut par Visual studio. Et nous utilisions une tabulation de 2 espaces configurée dans l’éditeur (plutôt qu’avec le caractère tabulation) afin d’avoir une présentation identique sur tous les postes.
Ce qui donne quelque chose comme ceci :
Plutôt que de définir une stratégie de césure des lignes trop longues, nous décidons de remanier systématiquement ces lignes.
Ainsi
Sera remplacé par :
De même une fonction possédant une grande collection de paramètre sera traité en regroupant les paramètres dans une classe. Naturellement ce principe ne s’applique que pour des fonctions ayant une grande collection de paramètre. Il s’agit d’une certaine façon d’un remaniement qui consiste à regrouper des paramètres liés entre eux dans une structure ayant un sens, le nombre de paramètre élevé étant un indicateur (code smell) de ce remaniement nécessaire.
Les noms des variables devront avoir une signification claire. De plus la déclaration d’une variable devra se faire au début du bloc de code l’utilisant. Ceci est un bon compromis entre la lisibilité (déclaration des variables regroupé) et la performance (il faut éviter de déclarer des variables qui pourrait ne pas être utilisé).
Il s’agit ici de définir la manière dont on nommera un élément en fonction de son type ou son usage. Il existe de nombreuses conventions, notamment la notation hongroise qui consiste à utiliser un préfixe définissant le type d’une variable. Cette notation peut vite devenir lourde à gérer, et surtout n’est plus vraiment adapté à des langages objet, puisque la plupart des variables seront d’un type non prévue par la notation. De plus avec les éditeurs modernes on trouve très facilement le type d’une variable si nécessaire.
Notre convention portera donc surtout sur la capitalisation des noms en fonction de l’objet nommé.
Le nom commencera par une majuscule, et chaque mot accolé au premier commencera aussi par une majuscule.
Une classe n’aura pas de préfixe particulier, alors qu’une interface commencera par la lettre I.
On essayera de ne pas utiliser d’abréviation, sauf pour des termes très répandu.
Par exemple :
Comme pour une classe, le nom commencera par une majuscule, et chaque mot accolé au premier commencera aussi par une majuscule.
On utilisera plutôt un verbe indiquant l’action que la méthode effectue.
Pour faciliter la compréhension, on inclura dans le nom des paramètres une information sur l’unité utilisé si nécessaire.
Par exemple :
Est plus clair que :
On utilisera une minuscule pour le premier mot, et une majuscule sur les mots suivant.
Le nom sera entièrement en minuscule.
Le nom sera entièrement en majuscule. On séparera les noms par un caret : _.
Les noms des énumérations utiliseront la règle s’appliquant aux classes, et les valeurs celle des constantes.
L’un des principes de XP est que la documentation est dans le code. Plutôt que d’avoir un code obscur nécessitant une documentation pour le comprendre, on s’appliquera à obtenir un code simple et clair. Par contre dans le cas ou une documentation est nécessaire, notamment pour les APIs, on utilisera un outil de génération de documentation (comme XMLDoc pour C# ou doxygen pour C++) pour maintenir la documentation dans le code source. Cette pratique limite fortement le risque de divergence entre la documentation et la réalité du code.
Même si les règles n’étaient pas toujours respectées, le fait d’avoir un consensus sur l’objectif s’est avéré très positif sur l’évolution du code. On a ainsi évité les discussions lié à la responsabilité collective du code sans que des règles claires soit définis (les fameux : « qui a foiré mon indentation ». et autres joyeusetés). On en reparlera bientôt en traitant justement de la responsabilité collective du code.
A suivre.