jeudi 7 avril 2011

Agile Team Agreement

L'année dernière j'ai vécu dans une équipe qui marchait particulièrement bien. En essayant de comprendre les raisons de ce succès avec un autre des membres, Bernard Huguet, on a mis le doigt sur un pattern qui nous semble prédominant que l'on avait appelé l'Agile Team Agreement - l'ATA. On va essayer de décrire ce qu'on entend par ATA et partager la rétrospective que nous en avons fait. Mais avant d’aller plus loin je voudrais dire que nous ne l’avons pas inventé, l’idée derrière les Team Agreements ou Working Agreements existe sans doute depuis l’aube de l’homme et il n’y a rien d’obligatoirement agile, cela pourrait fonctionner dans n’importe quelle équipe. Le contenu serait juste différent.

Quoi de mieux que la photo de notre ATA pour décrire ce que c'est?


L'équipe a travaillé ensemble pour trouver et partager les pratiques qui lui paraissent être les facteurs clés de son bon fonctionnement. Il est essentiel que ce soit le résultat d'une participation active et équilibrée des membres de l'équipe, peut-importe comment vous y arrivez (pratiques de rétrospectives agiles peuvent aider ici). Exprimé sur un simple bout de papier, ce consensus est un réel contrat d'équipe et on s'attend à ce que tout le monde s'implique à 100%.

Au fil des mois on a pu observer un certain nombre de comportements que l’on pourrait imputer à l’ATA:

Fort sentiment d'appartenance à une équipe
Partager des valeurs, être fier de ce qu’on fait et savoir qu’on peut compter sur les autres membres de l’équipe crée un fort sentiment d’appartenance à cette équipe. C'est un élément important de motivation que d’avoir l’impression de faire parti de quelque chose de plus grand que soi.

Les équipiers ont du courage quand il le faut
Quand on a pris du retard sur un tâche ou que l’on subit une forte pression du management et du business, il est très tentant de discrètement prendre des raccourcis pour finir plus vite. Il y a deux avantages immédiats, 1) on tient les délais prévus et 2) on ne donne pas l’impression d’être lent ou mauvais. Certes on peut choisir de prendre des raccourcis mais ça doit certainement pas être pour sauver sa propre fierté. Les effets négatifs des raccourcis se font généralement sentir assez vite et on les paye souvent sur toute la durée de vie du projet.

Les post-its "Healthy Code", "Rendre problèmes visibles" et "As a team". Aident justement à donner du courage à rendre les problèmes visibles afin qu'un décision lucide puisse être prise par l'équipe.

Confiance partagée en chacun des équipiers
Puisque tes coéquipiers partagent tes valeurs tu peux avoir confiance dans leur travail. Par exemple, nous avions “rendre les problèmes visibles” et “DoD” (Definition of Done) dans notre ATA. Ayant confiance dans le travail de nos coéquipiers on pouvait se concentrer sur notre travail avec l’assurance que ça allait bien se passer et que si un problème survenait, il serait rendu visible rapidement et une action serait prise.

Tout le monde va dans le même sens
De manière générale on est tous influençable. On a envie de plaire aux gens de notre entourage. Autrement dit on va naturellement tendre vers ce que valorise notre entourage … du moment qu’on sait ce que c’est!

Puisque l’ATA rend visible ce qui a beaucoup de valeur pour les équipiers, alors il agit comme un centre de gravité comportemental qui soude l’équipe et qui l’aide à avancer dans le même sens.

Défini dans un contexte facile et utilisé dans un contexte difficile
SI quelqu’un vient régulièrement 5 min en retard aux stand-ups, ou si quelqu’un joue cavalier seul devant le PDG au détriment de quelqu’un d’autre, il est beaucoup plus facile de rappeler l’ATA que d’initier une discussion sur la ponctualité, ou de dire à qu’il a fait le beau devant le management.

Conclusion
Cela a bien marché pour nous et nous n’imaginons pas construire une nouvelle équipe sans cet ingrédient. C’est pour ça qu’on avait envie de partager ce bout de recette avec vous.

D’ailleurs nous sommes à nouveau tous les deux dans une nouvelle équipe et la construction de notre ATA est prévue pour demain :)

samedi 22 janvier 2011

Le CodeRetreat à Grenoble

Vendredi dernier c'était le CodeRetreat à Grenoble. Pour tout le monde c'était leur premier retreat, participants comme organisateurs! Pas facile alors de se lancer. C'est certain on y croyait, surtout après nos premiers tentatives sur le problème du Jeu de la Vie de Conway en décembre on a vu que ce problème était excellent pour nous ébranler dans nos habitudes de code et de TDD. Mais on ne savait pas encore si la journée allait être une réussite.

Maintenant c'est passé et on est très contents de l'avoir fait. C'était une journée intense et tout le monde a vraiment apprécié cette exercice. C'est marrant je crois que tout le monde était fatigué voire vidé à la fin de la journée - ça doit être signe d'avoir appris quelque chose!

La veille j'avais regardé ce vidéo d'introduction d'un CodeRetreat par le maître Yoda des CodeRetreats, Corey Haines, où il explique très bien que dans la vie de tous les jours on a l'obligation de résultat qui nous pousse à ne pas être parfait, à arrondir les angles, à prendre des raccourcis. Certes, c'est normal, obligé et même une bonne chose mais cela nous aide pas à progresser, à se rapprocher de "parfait". Dans le CodeRetreat c'est different, il n'y a pas d'obligation de résultat, même c'est presque impossible de finir en 45 minutes (le temps qu'on a avant de devoir effacer le code!!). C'est donc une occasion unique de s'entrainer au perfectionnisme. De recommencer et recommencer jusqu'à cela devient un automatisme.





Nous avons fini la journée avec une rétrospective où nous avons posé trois questions à chacun
  1. Qu'est-ce que tu as ressenti?
  2. Qu'est-ce que tu as appris?
  3. Qu'est-ce que tu appliqueras dès lundi?
Ces excellentes questions viennent d'un chevronné des CodeRetreats, Alex Bolboaca. En fait la journée est tellement intense et rempli d'expériences qu'il y a besoin de quelque chose de ce genre pour en tirer le maximum de profit. En groupe c'est d'autant plus intéressant car d'un côté le groupe nous oblige de formuler notre pensée la cristallisant ainsi, et de l'autre tout le monde n'a pas appris les mêmes choses et c'est intéressant d'entendre les autres.

Pour ma part j'ai l'impression d'avoir encore besoin de temps pour digérer les expériences de cette journée - et je n'ai à peine touché un clavier !

Seul petit bémol, j'aurais bien voulu qu'on ait le temps de faire une rétro de l'animation, mais tout le monde était trop fatigué. J'espère que les participants nous donneront leurs retours et leurs propositions d'améliorations, sans trop de retenu. En gros, lachez-vous ! ;)

J'ai envie de finir avec quelques commentaires que j'ai entendu au cours de la journée:
  • "Je vais instaurer le pair-programming au moins une demi-journée par semaine"
  • "Le Smalltalk c'est cool!"
  • "Je m'efforçais déjà à prendre des baby-steps mais là je vais le faire encore plus!"
  • "C'est vraiment bien d'écouter ce que me disent les tests pour trouver un meilleur design"
  • "C'est génial de pouvoir pairer avec autant de personnes"
Si vous n'avez toujours pas envie d'aller à un CodeRetreat ou d'en organiser un, allez donc lire ça!

Merci à nos sponsors : le CARA, l'Alpes-JUG et l'Ensimag

jeudi 2 décembre 2010

Tests super sonics

Hier j'ai assisté à une conférence au Alpes JUG, enfin plutôt deux du même présentateur, David Gageot. Il a d'abord parlé de Git, puis de ce qui m'intéressait plus - comment rendre et les tests très très rapides.

Algodeal tourne leurs 600 classes de test et 60 classes de tests fonctionnels/intégration en moins de 4 minutes!! David n'est pas allé dans le détail des métriques, mais cela couvrirait 60.000 lignes de code.





Voici la liste de conseils que j'ai trouvé pertinents :

  • Effacer du code (et tests) non utilisé (fonctionnalités devenus obsolètes)
  • Faire tout in-memory (DB, mail-server, http-server, ...)
  • Paralléliser (soit les threads junit, soit un projet multi-module)
  • No file access (Apache VFS, Spring ressources)
  • Prenez une suite de tests fonctionnels, découpez en UN test fonctionnel, TOUS les autres cas en tests unitaires.
  • Dans les tests fonctionnels il n'hésite pas à mocker les parties coûteuses
  • Battez-vous contre la complexité de votre application - les utilisateurs veulent une application simple, et il y a un fort lien entre la simplicité de l'utilisation et la simplicité de l'implémentation.
  • Faites un maximum de choses server-side - c'est bcp moins coûteux en temps d'exécution et maintenance de tests.
  • Si vous faites du ajax, encore une fois UN test fonctionnel (éventuellement pas sur plusieurs browsers). Toutes les variations en TU de javascript)
  • Rendez votre application plus rapide, les tests le seront aussi :-)

En regardant cette liste je me dis qu'il n'y a rien d'extraordinaire, mais ça m'a quand même fait l'effet d'une délivrance. C'est une chose d'avoir un sentiment, voire une conviction. C'est autre chose de voir quelqu'un l'appliquer avec succès.

Il a répété plusieurs fois que certes on peut mieux se protéger contre des bugs en prod (et encore je ne suis pas si sûr), mais à quel prix?

Les slides

Il a aussi parlé de GIT. Je m'en sers au quotidien et je savais déjà que c'était génial. Maintenant je sais que c'est mieux que ça.
Les slides

samedi 11 septembre 2010

Faisons plus d’interfaces fluides – puisque c’est simple!

Ca fait quelque temps que j’utilise des frameworks avec une interface fluide (cf Martin Fowler Fluent Interface). Je pense à Mockito, JMock2 et Hibernate Query API entre autres. Depuis peu j’utilise fréquemment le Test Data Builder Pattern. Ces derniers sont plutôt des Domain Specific Languages, une version évoluée des interfaces fluides. Mais je n’avais jamais réalisé que ce soit un jeu d’enfant de créer sa propre interface fluide. Prenons par exemple

Math.pow(3, 2)

Ca fait quoi au juste? Ah oui c’est l’exposant 3 de 2. Ou peut-être l’exposant 2 de 3?  Et si on écrivait plutôt



exponent(3).of(2)

Ici on voit bien ce qui se passe! Certes la javadoc de Math.pow(double a, double b) est clair et ça marche bien quant on écrit du code, mais pas quand on lit du code déjà écrit. Puisqu’on estime que du code est lu 10-100 fois plus qu’il n’est écrit (sans parler d’un framework open source), il est très important de rendre la vie facile à nos lecteurs.


Mais alors qu’est-ce ça demande comme effort de transformer Math.pow(a, b) en exponent(a).of(b)? Très peu en fait :



class Exponent {
private final double exponent;

public Exponent(double exponent) {
this.exponent = exponent;
}

public static Exponent exponent(double exponent) {
return new Exponent(exponent);
}

public double of(double base) {
return Math.pow(base,exponent);
}
}

puis un import statique dans la classe client



import static Exponent.exponent;

L’import statique avec le Factory Method exponent() jouent un rôle centrale, ils évitent le bruit syntaxique qu’il y dans



new Exponent(3).of(2)
//ou
Exponent.exponent(3).of(2)


J’ai pensé à cette astuce lorsque j’étais entrain de travailler sur un défi TDD – faire un convertisseur du système décimal vers un système quelconque. Dans ma solution il y avait cette fonction qui sert à calculer le chiffre à une position donnée dans le nouveau système. Ainsi si je veux transformer 3 en système binaire, pour connaitre si j’ai le chiffre à la position 0 (le plus à droite) je fais (3 modulo 2^1) quotient 2^0. Et pour la position 1 soit la plus à droite (3 modulo 2^2) quotient 2^1.


J’étais moyennement content de ça



private String digitAtPosition(int pos, int tenBaseNumber) {
int nextPos = pos+1;
long remainderOfNextPos = tenBaseNumber % nthPowerOfBase(nextPos);
long digitInTenBase = remainderOfNextPos / nthPowerOfBase(pos);
return convertSingleDigit(digitInTenBase);
}
protected final long nthPowerOfBase(int n) {
return round(pow(base,n));
}

on lit plus facilement



private String digitAtPosition(int pos, int tenBaseNumber) {
int nextPos = pos+1;
long remainderOfNextPos = tenBaseNumber % exponent(nextPos).of(base);
long digitInTenBase = remainderOfNextPos / exponent(pos).of(base);
return convertSingleDigit(digitInTenBase);
}

De plus cette classe extraite, Exponent, n’a rien de spécifique à mon convertisseur et pourrait potentiellement être utilisée ailleurs, promouvant ainsi la réutilisation. De plus et de manière générale une interface fluide est le début d’un DSL que l’on verrait plus facilement apparaitre à des parties du code fortement utilisés.


Et la performance?



Ca doit coûter cher de créer un objet à chaque fois, non?


Executer exonent(3).of(2) un million de fois prend 0,9s là ou Math.pow(2, 3) prend 0,64s sur mon portable, si j’augmente l’exposant à chacun des un millions d’appels (histoire de ne pas me faire avoir par une optimisation du JVM) j’obtiens 0,84s contre 1,4s. On reste tout de même à l’échelle du nano-second, alors à moins que cela soit le cœur de mon application je m’arrêtes volontiers à la deuxième étape dans ces bonnes principes



  1. Make it work


  2. Make it good


  3. (Then perhaps) Make it fast



Et si le besoin de rapidité apparait, il y a plusieurs façons d’attaquer le problème, revenir en arrière, ou introduire un cache des objets crées, ou en modifiant l’interface un poil :




exponent(3, of(2))
...

public static double of(double number) {
return number;
}



Des variantes de la classe Exponent



Pour ceux qui trouvent que la classe Exponent est trop verbeuse, il y a un peu plus bref ( en utilisant les double accolades pour accéder à l’instance initializer)



class Exponent {
double exp;
public static Exponent exponent(final double exponent) {
return new Exponent() {{
this.exp = exponent;
}};
}

public double of(double base) {
return Math.pow(base,exp);
}
}

encore une autre qui évite la variable d’instance et qui permet d’autres implementations de of() – par exemple log(logBase).of(someNumber).



class FluidMaths {
public static Exponent exponent(final int exponent) {
return new Exponent() {
public Long of(int base) {
return round(pow(base,exponent));
}
};
}

interface Exponent {
public Long of(int base);
}
}





 






  

mardi 20 avril 2010

Amélioration des rétrospectives – une approche minimaliste

Les rétrospectives dans l’équipe dans laquelle je travaille laissent beaucoup de place à l’amélioration : En fin de sprint de deux semaines on fait un tour de table pour avancer les points positifs et les points d’amélioration. Point.

On était deux dans l’équipe à souhaiter quelque chose de plus ambitieux. Alors on s’était renseigné pour avoir une personne extérieure à l’équipe, voire un coach. Pour divers raisons rien s'était passé en six semaines, alors on a décidé d’améliorer ce que nous avions déjà avec les moyens du bord. Le déclencheur a sans doute été notre présence à XP Days Suisse où nous avons assisté à une session sur les rétrospectives (compte rendu de Bruno Orsier, Luc Jeanniard)

Nous avons commencé par revoir la dernière rétrospective pour savoir s’il y avait des points importants qui n’avaient pas été adressés. Ensuite nous avons conduit la rétrospective comme avant.

Au lieu de laisser les points d’amélioration cachés dans une page au fond d’une application quelque part, nous avons priorisé les points. Chacun pouvait voter pour les deux points qu’il trouvait les plus important. L’engagement était de faire quelque chose pour les 2-3 points les plus importants dans le sprint suivant. Voici nos points :

  1. Améliorer la qualité des scénarios de BDD (Behavior driven development)
  2. Diminuer le délai entre le début d’une livraison et la mise en production (le problème étant surtout un problème de délai et non de charge de travail)
  3. Faciliter le ramp-up de deux collaborateurs arrivés récemment en imprimant un schema de la base de données.

Le point 3 étant très simple nous l’avons simplement fait le lendemain.

Pour améliorer la phase de déploiement nous avons décidé d’actions concrètes :

  • Evaluer en détail la faisabilité de plusieurs pistes connus pour simplifier la procédure de déploiement, notamment en éliminant les tâches manuelles.
  • Décrire au moins deux options d’architecture pour permettre un blue-green deployment.

Ces deux actions ont été planifiées dans le sprint AVEC une priorité importante – afin d’être sûr qu’elles seront adressées.

Finalement pour adresser le premier point nous avons discuté avec tous les acteurs concernés afin d’établir un plan d’action. Le voici :

  • Product Owner : exprime ses idées à travers un scenario
    • afin de venir avec des propositions plus réfléchies
  • Product Owner + Scrum Master + Dev Lead : font des backlog reviews systématiques avant le sprint planning. Cette réunion donne lieu à deux livrables
    • DraftScenarios (Des scenarios suffisamment précis pour une estimation en poker planning)
    • Une priorisation du product backlog
  • Product Owner + dévelopeur(s) : écrivent ensemble les GoScenarios ( ce qui signifie des scenarios prêts pour être développés).

Conclusion

Avec des améliorations ultra simples nous allons, je pense, tirer beaucoup plus des rétrospectives qu’auparavant. C’est tellement simple que j’avais l’impression que c’était bête d’en blogger, mais à mon avis cette équipe n’est pas la seule à faire des rétrospectives bâclées. Et cette expérience montre que même avec peu de moyens en temps et en connaissance on peut faire des améliorations importantes.

Prochaines étapes :

  • Lire ce livre
  • Faire une rétro un peu plus longue en jouant toutes les phases d'une rétro avec root cause analysis
  • Afin d'avoir des animateurs qui ne font pas parti de l'équipe (c'est plus facile d'animer une retro si on est partie prenante!) on a eu l'idée qu'un de nous fasse la rétro d'une autre équipe et que cette autre équipe nous rende le service.

dimanche 24 janvier 2010

Sonar & eclipse + PMD & Checkstyle & Findbugs

J’aime beaucoup le feedback rapide que donne les plugins PMD, Checkstyle et Findbugs dans Eclipse. Mais il y avait certains freins à l’utilisation:

  • Checkstyle a trop de règles activées par défaut. Le travail de désactivation est laborieux.
  • Ce n’est pas facile de faire en sorte que tout le monde dans une équipe utilise les même règles.
  • Surtout lorsqu’on décide de les mettre à jour.
  • Sonar utilise les mêmes plugins, avec une configuration différente par défaut. Le résultat est que beaucoup de violations perdurent car c’est bien plus compliqué d’aller voir l’interface Sonar que de réagir à un avertissement qui apparait dans l'IDE.

Une solution est de centraliser les règles de à travers Sonar permettant ainsi de maintenir un seul ensemble de règles. Ce que je décris ici est une suite à un billet sur Checkstyle par Freddy Mallet.

Installer les plugins CheckStyle, FindBugs et PMD

Dans Sonar aller dans Configuration => Quality Profiles. L'onglet Permalinks copier les liens vers les règles PMD/CheckStyle/Findbugs pour chacun des profiles.

Dans Eclipse => Menu Window => Preferences :

  • Checkstyle -> New... -> Remote Configuration
  • Location : http://<sonar>/rules_configuration/export/java/<rule-name>/checkstyle.xml
  • Press 'Set as Default'

  • PMD -> (subsection) Configuration des règles -> Tout effacer -> Importer un ensemble de règles :
  • http://<sonar>/rules_configuration/export/java/<rule-name>/pmd.xml
  • Press OK

  • Findbugs
  • download file http://<sonar>/rules_configuration/export/java/<rule-name>/findbugs.xml
  • Window –> Preferences -> Java -> (subsection) Findbugs -> Filter files
  • Add the downloaded file to 'include filter files'

Petit plus. Je trouve les règles Checkstyle dans le profil par défaut de Sonar beaucoup plus pertinentes que celles livrées avec le plugin pour Eclipse.

Depuis peu un plugin sonar pour eclipse est disponible.

Edit 2011-04-07 :
- mis à jour l'endroit dans sonar où on trouve les liens des profiles
- ajout lien plugin sonar