mercredi 20 mai 2009

2 ANTIPATTERNS DE BINOMMAGE

Nous pratiquons le Pair Programming. Pas 100% du temps, mais le plus possible.

Nous pilotons nos activités avec un Kanban. Chaque étiquette du Kanban est un post-it sur un tableau. Chaque post-it représente une tâche à mener. Sur ces post-it, nous nommons les équipiers qui participent à sa réalisation.

En surveillant la liste des équipiers sur les post-it, nous avons pu identifier 2 antipatterns de Pair Programming. Il en existe bien plus, mais ceux là nous amusent bien.

A + B - B, ou le "Ca pue, je me casse"

Nico est le premier assigné à une tâche. ManU vient binommer avec Nico. Après quelques heures, ManU trouve une tâche plus prioritaire à mener. En fait, après avoir vu ce sur quoi travaillait Nico, ManU s'est mis en tête de trouver une tâche plus prioritaire. Il s'agit d'une manière agilement correcte de dire "Ta tâche pue, je me casse!".

A + B - A, ou le "Je te délègue ma bouse"

ManU est le premier assigné à une tâche. Nico vient binommer avec ManU. Après quelques heures, ManU trouve une tâche plus prioritaire à mener. Il s'agit d'une manière agilement correcte de dire "Je te délègue ma bouse!".

Les patterns sont un langage de travail

Désormais, dans notre open space, nous entendons des développeurs se dire: "Mais, tu ne serais pas en train d'essayer de me faire un A + B - A?".

Pas très agile tout ça

Certains extrémistes s'évertueront à dénoncer qu'il s'agit de manquements aux valeurs, principes et pratiques de l'agilité. C'est vrai, mais parfois nous sommes aussi des hommes. Et puis on se marre bien dans l'équipe ;o)

lundi 18 mai 2009

AGILITY AND LEAN FOR AVIONICS, EN VIDEO

Voici la vidéo de ma conférence donnée chez AdaCore à l'occasion de l'évènement The Lean, Agile Approach To High-Integrity Software. La vidéo est en quatre parties.

Partie 1 sur 4:


Partie 2 sur 4:


Partie 3 sur 4:


Partie 4 sur 4:


Les slides de la présentation sont disponibles ici et l'article ayant servi à préparer la conférence est consultable ici.

Les vidéos ont initialement été mis en ligne sur le site OPEN-DO. Vous y trouverez les vidéos des autres présentations de l'évènement.

samedi 16 mai 2009

LA CHUTE

J'aime bien quand on rit de l'agilité. C'est agréable de ne pas se prendre au sérieux. L'analogie n'est pas heureuse, mais j'ai adoré ce détournement. Le son est obligatoire même s'il n'apporte aucune information.

samedi 25 avril 2009

L'INTÉGRATION CONTINUE EST UN SYSTÈME MULTITACHE

Ce billet est consacré à une pratique de l'intégration continue et au parallèle que nous pouvons dresser entre le développement concurrent avec intégration continue et les systèmes multitâches.

3 IDÉES
  • Je vais commencer par vous expliquer comment nous pratiquons une forme sécurisée de l'intégration continue.
  • Ensuite, j'évoquerai un problème propre à l'intégration continue et je présenterai les solutions que nous avons mis en place pour y remédier.

INTÉGRATION SÉCURISÉE

Pour qu'un développeur de notre équipe contribue au projet en délivrant ses travaux, il utilise un script qui automatise les activités suivantes:
  1. Identification des modifications: Il s'agit du "commit" ou "checkin" des fichiers modifiés de l'espace personnel de travail. Un éditeur texte est ouvert pour que le développeur justifie ses modifications.
  2. Synchronisation de l'espace personnel: L'espace personnel de travail est synchronisé par rapport à la référence du code en y important les nouveautés de la référence du code.
  3. Build et test de l'espace personnel: Le build est lancé et l'intégralité des tests xUnit sont exécutés dans l'espace personnel. Cette étape s'assure que les modifications du développeur sont compatibles de la référence du code.
  4. Synchronisation de la référence: Si le build et tous les tests ont réussi, alors les modifications de l'espace personnel sont délivrées dans la référence du code.
  5. Build et test de la référence: En moins d'une minute, l'outil d'intégration continue détecte la modification de la référence du code et lance un build incrémental avec rejeu de tous les tests xUnit. En général, le défaut type détecté par cette étape est un nouveau fichier source introduit dans le produit par le développeur et non géré par l'outil de gestion des versions.
Il s'agit d'une démarche de contribution sécurisée car le développeur ne peut délivrer des modifications incompatibles avec la référence du code. En effet, l'étape 3 interdit la livraison des modifications si le build ou le test de la version intégrée échoue. La référence du code est donc protégée contre l'injection de défauts.
Cette synchronisation est fluide car elle est automatisée et courte. Elle ne dure que de 2 à 3 minutes environ. Ainsi, chaque développeur se synchronise plusieurs fois par jour pour entretenir une intégration continue du produit en développement.

INTÉGRATION CONTINUE OU INTÉGRATION PERPÉTUELLE?

Néanmoins, il existe un point faible dans cette démarche, entre l'étape 2 et l'étape 4. Pour le comprendre, analysons le scénario suivant.
Supposons que Jacques et Paul soient deux développeurs de notre équipe. Jacques a terminé une étape de son travail et souhaite la délivrer dans la référence du code. Il lance le script d'intégration. A l'étape 2, il a récupéré chez lui les nouveautés de la référence du code. Il en est à l'étape 3: les tests sont en cours d'exécution dans son espace personnel.
Il se trouve que Paul avait commencé une synchronisation quelques minutes ou secondes avant Jacques. Alors que Jacques en est encore à l'étape 3, Paul en est déjà à l'étape 4: il délivre le résultat de son travail dans la référence du code.
Maintenant, c'est au tour de Jacques de passer à l'étape 4 et de délivrer son travail. Mais la référence du code a changée car elle a été enrichie des travaux de Paul. Donc, Jacques vient de finir son intégration et pourtant il n'est déjà plus synchronisé avec le version de référence du code! Il ne peut donc pas délivrer son travail et il doit reprendre son intégration depuis le début, à l'étape 1.

Ce petit scénario n'est pas bien grave. Jacques n'a perdu que 3 minutes. Maintenant, comprenez que notre équipe est composée de plus de 15 développeurs qui se synchronisent plusieurs fois par jour. Ce scénario de collision a donc une forte probabilité d'occurrence et l'intégration de Jacques peut durer des heures. Pour Jacques, l'intégration continue est devenu une intégration perpétuelle.

LE PROBLÈME

Nous nous sommes rendu compte qu'un seul développeur de l'équipe peut intégrer à la fois. L'intégrateur doit bénéficier d'un accès exclusif à la référence du code pour intégrer ses travaux sans être perturbé par les modifications d'autres développeurs. L'outil de gestion de configuration de gère pas cette exclusion mutuelle car l'intégration est composée de plusieurs commandes atomiques de gestion de versions.

GIZMO, OU L'EXCLUSION MUTUELLE EN INTÉGRATION

Depuis plusieurs projets, nous avons décidé de régler ce problème à l'aide d'une simple peluche, baptisée Gizmo par l'équipe. Pour intégrer ses travaux, un développeur doit poser cette unique peluche sur son écran. A la fin de sa synchronisation, il libère la référence du code en retirant le Gizmo de son moniteur. Ainsi, nous avons très simplement organisé l'intégration exclusive des travaux dans la référence du code.
Il se trouve que la pratique du Gizmo a deux autres bénéfices très importants expliqués en détail dans la description de nos pratiques d'équipe.

LE VERROU NUMÉRIQUE D'INTÉGRATION

La pratique du Gizmo suffit pour assurer l'exclusion mutuelle des développeurs en intégration dans le cas où l'équipe partage le même bureau. En effet, il faut visualiser où est Gizmo et pouvoir le prendre. Or, certains (rares) contributeurs à notre projet ne sont pas dans notre open-space. Nous avons alors décidé de doubler la peluche Gizmo par un verrou numérique. La séquence automatisée par le script d'intégration est donc devenue:
  1. [Nouveau] Recherche du verrou. Si la référence du code est verrouillée en intégration, la séquence est interrompue et on demande au développeur d'intégrer plus tard;
  2. [Nouveau] Verrouillage de la référence du code.
  3. Identification des changements;
  4. Synchronisation de l'espace personnel;
  5. Build et test de l'espace personnel;
  6. Synchronisation de la référnce du code (si les tests ont réussi!);
  7. [Nouveau] Libération du verrou;
  8. Build et test de la référence du code par l'outil d'intégration continue.
Le verrou est un simple fichier créé et supprimé dans la référence du code. Ce verrou numérique ne remplace pas pour autant le Gizmo en peluche. En effet, l'utilisation de la peluche présente deux autres bénéfices très intéressants (se référer à la description de nos pratiques d'équipe).

DÉVELOPPEMENT CONCURRENT AVEC INTÉGRATION CONTINUE ET SYSTÈME MULTITACHE

Pour comprendre la nécessité d'un verrou d'intégration, il suffit de faire un parallèle avec la programmation concurrente et les systèmes miltitâches.

Une équipe qui pratique le développement concurrent est un système multitâche. En effet, chaque développeur (ou binôme) est assimilable à un thread concurrent qui mène ses activités en parallèle des autres.

Si les développeurs pratiquent l'intégration continue, alors ils se partagent une ressource. Il s'agit de la référence du code. La séquence de synchronisation avec la référence (étapes 1 à 4) est donc une section critique. Un seul développeur à la fois doit la dérouler. Puisqu'il s'agit d'une section critique, il convient d'en assurer une utilisation exclusive à l'aide d'un mécanisme d'exclusion mutuelle, comme les mutex ou les sémaphores. La peluche baptisée Gizmo ou le verrou numérique sont en fait un sémaphore (à un jeton) tel qu'il en existe dans les OS temps-réel pour gérér l'exclusion mutuelle des thread dans les sections critiques.

Autrement dit:
Les développeurs sont les threads concurrents, la référence du code est la ressource partagée, la séquence d'intégration est la section critique et le verrou d'intégration est le mutex. Le développement avec intégration continue est un système multitâche.
Une fois que ce parallèle est admis, alors les règles de la programmation concurrente s'appliquent également pour l'intégration continue. En effet, le temps passé en section critique doit être aussi court que possible car une section critique est un goulet d'étranglement. La pratique de l'exclusion mutuelle en intégration créé une file d'attente d'intégration qui peut pénaliser les travaux si la durée d'intégration est longue ou si l'équipe est nombreuse.

COMMENT FONT LES AUTRES ÉQUIPES?

Je m'étonne toujours de constater que d'autres équipes (même chez nous) ne semblent pas être confrontées à ce problème. Cela n'est pas une question de taille de l'équipe car nous avons instauré cette pratique pour la première fois lors d'un projet développé à 4 développeurs organisés en 2 binômes. Ce problème me semble indissociable du développement concurrent avec intégration continue.
Alors, comment faites-vous?

mercredi 22 avril 2009

CLEAN CODE, ROBERT C. MARTIN

J'avais énormément appris en lisant le précédant livre d'Uncle Bob, Agile Software Development: Principles, Practices and Patterns. Son catalogue des principes avancés de conception objet et ses métriques de couplage ont été une aide pour développer mieux.

Autant dire que j'attendais le livre suivant Clean Code, traduit en français sous le titre Coder Proprement.

Malheureusement, j'ai été déçu. Le livre est bien, mais j'ai appris bien moins qu'avec le précédant. Aussi, les chapitres rédigés par différents auteurs sont assez irréguliers en qualité. Voici la synthèse de ce qui m'a plu et de ce que j'ai appris.

QUELS SONT LES CRITÈRES DE QUALITÉ D'UN BON CODE?

Voici la définition qu'en donne l'eXtreme Programming:

Par ordre de priorité, le bon code respecte les critères suivants:
  1. Il passe ses tests;
  2. Il ne contient pas de redondance;
  3. Il est explicite;
  4. Il est minimal.
Malheureusement, l'auteur insiste peu sur le fait que les critères 3 et 4 peuvent être contradictoires et que l'ordre des priorités entre ces deux critères est très important. En effet, un code explicite tend à être plus modulaire et à être découpé en petites classes ayant chacune une seule responsabilité et en courtes opérations ayant un seul niveau d'abstraction. Ceci amène à plus de déclarations et donc à plus de code, ce qui s'oppose au critère 4.
D'ailleurs, dans tous les exemples de remaniement du livre, on constate que le code remanié est toujours 2 fois plus volumineux que le code d'origine! Cela ne me choque pas, mais je pense qu'il est important de le souligner clairement.

LIRE ET ÉCRIRE

Nous passons plus de temps à lire du code qu'à en écrire. En rendant le code facile à lire, nous le rendons plus facile à écrire.

LA RÈGLE DU BOY SCOUT

Lorsque nous ouvrons un fichier de code source, nous devons le laisser plus propre que nous l'avons trouvé.

LA LIGNE VIDE

Une opération ne doit pas contenir de ligne vide. Une ligne vide dans une opération sert à aérer son code en regroupant les instructions contribuant à une même action. Une ligne vide est donc un indice indiquant que l'opération passe à autre chose et qu'il y a plusieurs niveaux d'abstraction au sein de la même opération.
Alors, il plus cohérent d'exporter chaque groupe d'instructions contribuant à une même action dans une nouvelle opération nommée selon cette action et à appeler cette nouvelle opération dans l'opération d'origine. Ainsi, il ne reste dans l'opération d'origine que des instructions d'un même niveau d'abstraction.

LIRE LE CODE D'UNE OPÉRATION

Les étapes d'une opération doivent se trouver à un même niveau d'abstraction en dessous du nom de l'opération. Le code d'une opération bien écrite doit pouvoir se lire de la manière suivante:
POUR nom_de_l_opération IL FAUT première_étape_de_l_opération PUIS deuxième_étape_de_l_opération PUIS troisième_étape_de_l_opération PUIS ...
Les différentes étapes de l'opération sont des instructions du langage de programmation ou des appels d'opérations d'un même niveau d'abstraction.

CLASSES ET STRUCTURES DE DONNÉES

Depuis quelques projets, nous remarquons qu'il semble par endroit plus adapté d'écrire un code procédural plutôt qu'un code orienté objet. Est-ce une hérésie? Le constat suivant d'Uncle Bob m'a beaucoup rassuré.

Un code procédural (un code qui utilise des structures de données) facilite l'ajout de nouvelles fonctions sans modifier les structures de données existantes. Un code orienté-objet facilite l'ajout de nouvelles classes sans modifier les fonctions existantes.

Un code procédural complexifie l'ajout de nouvelles structures de données car toutes les fonctions doivent être modifiées.
Un code orienté objet complexifie l'ajout de nouvelles fonctions car toutes les classes de l'arbre d'héritage doivent être modifiées.

Par conséquent, ce qui est difficile pour l'orienté objet est facile pour le procédural, tandis que ce qui est difficile pour le procédural est facile pour l'orienté objet!

Dans un système, nous avons parfois le besoin d'une souplesse d'ajout de nouveaux types de données et choisissons alors une implémentation fondée sur les objets. Si nous voulons disposer d'une souplesse d'ajout de nouveaux comportements, alors nous optons pour les structures de données et les procédures.

Les programmeurs expérimentés savent très bien que l'idée du tout objet est un mythe. Les bons développeurs de logiciels abordent ces questions sans préjugé et retiennent l'approche adaptée à leurs besoins.

DES TESTS PROPRES

Le code de test est aussi important que le code de production. Il doit rester aussi propre que le code de production.
J'avais consacré un billet intitulé Les Tests Sont du Code à ce sujet et c'est d'ailleurs le thème du livre que je suis actuellement en train de lire : xUnit Test Patterns: Refactoring Test Code. Je reviendrai plus longuement sur ce livre car il améliore grandement ma pratique du test automatisé.

L'EVOLUTION DES SYSTEMES LOGICIELS

Les systèmes logiciels sont uniques si on les compare aux systèmes physiques. Leur architecture peut évoluer de manière incrémentale si nous maintenons la séparation adéquate des préoccupations (et le test de leurs constituants!).

SUR LA CONCURRENCE

Incroyable, deux chapitres du livre sont dédiés au développement de logiciels avec traitements concurrents! Malheureusement, il n'y a rien de bien nouveau. Néanmoins, c'est rassurant de lire des recommandations que nous appliquons déjà (voir mon précédant billet Extreme Programming Embarqué). Voici ces constats et recommandations:

La conception d'un système concurrent peut être très différente de celle d'un système monothread. Le découplage du quoi et du quand a généralement un impact très important sur la structure du système.

Gardez le code lié à la concurrence séparé de tout autre code. Ne tentez pas de pourchasser à la fois les bogues du code normal et ceux du code multithread. Assurez-vous que votre code fonctionne en dehors des threads.

CONCLUSION

Malgré quelques déceptions, je ne regrette pas la lecture de ce lire. Néanmoins, je conseillerais plutôt le livre précédant, bien plus enrichissant à mon avis.

lundi 6 avril 2009

LOGO EXPERIENCED EXTREME PROGRAMMER

Je ne suis pas à l'aise et cohérent avec ce logo Certified ScrumMaster. D'un côté, je trouve qu'il en jette et qu'il épate ceux qui n'ont pas suivi la formation certifiante Scrum. D'un autre côté, je sais bien qu'il n'a aucune valeur.

Pour je ne sais quelle raison idiote, je n'arrive pas à me convaincre de l'enlever de mon blog. Alors, j'ai décidé de le tempérer par un logo fait maison: celui du praticien expérimenté de l'eXtreme Programming. Ce logo est gratuit et auto-proclamé. Il n'a aucune valeur non plus. Pourtant, je l'aime bien parce que sur ce logo:
  • "eXPerienced" se subsititue à "Certified";
  • Le binôme se substitue au cycle quotidien et au cycle itératif;
  • Un graphisme rustique, monochrome et à la main levée (la solution suffisante la plus simple) se substitue à la belle infographie en couleurs.
Si cela vous amuse, vous pouvez utiliser ce logo: il est gratuit, auto-proclamé, non signé et ne profite à personne ;o) ;o)

samedi 4 avril 2009

PARTIE VISIBLE ET PARTIE INVISIBLE

Dans notre organisation, nous constatons que la partie visible de nos pratiques de développement séduit les décideurs. Cette partie visible correspond aux pratiques de pilotage de projet de développement. Dans notre cas, il s'agit de la pratique de Scrum complétée par le Lean avec le Value-Stream-Mapping et les Kanbans.

LA PARTIE VISIBLE

Ces pratiques séduisent les décideurs pour plusieurs raisons.
D'abord l'équipe développe le bon produit grâce au rôle joué par le Product Owner, grâce à la construction itérative et incrémentale et en évaluant les incréments de produit lors des démonstrations d'itération.
Ensuite, l'avancement est transparent grâce à l'identification, à la priorisation et à l'estimation du restant à faire dans le Product Backlog et l'Iteration Backlog, grâce à la visualisation du restant à faire par les Burndown-Charts, grâce à la mesure de la vélocité et enfin grâce aux incréments de fonctionnalité présentés en démonstration d'itération.
La complexité est maitrisée par la construction itérative et incrémentale du produit.
L'équipe se responsabilise pour tenir l'objectif en planifiant les itérations, en pilotant quotidiennement les activités lors des Daily-Stand-Up-Meeting et en présentant leur travail lors des démonstrations d'itération.
L'équipe améliore ses pratiques en menant les rétrospectives d'itération, en portant un regard critique sur la cartographie du flux de valeur et en traitant les goulots d'étranglement révélés par les Kanbans.

Toutes ces pratiques sont pleines de bon sens. Elles ont aussi le grand avantage d'être visibles et touchent des décideurs n'ayant pas un profil technique.

LE CHAOS

Le développement logiciel est une activité assez chaotique. Or ces pratiques permettent de s'accommoder du chaos car elles se mènent en cycles très courts, permettent de collecter de l'information et apportent de la transparence.
Par contre, ces pratiques génèrent également du chaos. Il s'agit du chaos lié à l'instabilité du produit construit par incrément en cycles très courts. La construction itérative et incrémentale amène à faire évoluer la conception et à reprendre le code déjà écrit. Si cette instabilité n'est pas maitrisée, elle conduit à des régressions. Et tout s'écroule ...

LA PARTIE INVISIBLE

Le chaos lié à l'instabilité du produit est maitrisé par la partie cachée des pratiques de développement. Ces pratiques ont le désavantage de ne pas être visibles. Il s'agit par exemple de l'intégration continue, du développement piloté par les tests, de la programmation par contrat, de la programmation orientée-objet, du strict respect des grands principes de conception orientée-objet et de l'exception visible: le Pair Programming. Ces pratiques combinées et la recherche de l'excellence technique permettent de maitriser l'instabilité d'un produit en train de "pousser" par incréments. Malheureusement, le fait que ces pratiques ne soient pas visibles les rend plus difficiles à valoriser auprès de décideurs et des équipes de développement.

OU EST LE PROBLÈME?

Le risque est que décideurs et équipes de développement n'adoptent que la partie visible des pratiques de développement. Ces projets souffriront beaucoup du chaos et de l'instabilité du produit. L'adoption des nouvelles pratiques sera tenue responsable des échecs. Malheureusement, un échec cuisant peut avoir plus d'effet que plusieurs succès quand à la promotion d'une nouvelle démarche au sein d'une organisation.

DES SOLUTIONS?

Communiquer auprès des décideurs et des équipes en démontrant les pratiques visibles est très efficace pour séduire et convaincre. Cependant, il faut également insister lourdement sur l'absolue nécessité du socle technique.
Aussi, nous avons remarqué que nos équipes qui ont pris le virage avec succès ont commencé par adopter les pratiques techniques. Peut-être qu'il est plus sûr de débuter par la partie invisible et d'attendre que les bienfaits se fassent sentir?