Création de logiciels : de l'agilité à l'artisanat

Faut-il encore parler de méthodes agiles en 2012 ?

Les années passent et je me dis de plus en plus souvent : mais pourquoi encore parler de méthodes agiles ?
Pourquoi garder ce terme restrictif alors que l'on devrait, à mon avis, tout simplement parler de méthodes professionnelles de développement logiciel ?

Car c'est bien de cela dont il s'agit : des valeurs, des principes et des pratiques qui guident toute activité de développement logiciel et qui caractérisent, sans fausse modestie ni dédain, le professionnalisme nécessaire à la satisfaction des utilisateurs et à la pérennité de l'ouvrage.

En ce début d'année 2012, je ne vais donc prendre qu'une seule résolution pour toutes mes activités qui tournent autour du développement logiciel : parler le moins possible de méthodes agiles et le plus possible de méthodes professionnelles.

Et pour sortir du carcan des "méthodes agiles", quoi de mieux que de commencer l'année avec une rencontre axée sur l'écriture de code, activité majeure de tout développement logiciel ?
Le 5 janvier, c'est la première du software craftsmanship Toulouse (il y aurait aussi beaucoup à dire sur le terme craftsmanship mais chaque chose en son temps...)

Dans mon agenda "agile", j'enchainerai les 2 et 3 février avec une réunion de sensibilisation aux méthodes agiles pour les enseignants des IUT Informatique où j'aurai le plaisir d'intervenir.
Malgré un programme pédagogique national des DUT informatique assez ancien, il y a des choses qu'un diplomé de 2012 qui se lance dans le développement logiciel devrait savoir et toute action de promotion/sensibilisation ne peut aller que dans le bon sens.
J'y animerai probablement un des ateliers ludiques sur l'importance des principes de conception pour garder un logiciel maintenable ou sur la place des artefacts de test dans le TDD. Cela m'évitera de parler de méthodes agiles (ce que d'autres feront bien mieux que moi).

Ce début d'année bien rempli se poursuivra les 16 et 17 mars à Banyuls sur mer pour le premier Agile Open Sud. La rencontre entre une trentaine de passionnés[1] promet d'être enrichissante.
J'y aborderai peut-être le sujet de la place des méthodes agiles. Sommes-nous contraints à vivre éternellement dans cet enclos pour bêtes curieuses du développement logiciel ? Est-ce aller trop loin que de suggérer le caractère non-professionnel de ceux qui resteraient scotchés sur des approches d'un autre siècle ?

Mais mon principal chantier de l'année sera certainement de prendre du recul sur le chemin parcouru avec la même équipe de développement depuis six ans. Aujourd'hui, je n'utilise pas quotidiennement une méthode agile. Je ne fais que développer une famille de produits logiciels en adaptant jour après jour la manière de travailler. Après avoir fait, il y trois ans, un premier bilan sur la mise en place de Scrum, il me faudrait faire une synthèse sur tout ce qui a changé depuis : des itérations au flux, des estimations à la décomposition, des tests manuels aux tests automatisés et à l'exploration, l'architecture centrée sur le métier, l'apprentissage en continu...

Je ne parlerai peut être plus de méthodes agiles mais je vais encore parler de développement logiciel pendant un certain temps.

Notes

[1] il reste encore des places mais ça devrait partir, je pense, assez vite

Boucles à base de générateurs et de transformations : un exemple plus complet

Dans un billet précédent, j'avais évoqué une approche pour l'écriture de boucles permettant d'expliciter la combinaison de diverses exigences.
Le reproche fait dans les commentaires de ce billet est que cette approche serait moins lisible et rendrait inutilement le code plus compliqué.

Pour ma part, je campe sur mes positions. L'approche n'est moins lisible que pour des exemples triviaux que l'on ne rencontre jamais dans un programme réel.
La complexité inhérente à ces programmes fait que, au final, un programme est plus facilement maintenu s'il se base sur une combinaison de générateurs et de transformations indépendantes que s'il se base sur des boucles où tous les ingrédients sont mélangés.

Ce débat me semble par ailleurs être une illustration de la différence entre "simple" et "facile" mise en lumière par Rich Hickey. Les boucles while/for sont certainement plus faciles à écrire au début mais elle ne donnent pas ce qu'il y a de plus simple à maintenir et faire évoluer.

Essayons donc de voir ce que cela donne avec un programme à peine plus riche que des exemples d'une ou deux lignes.



Soit un programme qui :

  • demande à l'utilisateur de choisir une fonction parmi les suivantes :
    • mettre un entier au carré
    • calculer la somme des entiers inférieurs ou égaux à un entier donné
    • calculer le k-ième terme de la suite de Syracuse à partir d'un entier donné, k étant un entier saisi par l'utilisateur
  • demande à l'utilisateur de choisir un filtre parmi les suivants :
    • prendre les k premiers éléments, k étant un entier saisi par l'utilisateur
    • prendre les éléments inférieurs ou égaux à k, k étant un entier saisi par l'utilisateur
    • prendre les éléments impairs inférieurs ou égaux à k, k étant un entier saisi par l'utilisateur
  • Lorsque l'utilisateur a fait ces choix, affiche les images par la fonction choisie précédemment des entiers naturels strictement positifs restreints au filtre lui aussi choisi précédemment

Exemples d'utilisation :

  • L'utilisateur choisit "mise au carré", puis "4 premiers éléments". Le programme affiche : 1, 4, 9, 16
  • L'utilisateur choisit "somme des entiers inférieurs ou égaux", puis "impairs inférieurs à 17". Le programme affiche : 1, 3, 15
  • L'utilisateur choisit "3ème terme de la suite de Syracuse", puis "éléments inférieurs à 6". Le programme affiche : 2, 4, 5, 1

Voici une implémentation à base de générateurs et de transformations. Le code complet est disponible sur github.

J'ai essayé de décrire la démarche étape par étape mais je ne parle pas de ce qui a, dans le cas présent, un intérêt moindre, comme par exemple le découplage au niveau de l'"interface utilisateur" pour faciliter l'écriture des tests.

Allons-y.

Stab : un langage pour découvrir C# quand on ne connait que java

Ce billet est issu de la concomitance de deux évènements :

  • je me pose la question "comment peut-on écrire quelque chose proche de C# mais qui tourne avec une JVM ?" et je découvre le langage "stab"
  • je lis ce billet "Sélection FooBarQix" où un même programme a été implémenté dans 13 langages différents ayant pour seul point commun la JVM.

Il ne m'en a pas fallu plus pour écrire un FooBarQix en stab.
Et je crois que ce programme a un intérêt pour montrer ce que l'on peut écrire quand on rajoute quelques éléments basiques de C# 3 à java 6.
Le code complet est dispo sur github.

J'ai fait au plus simple avec seulement deux fichiers.

Un fichier de tests qui utilise junit :

using java.lang;
using junit.framework;
 
public class TestFooBarQix : TestCase
{
  delegate void Action<T1,T2>(T1 t1, T2 t2);

  public void testFBQ()
  {
    Action<Integer,String> check = (src,dst) => { assertEquals(src+" => "+dst, dst, FooBarQix.from(src)); };
    check(1,"1");
    check(2,"2");
    check(3,"FooFoo");
    check(4,"4");
    check(5,"BarBar");
    check(6,"Foo");
    check(8,"8");
    check(9,"Foo");
    check(10,"Bar");
    check(11,"11");
    check(12,"Foo");
    check(13,"Foo");
    check(15,"FooBarBar");
    check(7,"QixQix");
    check(14,"Qix");
    check(16,"16");
    check(17,"Qix");
    check(18,"Foo");
    check(19,"19");
    check(20,"Bar");
    check(21,"FooQix");
  }
}

Et un fichier de code qui tire profit de quatre éléments majeurs de C# :

  • les lambda expressions
  • les générateurs
  • les types anonymes
  • LINQ (qui n'est presque rien de plus que la résultante des éléments précédents)
using java.lang;
using stab.query;
 
public static class FooBarQix
{
  public static String from(Integer numberToConvert)
  {
    var fbqDigits = sequence(
      new { Value=3, Text="Foo" },
      new { Value=5, Text="Bar" },
      new { Value=7, Text="Qix" }
    );

    Predicate<Integer> isNumberToConvertDivisibleBy = n => (numberToConvert % n == 0);
    var divisors = fbqDigits.where(x => isNumberToConvertDivisibleBy(x.Value));

    var digitsReplacement=digitsLeftToRight(numberToConvert).selectMany(digit => fbqDigits.where(x => x.Value==digit));

    var fbqConversions = divisors.concat(digitsReplacement);
 
    if( fbqConversions.count() == 0 )
      return Integer.toString(numberToConvert);
    else
      return fbqConversions.select(x => x.Text).aggregate((a,b)=>a+b);
  }

  static Iterable<Integer> digitsLeftToRight(Integer number)
  {
    return digitsRightToLeft(number).reverse();
  }

  static Iterable<Integer> digitsRightToLeft(Integer number)
  {
    while(number != 0)
    {
      yield return number % 10;
      number = number / 10;
    }
  }

  delegate Boolean Predicate<T>(T t);

  static Iterable<T> sequence<T>(params T[] items)
  {
    return Query.asIterable(items);
  }
}

Fluctuations d'une équipe agile

L'équipe entame une période un peu particulière. Pour quelques mois, elle va devoir prendre en charge une activité de support produit qui sort de son cadre habituel de développement logiciel. Cette activité est potentiellement chronophage (elle occupera facilement une personne à plein temps sur les quatre développeurs que compte l'équipe) et les attentes des clients sur les sorties à venir ne diminuent pas pour autant. Il y a un budget permettant de financer une personne supplémentaire pendant 9 mois.
Que faire ?

L'option "la personne supplémentaire assurera le support produit et on ne change rien d'autre" n'est pas envisageable : cette activité nécessite des connaissances spécifiques et une autonomie qui ne s'acquièrent pas en moins de 6 mois.
Par ailleurs, les membres de l'équipe ont à coeur de minimiser l'impact sur leur situation actuelle : "Notre métier c'est le développement logiciel. On n'assurera le support que parce qu'il faut bien que quelqu'un s'en charge". Et ils sont les seuls à pouvoir le faire.

L'équipe s'est réunie et a décidé de modifier son organisation pour faire face aux nouvelles contraintes :

  • A tour de rôle, un membre est désigné pour assurer la prise des appels téléphoniques. Chaque appel sera limité en durée afin que la perturbation induite ne soit pas supérieure aux interruptions habituelles internes à l'équipe.
  • Si une demande de support vient à prendre plus de temps, elle devient une tache de l'équipe et rejoint le tableau Kanban avec une classe de service dédiée. Un WIP dédié à cette classe permettra de maitriser le temps consacré au support.
  • Avec le budget fourni, un développeur supplémentaire rejoint l'équipe pendant 9 mois. L'usage généralisé du pair programming devrait permettre d'intégrer rapidement la personne. La présence de ce nouveau développeur garantira par ailleurs la continuité du travail en paires.

Reste une question: comment trouver le développeur supplémentaire ?
En faisant probablement appel à une SSII, mais comment déterminer la mission et les compétences recherchées ?

  • Les développements sont faits en C# mais la maitrise du langage n'est pas primordiale. Un développeur java ou C++ qui applique les principes essentiels et utilise les bonnes pratiques s'intègrerait plus facilement qu'un développeur qui sait avant tout cliquer dans MS Visual Studio.
  • La connaissance de l'environnement .NET ou de tel ou tel framework n'est pas non plus essentielle. L'architecture du produit est centrée sur le besoin à résoudre et est quasiment framework-agnostique.
  • L'équipe essaie dans la mesure du possible de coller aux valeurs et aux principes agiles mais un fraichement certifié CSM serait un peu déboussolé dans un contexte agile sans sprints, sans burdown chart, sans estimations et presque sans Scrum.

Bref, ce qu'il nous faudrait c'est un compagnon de route qui vienne pendant quelques mois vivre notre cheminement, nous aider à ne pas décevoir les attentes de nos clients, partager son réel savoir-faire et peut être apprendre quelques trucs au passage.
C'est mon idée d'un vrai développeur professionnel qui va de mission en mission. Je me demande s'il y a des SSII qui peuvent répondre à ce genre de demandes mais je ne vais probablement pas tarder à le découvrir...

Si quelqu'un qui passe par ici est intéressé, je suis facile à joindre.

Agile Tour Toulouse 2011 : jour J-2

Avec plus de 300 personnes déjà inscrites (les records des années précédentes vont être explosés), l'Agile Tour Toulouse 2011 sera probablement un grand succès.

J'aurai le plaisir d'y animer deux sessions. Je n'ose pas leur donner le nom de "présentations" car je n'y présenterai rien du tout.

La journée débutera par une keynote d'Alexandre Boutin qui donnera une place de choix à l'apprentissage par le jeu. Je crois que, plus ou moins consciemment, la présence de ce thème m'a amené à construire mes sessions comme des jeux.

Loin de moi la prétention d'en imaginer qui pourraient être utilisés de manière courante dans l'enseignement des méthodes agiles mais j'espère quand même que ce format donnera l'occasion à tous les participants d'apprendre quelques trucs et de s'en souvenir grace au format ludique.
Le matin, dans "si t'es pas SOLID, t'es pas agile", les participants se retrouveront sur scène à se faire des passes avec un ballon (ovale, actualité oblige !) pour dérouler l'exécution d'un programme. Le ballon représentera en quelque sorte l'instruction courante et toute la difficulté du jeu résidera dans le choix de la meilleure tactique pour répondre le plus efficacement possible aux attentes toujours changeantes d'un client.
En fin de journée, dans "quand je serai grand, je serai artisan logiciel", on jouera aux cartes. A partir du livre "Apprenticeship Patterns", j'ai fabriqué un jeu de 35 cartes, une par pattern. Aidés par ces cartes, les participants tenteront de répondre à la question que beaucoup de monde se pose et dont la réponse n'est pas toujours simple : comment devient-t-on un bon développeur de logiciels ?

D'autres jeux (des vrais, maintes fois éprouvés) seront aussi présents dans cette journée : le "marshmallow challenge" et le "sky castle game". Je n'y participerai pas mais je ne peux que les conseiller à tous ceux qui voudraient passer une journée animée loin des confortables fauteuils d'un amphithéatre.

Je ne sais pas encore exactement comment j'occuperai le reste de ma journée. L'association SigmaT, organisatrice de l'évènement y aura un stand où j'assurerai probablement un peu de permanence. Il y a quelques présentations que j'aimerais voir comme l'"histoire d'un transformation agile"Laurent Carbonnaux parlera de l'utilisation des méthodes agiles à une échelle rarement rencontrée en France. J'aimerais également parler de Domain Driven Design avec les toujours sympathiques et compétents bordelais d'Arpinum parce que c'est une approche que l'on commence à aborder dans mon équipe.

Quoi qu'il en soit, avec 4 sessions en parallèle sur les 5 créneaux de la journée, il y en aura pour tous les goûts et si vous lisez ce billet avant la date du 19 octobre 2011, il est encore temps de s'inscrire !

Faire des boucles sans "while" ni "for" pour les rendre plus lisibles et maintenables

Le B.A.BA de la programmation, celui que tout le monde, ou presque, commence par apprendre en débutant l'écriture d'algorithmes, ce sont les structures de contrôle en programmation impérative : les tests, les boucles, les sauts...
Mais, avec le temps, cela devient, de moins en moins vrai. Les instructions de sauts ont commencé à disparaitre des langages informatiques quand deux illustres néerlandais et suisse ont évoqué leur nocivité.
En ce qui concerne les structure de tests, il a fallu attendre l'avènement des langages orientés objet pour que le polymorphisme devienne "mainstream". Aujourd'hui, on peut ouvertement se revendiquer anti-if.

La seule structure qui résiste encore bien, ce sont les boucles. Mais la redécouverte de la programmation fonctionnelle à travers sa présence à dose plus ou moins grande dans des langages "en vogue" (python, ruby, javascript, C#, scala...) fait que le développeur lambda[1] peut commencer à entrevoir d'autres manières de décrire des opérations sur des ensembles d'éléments.

Je vais dans ce billet essayer de montrer ce que l'on peut faire en C# sur ce sujet.
Prenons un exemple simple : "afficher les carrés des entiers naturels inférieurs ou égaux à 10"

L'implémentation la plus courante ressemblera à une boucle sur des entiers au sein de laquelle seront mis en oeuvre le calcul et l'affichage adéquats :

for(var i=0; i<=10; i++)
  Console.WriteLine( i*i );

Ca fonctionne, mais ce n'est pas très explicite. L'énoncé du problème comporte 4 exigences distinctes et le code proposé ne permet pas de les expliciter et les implémenter indépendamment les unes des autres :

  1. afficher
  2. les carrés
  3. des entiers naturels
  4. inférieurs ou égaux à 10

Commençons par les points (3) et (4). Pour expliciter les éléments sur lesquels portent l'opération, on pourrait écrire quelque chose dans ce genre :

foreach(var n in Sequence.OfN().TakeWhile( n => n<=10 ))
  Console.WriteLine( n*n );

Sequence.OfN() n'est pas du code standard C#. On va supposer que cela retourne un IEnumerable<int> qui est l'ensemble des entiers naturels. On s'interessera plus tard à son implémentation.
Le TakeWhile( n => n<=10 ) est quelque chose qui devrait être désormais naturel à tous les développeurs C# qui connaissent LINQ et les lambda expressions.

On va maintenant expliciter le point (2) en remontant son calcul dans la définition de l'ensemble de nos éléments :

foreach(var n2 in Sequence.OfN().TakeWhile( n => n<=10 ).Select( n => n*n ))
  Console.WriteLine( n2 );

Pour en finir avec la boucle, il ne reste plus qu'à imaginer un moyen simple pour effectuer un affichage sur un ensemble d'éléments donné :

Sequence.OfN().TakeWhile( n => n<=10 ).Select( n => n*n ).Apply( n2 => { Console.WriteLine(n2); } );

Et voilà... Notre boucle s'est métamorphosée en la concaténation d'opérations indépendantes sur des suites d'éléments :

  1. afficher => Apply( n2 => { Console.WriteLine(n2); } )
  2. les carrés => Select( n => n*n )
  3. des entiers naturels => Sequence.OfN()
  4. inférieurs ou égaux à 10 => TakeWhile( n => n<=10 )

L'avantage d'une telle écriture, c'est que l'on n'est plus condamné à des algorithmes monolithiques où la modification d'une exigence a des impacts sur les autres. On a remplacé cela par des briques de lego que l'on peut facilement recombiner.

Passons maintenant à l'implémentation. Définissons d'abord quelques briques de base sur lesquelles viendront s'appuyer les autres :

  • la définition d'une suite initiale d'éléments IEnumerable<T>. Pour cela, on utilisera 2 méthodes :
    • IEnumerable<T> Of<T>(params T ts) pour une suite définie par la liste explicite de ses éléments
    • IEnumerable<T> Of<T>(Func<T> next) pour une suite définie par une fonction génératrice (chaque appel renvoie l'élément suivant de l'énumération)
  • les opérations de transformation d'un IEnumerable<T> vers un IEnumerable<U> : nul besoin d'écrire quoi que ce soit pour cela, il y a déjà de quoi faire avec le LINQ de base
  • une opération de terminaison void Now<T>(this IEnumerable<T> seq). Toutes les autres opérations étant à évaluation différée, il nous faut une opération qui force l'exécution.

Tout cela fait beaucoup de blabla pour finalement peu de code :

public static class Sequence
{
  public static IEnumerable<T> Of<T>(params T[] ts)
  {
    return ts;
  }

  public static IEnumerable<T> Of<T>(Func<T> next)
  {
    sendNext:
    yield return next();
    goto sendNext; // on aurait pu faire un while(true) mais le goto est plus fun, non ?
    // En tout cas, les codes CLR générés sont identiques.
  }

  public static void Now<T>(this IEnumerable<T> seq)
  {
    seq.Count(); // Demander le compte des éléments est un moyen simple pour forcer l'énumération
  }
}

A partir de là, implémenter notre Sequence.OfN() est une simple formalité. Il suffit d'initier un ensemble d'élément avec une fonction qui renvoie consécutivement les entiers naturels :

public static IEnumerable<int> OfN()
{
  var n=0;
  return Sequence.Of( () => n++ );
}

L'application d'une action sur chaque élément n'est guère plus compliquée :

public static IEnumerable<T> Apply<T>(this IEnumerable<T> seq, Action<T> action)
{
  return seq.Select( item => {action(item);return item;} );
}

Pour être tout à fait précis, le Apply étant défini à évaluation différée, notre exemple initial devrait se terminer par un Now pour forcer l'exécution :

Sequence.OfN().TakeWhile( n => n<=10 ).Select( n => n*n ).Apply( n2 => { Console.WriteLine(n2); } ).Now();

Passons maintenant à quelque chose d'un peu plus évolué. Les carrés des 10 premiers entiers, c'est sympa, mais la réalité est souvent plus complexe.
Prenons, par exemple, l'affichage des 20 premiers termes d'une suite d'entiers définie par récurrence :

var u = 1;
for(var i=0; i<20; i++)
{
  Console.WriteLine( u );
  u = 2*u+1;
}

Notre nouvelle écriture ressemblera à ça :

Sequence.Recurrence(1, x => 2*x+1).Take(20).Apply( n => { Console.WriteLine(n); } ).Now();

La méthode Recurrence est assez facilement définie à partir des autres méthodes d'initialisation :

public static IEnumerable<T> Recurrence<T>(T u0, Func<T,T> f)
{
  var u = u0;
  return Sequence.Of(u0).Concat( Sequence.Of( () => u=f(u) ) );
}

Notre collection ne pourrait pas être complète sans la star des algorithmes de boucles favoris des débutants : la suite de Fibonnacci.
En version "classique" :

var u = 1;
var v = 0;
for(var i=0; i<20; i++)
{
  Console.WriteLine( u );
  var w = u;
  u = u+v;
  v = w;
}

Et en version "moderne" :

Sequence.Fibonnaci().Take(20).Apply( n => { Console.WriteLine(n); } ).Now();

public static IEnumerable<int> Fibonnaci()
{
  return Sequence.Recurrence(new {fib=1,fib2=0}, x => new {fib=x.fib+x.fib2, fib2=x.fib}).Select(x => x.fib);
}

On remarquera au passage l'utilisation de types anonymes statiques.

Et pour finir, un petit exemple avec condition d'arrêt portant sur les élements manipulés avec un autre classique, la division euclidienne :

var a = 34;
var b = 5;

var q = 0;
var r = a;
while(r >= b)
{
  Console.WriteLine( "( q = {0}, r = {1} )", q ,r );
  q++;
  r -= b;
}

var quotientAndRemainder = Sequence
  .Recurrence(new{q=0,r=a}, x => new{ q = x.q+1, r = x.r-b })
  .Apply( x => { Console.WriteLine(x); } )
  .SkipWhile(x => x.r>=b)
  .First();

C'est fini...
J'espère que ce petit aperçu sur la manière d'écrire des boucles "autrement" donnera des envies d'exploration à ceux qui n'avaient jamais envisagé ces techniques d'écriture de code.
Comme d'habitude, les commentaires sont les bienvenus !

Notes

[1] Ce billet n'est pas destiné au développeur qui a SICP comme livre de chevet mais à un hypothétique développeur moyen tout comme on peut parler du "français moyen"

Agile Tour Toulouse 2011 : une journée pour les développeurs ?

L'été vient à peine de commencer mais c'est bientôt l'automne. Dans moins de 2 mois, l'Agile Tour posera ses bagages à Diagora Labège pour son édition toulousaine annuelle.
Les inscriptions sont d'ailleurs déjà ouvertes.

Pour ceux qui souhaiteraient apporter leur contribution au programme, c'est encore possible jusqu'au 15 septembre.
Pour ma part, je viens de déposer 2 propositions de sessions : "Si t'es pas SOLID, t'es pas agile" et "Quand je serai grand, je serai artisan logiciel".

La première est un atelier qui vise à découvrir ou approfondir l'importance des principes de conception dans toute organisation qui produit du logiciel de manière incrémentale et adaptative.
Pour cela, j'ai envie de surfer sur une approche que j'avais bien aimée lors du "Stub et Mock montent sur scène" de l'an dernier : des personnes qui montent sur scène pour jouer le rôle de composants logiciels.
L'idée ici, c'est que l'animateur joue le rôle du client et laisse l'équipe présente sur scène implémenter le logiciel "humain". Par demandes successives du client, il devrait être possible de redécouvrir rapidement l'intérêt de plusieurs principes SOLID et enchainer sur une discussion concernant leur apport à une démarche "agile".

La deuxième proposition serait plutôt dans le genre "débat". Les conférences sur les méthodes agiles proposent souvent des retours d'expérience orienté "projet" et, à mon goût, trop peu de retours d'expérience orientés "carrière dans le développement logiciel". L'idée serait donc d'amener les membres de l'assistance qui le souhaitent à évoquer des points essentiels de leur parcours.
Pour cela, les "Apprenticeship Patterns" formalisés par D.Hoover et A.Oshineye me semblent être un support intéressant. Malgré l'existence d'une version en ligne, ce sont des travaux, à mon avis, trop peu connus dans la communauté agile francophone.

Voilà... Ce deux propositions sont encore un peu des "work in progress" comme on dit et toutes les suggestions, voire les collaborations, sont les bienvenues.

Mon sentiment général, après avoir vécu plusieurs journées "agile tour" les années passées, est que ce genre de conférences s'adresse encore trop à des profils "chef de projets" -présents ou en devenir- et autres wannabe guru de l'organisation. De manière générale, je n'y vois pas un contenu suffisamment intéressant pour des développeurs.
Pour autant, je ne crois pas qu'un format "on amène nos laptops et on code" soit plus adapté. Une telle journée me semble plus intéressante pour ses opportunités de communication et d'échange. Pour écrire du code hors du contexte de travail habituel, il existe d'autre formats.

Mon espoir pour cette année est que la journée agile tour toulouse soit aussi pour les développeurs.

Tranches d'agilité

L'agilité, ça ne se vend toujours pas en boite de 12 mais ça peut se raconter en tranches.

C'est l'exercice auquel je vais me prêter cette semaine sur Slice of IT :

Slices of IT est une expérience : raconter nos tranches vie au sein d'un projet pour prendre du recul et tenter de s'améliorer, à la manière de G. Weinberg. Pour que ce soit facile, l'écriture d'une tranche en timebox de 15 minutes. Raconter les événements marquant et l'impression générale de la journée suffit à obtenir l'effet attendu.

Avant de se mettre à écrire, il faut apprendre à lire

read_and_write.pngConnaissez-vous des gens qui écrivent sans jamais avoir appris à lire ? L'idée est assez saugrenue.

Et pourtant...

Il ne faut pas chercher plus loin que dans l'industrie du logiciel.
On ne compte plus les professionnels qui écrivent du code à longueur de journée mais n'ont souvent jamais appris, ou simplement pris le temps de lire.

A ceux qui m'opposeront que écrire du code n'a rien à voir avec écrire de la littérature, je suggèrerai d'aller lire le dernier billet d'Antoine[1].

A moins d'être un génie qui jongle avec les mots comme d'autres jonglent avec un ballon ou avec des notes de musique dès leur plus jeune age, il y a un passage obligé pour arriver à écrire des choses de manière intelligible : la lecture.


Ma fille ainée a eu 10 ans hier. Il y a trois jours, elle m'a montré avec fierté une rédaction qui vient de lui valoir les félicitations de sa maitresse. Une histoire sur le cirque. Ce qui m'a le plus impressionné, c'est son application à dépeindre les personnages tant du point de vue physique qu'à travers leurs traits de caractère. Je lui ai demandé comment lui était venue l'idée d'écrire de cette manière là. Le plus simplement du monde, elle m'a répondu "c'est comme ça qu'ils font dans les livres".

Je ne connais pas de parents ayant pour préoccupation majeure la capacité de leur enfant de 10 ans à inventer et rédiger une histoire. Moi le premier. Si jamais cela arrive, on le reçoit comme un cadeau. Par contre, la plupart des parents que je connais seraient vraiment inquiets si, au même age, leur progéniture était incapable de déchiffrer une phrase.

Il faut croire que, dans le monde du logiciel, tout marche à l'envers. On s'intéresse beaucoup à la capacité qu'a un développeur d'écrire un programme. On s'intéresse plus rarement à sa capacité à le lire.
Toutes les Beaucoup de[2] formations sont axées sur l'écriture de code après quelques rudiments d'orthographe et de syntaxe, voire quelques notions de grammaire pour les plus chanceux.
L'employeur d'un développeur n'en demande pas plus. Il semble se complaire dans une sorte de "On s'en fout qu'il sache lire. On s'en fout que ce soit bien écrit. Tout ce qui compte c'est que le résultat plaise au client".

C'est en tout cas ce que j'ai souvent ressenti et le je m'enfoutisme vient parfois des développeurs eux-mêmes. Pour moi qui ai découvert ce qu'était un logiciel en recopiant inlassablement des pages entières de listing à la "grande époque" d'Hebdogiciel, c'est tout simplement inconcevable.
On ne peut bien écrire du code que lorsque l'on a passé du temps à lire du code, bon ou mauvais, à s'en imprégner, à en découvrir les forces et les faiblesses.

Le code, c'est une production humaine. C'est l'oeuvre d'un humain qui se parle à lui même et aux autres avant même de parler à la machine. Lorsqu'il écrit du code, un développeur devrait se demander comment celui-ci va être lu avant de se demander comment il va être compris par la machine.

Je laisserai le mot de la fin à un tweet de Jason Gorman.
Ecrire du code qu'un ordinateur comprend, c'est de la science. Ecrire du code que les autres programmeurs comprennent, c'est de l'art.

Notes

[1] sans lequel ce billet-ci n'existerait pas

[2] cf commentaire de Tok'

Pour en finir avec les Stubs et les Mocks

stubmockgear.pngLes termes de "Stub" et "Mock" sont aujourd'hui utilisés de manière assez courante[1] quand il s'agit de parler de tests unitaires, mais, faute de véritable référence, tout le monde n'utilise pas ces mots avec la même signification.

Une affirmation assez courante, consiste à dire "les stubs c'est pour faire des vérifications d'état, les mocks c'est pour faire des vérifications de comportement". Cette affirmation ne me convient pas car elle simplifie à outrance la diversité des techniques d'écriture de test.

Je préfère, de loin, les définitions proposées par Gerard Meszaros dans ses xUnit Patterns :

  • Un stub, c'est une doublure qui remplace un objet réel en fournissant des entrées indirectes à l'objet à tester
  • Un mock, c'est une doublure qui remplace un objet réel en vérifiant les sorties indirectes de l'objet à tester

Et la liste ne serait pas complète si on ne rajoutait pas l'espion :

  • Un spy, c'est une doublure qui remplace un objet réel en enregistrant les sorties indirectes de l'objet à tester pour vérification ultérieure par le test

C'est cette nomenclature que j'ai utilisée l'an dernier pour mon atelier "Stub et Mock montent sur scène" car elle me parait apporter la précision nécessaire à la compréhension des mécanismes de test.
Quand on parle des doublures, ces objets qui remplacent les objets réels lors des tests, les caractéristiques à identifier (celles qui auront le plus d'impact sur la stratégie d'implémentaiton du test) sont la mise en oeuvre des entrées indirectes et des sorties indirectes.

Voyons un exemple avec l'implémentation en Ruby[2] d'une partie de "Stub et Mock montent sur scène". On a un thermomètre qui sait calculer la température maximale observée à partir de relevés effectués sur un capteur et afficher cette température maximale sur l'écran qui lui est rattaché :

class Thermometre

  def initialize(capteur,ecran)
    @ecran = ecran
    @capteur = capteur
    @temperature_maximale = -273.15
  end

  def affiche_temperature_maximale
    temperature_courante = @capteur.lis_temperature_courante
    if temperature_courante > @temperature_maximale
      @temperature_maximale = temperature_courante
    end
    @ecran.ecris(@temperature_maximale)
  end

end

Une stratégie possible de test est la vérification de l'état de notre thermomètre. Puisqu'il mémorise la température maximale observée après chaque mesure, il suffit de vérifier la valeur mémorisée. Pour cela, on prend un stub pour doubler le capteur, un dummy pour doubler l'écran et on rend accessible l'état de notre thermomètre :

def test_avec_un_stub
  capteur = flexmock("capteur")
  capteur.should_receive(:lis_temperature_courante).and_return(21, 18, 25)

  ecran = Object.new
  def ecran.ecris(texte)
  end

  thermometre = Thermometre.new(capteur, ecran)
  def thermometre.temperature_maximale
    @temperature_maximale
  end

  thermometre.affiche_temperature_maximale
  assert_equal( 21, thermometre.temperature_maximale )
  thermometre.affiche_temperature_maximale
  assert_equal( 21, thermometre.temperature_maximale )
  thermometre.affiche_temperature_maximale
  assert_equal( 25, thermometre.temperature_maximale )
end

Une autre stratégie possible est de vérifier le comportement de notre thermomètre. Pour cela, on va toujours utiliser un stub pour les entrées indirectes fournies par le capteur mais on va prendre un mock pour vérifier ce que le thermomètre envoie à l'écran :

def test_avec_un_stub_et_un_mock
  capteur = flexmock("capteur")
  capteur.should_receive(:lis_temperature_courante).and_return(21, 18, 25)

  ecran = flexmock("ecran")
  ecran.should_receive(:ecris).with(21).times(2).should_receive(:ecris).with(25).once.ordered

  thermometre = Thermometre.new(capteur, ecran)
  3.times { thermometre.affiche_temperature_maximale }
end

Enfin, une troisième stratégie pourrait consister à vérifier les conséquences du comportment de notre thermomètre. On garde notre stub pour les entrées indirectes du capteur et on prend un spy pour enregistrer les conséquences des envois de notre thermomètre à l'écran :

def test_avec_un_stub_et_un_spy
  capteur = flexmock("capteur")
  capteur.should_receive(:lis_temperature_courante).and_return(21, 18, 25)

  ecran = Object.new
  def ecran.ecris(texte)
    @texte = texte
  end
  def ecran.affiche
    @texte
  end

  thermometre = Thermometre.new(capteur, ecran)
  thermometre.affiche_temperature_maximale
  assert_equal( 21, ecran.affiche )
  thermometre.affiche_temperature_maximale
  assert_equal( 21, ecran.affiche )
  thermometre.affiche_temperature_maximale
  assert_equal( 25, ecran.affiche )
end

Quelle est, de manière générale, la meilleure stratégie ?
Il n'y a pas de réponse unique à cette question. Cela dépend fortement de ce que l'élément que l'on est en train de tester.

Pour ce qui est de cet exemple précis, on peut toutefois avancer quelques arguments.

La simple vérification de l'état du thermomètre n'est peut être pas le meilleur choix. Imaginons que, lors d'une modification de code, un développeur supprime la ligne @ecran.ecris(@temperature_maximale) de notre thermomètre. On aurait donc ce code là :

def affiche_temperature_maximale
  temperature_courante = @capteur.lis_temperature_courante
  if temperature_courante > @temperature_maximale
    @temperature_maximale = temperature_courante
  end
end

Et le test de vérification d'état serait toujours vert malgré l'absence totale d'affichage à l'écran...

La vérification de comportement nous aurait signalé le problème :

Failure:
test_avec_un_stub_et_un_mock:
in mock 'ecran': method 'ecris(21)' called incorrect number of times. <2> expected but was <0>.

La vérification des conséquences du comportement en aurait fait de même :

Failure:
test_avec_un_stub_et_un_spy:
<21> expected but was .

Dans un exemple aussi simple, le cas est peu probable diront certains[3] mais dans du code un peu plus compliqué, ça arrive plus souvent qu'on ne le croit. D'autres diront[4] que la pratique du TDD n'aurait jamais pu conduire à cette situation : le code d'envoi à l'écran n'aurait jamais été écrit sans test qui ne passe pas.
Quoi qu'il en soit, un critère de qualité d'un test qu'il faut toujours avoir à l'esprit : un bon test passe au rouge si le code devient mauvais.

La vérification du comportement de notre thermomètre pose d'autres questions : si on vérifie le comportement de manière trop stricte, n'arrive-t-on pas à de la sur-spécification inutile ? Par exemple, un développeur qui passe sur notre code pourrait envisager une optimisation "Pas besoin d'écrire sur l'écran à chaque fois : il suffit de le faire lorsque le maximum change" et faire la modification suivante :

def affiche_temperature_maximale
  temperature_courante = @capteur.lis_temperature_courante
  if temperature_courante > @temperature_maximale
    @temperature_maximale = temperature_courante
    @ecran.ecris(@temperature_maximale)
  end
end

Et là, il se retrouve avec un test rouge pour une raison inutile qui l'oblige à aller modifier le test.

Failure:
test_avec_un_stub_et_un_mock:
in mock 'ecran': method 'ecris(21)' called incorrect number of times. <2> expected but was <1>.

Les deux autres stratégies de test n'ont pas ce problème là.

Donc, dans cet exemple précis[5], le couple stub+spy est, à mon avis, le bon choix. Le stub permet de simuler la lecture sur un capteur et le spy permet de vérifier les conséquences du comportement de l'élément testé.

Notes

[1] Google est d'accord

[2] Si un spécialiste Ruby passe par ici, qu'il n'hésite pas à pointer mes erreurs de débutant. J'ai choisi d'utiliser ce langage dans mes exemples pour son aspect dynamique qui simplifie grandement l'écriture des doublures

[3] et ils n'auront pas forcément raison

[4] et ils auront tout à fait raison

[5] N'en faisons pas une généralité

Bye Bye Scrum

R.I.P. ScrumJ'arrête Scrum.

Ce n'est pas un billet de premier avril qui aurait un peu de retard : j'arrête volontairement et définitivement l'utilisation de Scrum.

Il y a 4 ans, j'annonçais que, après quelques années de bricolages méthodologiques agiles, j'avais pris une approche relativement formelle pour passer à Scrum. Compte-tenu de mon contexte d'alors, je pense que c'était la bonne chose à faire.

Au fil du temps, l'équipe a gagné en compétence sur les pratiques agiles. De début 2007 à mi 2010, cinq releases de notre principal produit se sont succédées et, dans les derniers temps, les sprints se suivaient sans le moindre souci à gérer. En juin 2010, nous avons démarré une nouvelle ligne de produit avec un changement technologique assez conséquent.
D'un point de vue gestion de projet, le premier impact visible (et attendu) fut le changement de vélocité. Sur le produit précédent, le graphe de vélocité ressemblait à une mer d'huile. Sur les premiers mois du nouveau produit, il donnait plutôt dans la coupe d'une étape pyrénéenne du tour de France. Cela n'avait rien d'affolant : le contexte avait changé et il fallait quelques mois pour stabiliser la pertinence des estimations.
Ce n'est devenu plus problématique qu'en novembre lors de l'approche de la première release. La dernière itération avant la date butoir fut vécue comme une sorte de fin de projet où il fallait absolument livrer toutes les fonctionnalités prévues.

Je ne sais si j'ai été influencé par mes lectures d'alors[1] ou par quelques présentations intéressantes sur Kanban lors de l'agile tour mais j'ai pris -sans en parler à quiconque- une décision.
Puisque les fins d'itérations sont si mal vécues, c'est qu'elles n'ont pas que du bon. J'allais donc désormais m'abstenir d'envoyer des invitations pour la moindre réunion relative à une itération. Si un backlog ou une revue de sprint venait à manquer à quelqu'un, il ou elle le ferait probablement savoir...

Depuis quatre mois, nous n'avons plus formalisé la moindre itération.

A-t-on des problèmes pour définir le travail à réaliser ? Non. Il y a en permanence 2 ou 3 éléments du backlog de produit qui sont en cours de réalisation. Dès qu'un est terminé, celui qui suit par ordre de priorité prend sa place et est immédiatement découpé en taches.
A-t-on des problèmes pour rendre visible l'avancement du travail ? Non. Dès qu'un élément du backlog est terminé, il est présent dans le build du produit, lequel est immédiatement disponible pour qui voudrait l'essayer.

Progressivement, notre mode de fonctionnement passe d'un cadencement par les itérations à un flux qui s'écoule de manière plus régulière. La métaphore du "sprint" était en fait très bien choisie. On avait juste oublié qu'il est plus facile de gérer son effort dans une course de fond que dans une succession de sprints.

Bien sûr, tout cela n'est pas aussi simple. La disparition des itérations entraine des contraintes plus importantes sur certains aspects du processus.
L'intégration continue est un de ces aspects : la nécessité d'un build à jour et en état livrable est quasi-permanente. Heureusement, les efforts consentis sur la mise en oeuvre sans concession d'un développement piloté par les tests commencent à porter leurs fruits.
La planification des estimations doit, elle aussi, s'adapter au flux. Il n'y a plus de "début de sprint" où on peut estimer tout ce qui aurait pu entrer dans le backlog de produit pendant le déroulement du sprint précédent.

La définition de la vélocité et, plus généralement, du plan de release est probablement le changement le plus significatif.
Pour la vélocité, on a pour l'instant fait très simple. Quand on a des itérations de 4 semaines, la vélocité, mesurée en fin d'itération, c'est la somme des points des éléments du backlog terminés au cours des 4 dernières semaines. Et quand on n'a plus d'itérations ? Et bien, rien ne nous empêche de continuer à prendre la même mesure !!! On a une vélocité calculée sur une fenêtre glissante qui change chaque jour. Si le flux des éléments de backlog s'écoule régulièrement à travers l'équipe de développement, cela ne change rien par rapport à une mesure de vélocité par itérations.
D'ailleurs, il faut bien comprendre que la vélocité ne sert, au final, qu'à une seule chose : proposer une date de release la plus réaliste possible. Quand on a des itérations, la taille du backlog de release divisée par la vélocité nous donne le nombre d'itérations restant à effectuer pour terminer la release. Quand on n'a plus d'itérations, on divise toujours la taille du backlog de release par la vélocité, puis on multiplie par la taille, en jours, de la fenêtre de calcul de la vélocité et on obtient une approximation guère moins exacte du nombre de jours restant avant la release...

Finalement, la suppression des itérations et le passage à un processus de flux n'a rien de bien compliqué. Le point à surveiller le plus crucial est le maintien du flux. On doit en permanence garder à l'esprit qu'il vaut toujours mieux achever ce qui est déjà commencé que de commencer autre chose. Concrètement, cela veut dire que si un développeur termine quelque chose, il devrait, avant de prendre une nouvelle tache, toujours se demander s'il ne peut pas aider un collègue à terminer une tache en cours.
Ce n'est pas grand chose mais je crois que c'est une notion fondamentale. Quand on fonctionne par sprints, on a tendance à remplir un backlog de sprint avec des taches et à ne plus trop se préoccuper de la valeur de chacune de ces taches. Pourtant, à un instant donné, une tache qui permet de terminer la réalisation d'une histoire utilisateur a énormément plus de valeur qu'une autre tache qui ne fait que démarrer la réalisation d'une autre histoire.
Le but d'une méthode agile n'est-il pas de fournir, dans un délai le plus court possible, de la valeur pour les utilisateurs tout en conservant un rythme viable sur une longue durée ?

Il y a là, je pense, matière à réflexion pour toute équipe pratiquant le développement itératif.
En ce qui me concerne, le pas est franchi. Scrum, c'est fini. Désormais, tout se passera dans le flux.

Notes

[1] Je ne lis pas souvent mai, en novembre dernier, j'ai notamment apprécié "Lean Management" de Pierre Pezziardi et "Who Moved My Cheese ?" de Spencer Johnson

Le référentiel des pratiques agiles : vers la formalisation du "framework agile" ?

Il y a quelques jours semaines[1], l'institut agile a publié la 1ère version du référentiel des concepts, pratiques et compétences agiles.

Par les temps qui courent, de plus en plus de monde s'intéresse aux méthodes agiles et le nombre d'experts de la chose s'adapte bien évidemment à la demande qui en résulte. Dans un tel contexte, un référentiel a un intérêt immédiat : clarifier les définitions du vocabulaire agile pour que tout le monde parle de la même chose avec les mêmes mots.

Et même en ayant une bonne expérience des méthodes agiles, je crois que l'on sous-estime le besoin de définitions partagées et non ambigües.
Un exemple. Récemment, lors d'une discussion sur la liste "xp-france", j'ai posé une question et j'ai eu la réponse suivante :

Les équipes que j'ai vu faire de l'agile utilisent le concept d'itération pour répondre à cette question. A intervalles réguliers, ils vérifient avec les clients (parfois nommés aussi "utilisateurs") que le produit correspond à ce qu'ils sont prêts à payés.

La réponse ne correspondait pas à ce que j'attendais[2].
En temps normal, je n'aurais pas creusé plus loin mais, là, je suis allé voir la définition d'itération dans le référentiel :

Une itération au sens Agile est une "boite de temps" ou "timebox" dont la durée:
*varie d'un projet à l'autre, de 1 semaine à 4 semaines, rarement plus
*est en principe fixe sur la durée du projet

Une boîte de temps ou "timebox" est une période fixe pendant laquelle on cherche à exécuter le plus efficacement possible une ou plusieurs tâches.

Et il se trouve que, depuis quelques mois, mon équipe n'utilise plus de boites de temps[3] ce qui ne nous empêche pas de demander très souvent à notre chef de produit si ce que l'on fait correspond bien à ce qu'il a en tête.
Cette possibilité de vérification n'est donc pas issue des boites de temps.
En fait, ce qui permet à un client de vérifier très souvent que le produit correspond à ses attentes, c'est le développement incrémental

Pour s'en convaincre, il suffit d'aller regarder la définition dans le référentiel :

Le développement incrémental consiste à réaliser successivement des éléments fonctionnels utilisables, plutôt que des composants techniques.

J'apprécie énormément cette précision sur les termes utilisés.

Le seul reproche que je pourrais faire au référentiel dans sa version actuelle, c'est la frontière qui me parait encore un peu ambigüe entre les "concepts" et les "pratiques".
Pour ma part, j'aurais plutôt vu "développement itératif" et "développement incrémental" dans les pratiques et non pas dans les concepts.

Ceci étant dit, le potentiel de ce référentiel me parait important.
Je ne sais pas si c'est un objectif souhaitable pour ce référentiel mais j'y verrais bien une plus grande articulation des pratiques entre elles, façon pattern language.

Le canevas de description des pratiques est ce que l'on attendrait classiquement d'une fiche de pattern[4]
Par exemple, chaque pratique contient une section "bénéfices attendus" qui la met en perspective en tant que solution possible à un problème que l'on pourrait rencontrer.

Un exemple assez représentatif : intégration continue

* le principal intérêt de l'intégration continue est de réduire la durée, l'effort et la douleur provoquée par chaque intégration, l'expérience suggérant qu'il existe un "cercle vicieux" dans le sens inverse: plus les intégrations sont espacées, plus elles sont difficiles, et plus (en réaction à la douleur provoquée) on a tendance à les espacer
* l'intégration continue démultiplie le bénéfice d'une batterie étendue de tests unitaires: elle permet de détecter au plus tôt les défauts n'apparaissant qu'à l'intégration et par conséquent de minimiser leurs conséquences et les risques associés aux défauts d'intégration
* l'intégration continue permet de tirer le meilleur parti du développement incrémental: des questions comme l'installation et le déploiment du produit ne sont pas laissées de côté jusqu'à la fin du projet mais résolues dès le départ dans le cadre de la pratique

Le petit plus qui permettrait d'atteindre le niveau langage de patterns, c'est une formalisation des liens entre les différentes pratiques. Dans l'exemple précédent quelques filiations apparaissent : pour qui implémente déjà la pratique "tests unitaires automatisés" ou la pratique "développement incrémental", l'intégration continue est une suite logique.

Ce langage de pratiques agiles, que l'on peut également qualifier de "framework agile" me semble inévitable.
L'agilité en est arrivée à un point où tout le monde essaie d'adapter les méthodes existantes à des contextes très variés (avec plus ou moins de savoir faire).
Une bonne boite à outils serait certainement très utiles à tous les apprentis sorciers qui conçoivent des schemas d'organisation agile après deux jours de formation Scrum et la lecture d'un ou deux livres.
Et aux autres, aussi, bien sûr.

Notes

[1] le temps passe trop vite

[2] mais c'est une autre histoire : j'aurais dû formuler différemment ma question

[3] on est passé à un mode de fonctionnement "en flux" mais ça aussi c'est une autre histoire

[4] je n'arrive pas à me faire à la moindre francisation de ce mot : patron, motif, modèle...

Gloubi-Boulga Agile

De temps à autre, j'aime bien me balader en ligne dans les endroits où les gens parlent de méthodes agiles. Ca permet de garder un certain contact avec les préoccupations actuelles de ces personnes.
Ce soir, sur le groupe linkedin consacré au French Scrum User Group, je suis tombé sur une discussion qui m'a donné l'impression de débarquer sur une autre planète. Si c'est ça les méthodes agiles aujourd'hui, il serait grand temps pour moi d'aller voir ce qui se passe ailleurs. Un ailleurs où on serait plus attaché à faire de bons logiciels qu'aux organisations d'entreprises où on fait entrer de "l'agilité" au marteau piqueur (voire au bulldozer ?)

Ou devrais-je me consoler en me disant que ces gens là ne parlent pas vraiment de méthodes agiles car, en fin de compte, ils ne parlent que de Scrum ?

Pour ceux qui n'auraient pas l'immense privilège d'être inscrits sur linkedin et d'avoir accès à ce groupe, voici la discussion en question:


Intervenant A
Dans les grosses organisations, des Responsables qualité et PMO interviennent en soutien des Chefs de projet. Dans un monde agile, que deviennent-ils ?

Si t’es pas codeur, t’es pas producteur de logiciels

Au fil de ses réflexions sur le livre numérique, Thierry Crouzet vient d'écrire deux billets Si t’es pas codeur, t’es pas auteur et T’es pas codeur, t’es pas éditeur.

Je ne connais rien, ou si peu, au livre numérique mais quelques passages m'ont fait l'effet d'une étincelle.

Un auteur numérique ne produit pas des textes figés. Il doit rester en éveil sur ses créations, les faire vivre, leur donner la possibilité d’évoluer, sans pour autant renoncer à les partager avec ses lecteurs. C’est aussi une dimension de l’écriture qui a été peu exploitée jusqu’ici, à cause de la lourdeur des procédés éditoriaux.

S’il faut deux jours pour créer un epub, vous pouvez parier qu’aucun éditeur ne s’amusera à le recréer chaque fois que l’auteur en exprimera le souhait. Si tel est le cas, il ne fait que mimer en numérique l’édition papier.

Ces passages s'appliquent quasiment mot pour mot à la production de logiciels.

Un producteur de logiciels ne fabrique pas des oeuvres figées. Il doit rester en éveil sur ses créations, les faire vivre, leur donner la possibilité d’évoluer, sans pour autant renoncer à les partager immédiatement avec ses utilisateurs. C’est aussi une dimension de la production de logiciels qui a été peu exploitée jusqu’ici, à cause de la lourdeur des procédés de spécification, conception, distribution et installation.

S’il faut deux mois pour vérifier, valider et déployer une nouvelle version de logiciel, vous pouvez parier qu’aucun producteur ne s’amusera à dérouler toutes ces étapes chaque fois que l'utilisateur en exprimera le besoin. Si tel est le cas, il ne fait que mimer en numérique la création de produits physiques.

La production de logiciels telle que pratiquée par la majorité des "professionnels" a quelque chose d'assez déroutant : le produit réalisé et fourni à des utilisateurs est exclusivement immatériel mais les procédés qui encadrent sa réalisation sont la plupart du temps hérités du monde matériel.
Les éditeurs de livres dont parle Thierry Crouzet ont un très probablement un chemin à parcourir pour intégrer dans leurs pratiques quotidiennes la notion de "code" qui vient naturellement avec le passage au numérique. Les producteurs de logiciels, malgré la présence du numérique inhérente à leur activité, ont exactement le même problème.

Pourquoi ? Parce que la plupart d'entre eux ne sont pas des codeurs.

Oh... Il y a bien évidemment dans une équipe de production de logiciels quelques personnes capables d'écrire du code... sinon le logiciel ne verrait bien évidemment jamais le jour. Mais la production ne s'arrête pas à cela. On y trouve aussi des analystes capables de décrire le besoin des utilisateurs, des testeurs pour vérifier le bon comportement du logiciel, des auteurs techniques pour écrire les manuels d'utilisation et bien d'autres rôles. Sans oublier l'incontournable chef de projet qui dirige tout ça.
Tous ces rôles sont essentiels [1] mais ils sont souvent occupés par des personnes pour qui l'écriture de code n'est pas une activité naturelle et qui n'ont donc pas le réflexe d'introduire la notion de code au coeur du procédé de fabrication.

La conséquence directe c'est que pour produire un logiciel, une équipe se retrouve à faire nombre d'activités manuelles.
La conséquence suivante, c'est que pour gérer l'enchainement de ces activités manuelles, le chef organise l'activité de production comme un projet[2].
Un "projet", c'est un truc qui a un début et une fin et diverses phases qui ne sont justifiées que par l'impossibilité matérielle de réaliser toutes les activités manuelles en même temps.

Les vendeurs d'outils[3] pour la production de logiciel ne sont pas étrangers à cette situation. Les producteurs de logiciel, en utilisant ces outils, s'éloignent du code utilisé pour fabriquer le logiciel. Ils laissent le soin à d'autres de définir ce code à leur place et se retrouvent ainsi à ne maitriser que vaguement leur processus de fabrication dont ils bouchent les trous à grand renfort de procédures manuelles.

Mais cela n'a rien d'une fatalité.
Il faut simplement oser sortir de la logique de projet pour entrer dans une logique de flux. Le code est la clef de cette transition. En s'appropriant le procédé de fabrication et en l'automatisant soi-même[4] sous forme de code, chaque équipe de production de logiciel peut s'affranchir de nombreuses contraintes physiques. Tout ce qui constitue un goulot d'étranglement à l'écoulement du flot de fonctionnalités vers l'utilisateur doit être soigneusement éradiqué en introduisant le code adéquat[5].

Les méthodes agiles, en mettant en avant les cycles courts et la production en continu, favorisent l'émergence d'une telle logique de flux.

Notes

[1] quoique, pour le chef de projet, ça se discute

[2] d'où son nom : chef de "projet"

[3] outil pris au sens large : IDE, compilateur, debugger, contrôle de code source, gestion d'exigences, gestion de défauts, ...

[4] il faut certes avoir recours à quelques outils mais, des outils dont on garde l'entière maitrise tel un artisan dans son atelier.

[5] je ne dis pas que tout le monde dans l'équipe doit apprendre des techniques de codage mais tout le monde devrait, au minimum, voir les choses avec les yeux d'un codeur

4 bougies et un programme exceptionnel pour le SigmaT 16

Il y a 4 ans, Claude Aubry organisait le premier Séminaire d'information gratuit sur les méthodes agiles à Toulouse. Un impératif m'empêchait d'y assister mais je n'ai manqué aucune des éditions qui ont suivi.

Et je ne manquerai certainement pas la prochaine. Le 10 décembre 2010 à partir de 16 heures, le SigmaT souffle ses 4 bougies à l'occasion de sa 16ème édition. Le programme est en ligne et est assez exceptionnel avec un thème central : l'aspect social des méthodes agiles. Celles-ci sont, on l'oublie trop souvent, une question de personnes réelles avant d'être des collections de principes et de pratiques.

La qualité et la diversité des intervenants seront au rendez-vous :

  • Laurent Bossavit, directeur de l'institut agile et précurseur des méthodes agiles en France, racontera les 40 ans de crise du "génie logiciel" et les 10 ans d'agilité qui ont changé la façon d'aborder ce génie logiciel pour un grand nombre de personnes.
  • Florent Bonnel, psychologue et président de l'APAP, et Grégory Salvan aborderont les risques psychosociaux et trouveront peut être dans les méthodes agiles un moyen pour y faire face.
  • Nicolas Séné, journaliste qui vient de sortir le livre "Derrière l'écran de la révolution sociale", parlera des conditions de travail des salariés en SSII, très éloignées, pour la plupart, des valeurs du manifeste agile.

Comme d'habitude, l'IUP ISI accueille ce séminaire dans les locaux de l'université Paul Sabatier de Toulouse et l'entrée est gratuite mais il est demandé, pour des questions de logistique, de s'inscrire via le formulaire en ligne.

Venez nombreux !

"Derrière l'écran de la révolution sociale"

Je découvre aujourd'hui l'existence de ce livre de Nicolas Séné et du blog qui va avec par les actions quasi-simultanées de Thierry et de Libé Toulouse.

Le thème du livre n'a rien de surprenant pour quiconque connait le monde du développement logiciel en France et a cotoyé de près ou de loin les SSII :

Le livre propose de décortiquer le modèle social au sein des Sociétés de services en ingénierie informatique (SSII) ou “Quand le monde de l’informatique et des SSII sert de laboratoire social et induit une précarisation par le haut.”

Ce qui m'embête un peu plus, en revanche, ce sont les éventuelles conséquences de la prise de conscience induite par ce constat. Le dernier chapitre du livre semble évoquer le syntec, les syndicats et le MUNCI. Ce dernier a une position très conservatrice concernant les remèdes à apporter (protectionnisme économique, mesures fiscales de "relance", ...) et la perspective de voir le secteur du logiciel tomber dans les mêmes travers que d'autres secteurs touchés par la mondialisation concurrence ne me réjouit guère.
A quoi bon s'affranchir du pouvoir d'un certain capitalisme peu enclin à faire des produits de qualité pour se retrouver à la merci d'un pouvoir d'état qui, au gré du vent, décide de favoriser telle ou telle catégorie de personne ?

Les méthodes agiles véhiculent une autre perspective de changement social pour le développement logiciel, une perspective beaucoup plus réjouissante où producteurs et consommateurs de logiciels peuvent trouver une meilleure harmonie. Encore faudrait-il que ces méthodes ne soient pas dévoyées par quelques SSII (toujours elles !) qui prétendent faire de l'agilité mais n'ont en fait trouvé qu'une manière de plus pour vendre leur viande.
Je n'ai pas été surpris de retrouver parmi les billets de Nicolas Séné une SSII pratiquant le niveau zéro des ressources humaines. Cette SSII est la même qui publie des offres d'emploi hilarantes dans le domaine des méthodes agiles.

Le 9 novembre prochain une rencontre avec Nicolas Séné est organisée à la librairie Terra Nova. Je crois que je vais aller y faire un tour !

Agile Tour Toulouse 2010

Jeudi dernier, c'était l'étape toulousaine de l'agile tour 2010. Comme à Bordeaux, j'animais l'atelier Stub et Mock montent sur scène qui, pour sa 3ème édition, commence à être rodé. L'intérêt des participants est toujours au rendez-vous et de l'action en début de journée, ça évite d'aller s'assoupir dans les fauteuils d'un amphithéatre.
Quoique, à la même heure, certains étaient dans un de ces amphis en train d'écouter attentivement les fables de La Fontaine.

C'est ce même amphi que j'ai rejoint après la pause de la matinée pour écouter Pascal Fortin sur la mise en oeuvre de méthodes agiles en environnement contraint par la norme DO-178B. Les résultats annoncés sont plutôt impressionnants.
Point positif notable : on peut visiblement justifier l'utilisation d'une méthode agile là où les activités de développement et de vérification doivent être confiées à des équipes indépendantes.
Un bémol : la méthode Scrum introduite dans des équipes Extreme Programming pour justifier la mise en oeuvre d'un cadre plus formel. Le marketing Scrum aura réussi a faire avaler tout et n'importe quoi...

Lors de la session suivante, j'ai changé d'amphi pour aller voir Jean-Michel Inglebert exposer les atouts et les faiblesses des méthodes agiles.
Présentation très rythmée et parsemée de propos intéressants, notamment sur la confiance.
Il y a juste un point avec lequel j'ai un peu bloqué. Les méthodes agiles savent tout à fait gérer les changements importants dans la définition d'un produit : elles le découpent en petits changements.

Fin de la matinée. Suit une courte pause repas avec Isabelle, Marie-José, Grégory et Guillaume. La discussion nous amène sur l'enseignement de l'informatique dans les études supérieures et sur la place de l'agilité dans ces études. C'est un sujet assez récurrent pour moi ces temps-ci. On évoque également l'enseignement d'UML, ce qui m'amène à penser qu'enseigner UML en 2010, c'est comme quand j'avais des cours sur SADT ou Merise au début des années 1990 : un truc qui va peut-être servir à quelques personnes mais qui est inéluctablement sur le déclin.

L'après-midi démarre avec ce qui restera pour moi LA session qu'il ne fallait pas manquer : "XP, le projet social" par Thierry Cros et Angèle Batanero. Je n'ai rien appris sur Extreme Programming en tant que tel mais les considérations sur le changement social, la revalorisation du métier de développeur, la fierté du travail bien fait, l'auto-gestion, l'analogie avec les AMAPs et, enfin, la prise de conscience de l'inter-dépendance qui nous relie, développeurs et utilisateurs de logiciels sont autant de sujets que tout praticien des méthodes agiles digne de ce nom devrait prendre en considération.
Mais combien, parmi les personnes présentes, sont prêtes à embrasser ce changement là ?

Je continue mon après-midi avec Laurent Meurisse qui nous parle d'innovation dans les DSI. Sa présentation apporte une vision intéressante mais qui manque, à mon avis, de maturité. Les questions abordées en fin de prez mériteraient une place plus large, notamment sur les aspects humains. L'innovation ne peut pas se contenter d'un changement d'organisation. Si celui-ci n'est pas soutenu, voire porté, par l'ensemble des personnes travaillant dans une DSI, l'innovation aura la résistance d'un chateau de cartes.
Incidemment, je viens de lire "Lean Management" de Pierre Pezziardi. Ce sujet du facteur humain dans la transformation de l'entreprise me semble prêt pour le devant de la scène.

La fin de journée se placera sous le signe du Kanban.
Avec Luc Delamotte, d'abord, qui vient présenter la transition "Cycle en V => Scrum => Kanban" chez Thalès Alenia Space. Avec le trio infernal ensuite qui mélange Scrum et Kanban pour en sortir un résultat, semble-t-il, assez comestible.
Je ne m'étendrai pas sur le sujet. Ce sera certainement l'objet d'un billet à part entière dans les jours ou semaines à venir. J'avais déjà des envies de Kanban depuis quelques temps. Ces présentations m'ont conforté dans l'idée qu'il fallait tenter quelque chose. Reste à discuter de ça avec mon équipe et à voir ce qui pourrait être fait pour parvenir à un rythme de travail plus fluide (l'origine de mes envies tient dans un rythme itératif qui donne parfois l'impression de rouler à 130km/h et de voir arriver la fin d'itération comme un dos d'âne sur la chaussée)

La journée se terminera par une mini-retrospective à chaud autour d'une bière avec la plupart des organisateurs de la journée (en attendant la "vraie" retrospective lundi prochain). On évoque ce qu'il faudrait faire évoluer pour les éditions ultérieures. Mon intime conviction est que les thèmes abordés sont trop restreints à une certaine catégorie de sujets mais cela, aussi, sera l'occasion d'un billet à part entière...

L'intérêt réel de la certification ScrumMaster

Claude a récemment publié un billet sur la certification ScrumMaster où il évoque, entre autres, la distorsion induite sur la marché de l'emploi par l'existence d'une telle certification :

On pourrait m'accuser de plaidoyer pro domo puisque je propose des formations Scrum. Je n'en ai pas besoin : mes formations marchent très bien en ce moment. Non, ceux que je veux défendre, ce sont les participants à ces formations.
Imaginons qu'ils soient en concurrence pour un emploi ou une participation à un projet avec d'autres qui auraient mis sur leur CV "scrumMaster certifié". Il serait très injuste que des recruteurs considèrent cela comme un avantage compétitif.

Pour ma part, je vois au contraire l'existence de cette certification comme une très bonne chose. C'est ce que je tente d'expliquer en commentaire du billet :

Si je devais rechercher un poste de ScrumMaster ou équivalent, je commencerais par *éliminer* les offres d'emploi qui mentionnent la certification. Les sociétés qui les ont publiées ne sont certainement pas celles où j'aurais envie d'aller.
De même qui aurait envie de travailler pour un recruteur qui donne de la valeur à ces certifications ? Reconnaissons donc au moins à celles-ci un rôle sanitaire !

Je vais ici essayer d'apporter de l'eau à mon moulin.

Pour cela, prenons un moteur de recherche d'offres d'emploi relativement bien fourni et lançons la recherche "scrum certification". Sept réponses. Je prends la première de la liste. Elle a été publiée par une SSII fort connue.

Dès le titre, ça commence TRES fort : SCRUM Master senior / Leader Technique
Je ne savais même pas qu'il existait des ScrumMasters "seniors". Est-ce une nouvelle certification ? Une réponse au travail des "seniors" en cette période de réforme du système des retraites ?
Et le ScrumMaster, non seulement il est senior mais en plus il est leader technique. Les rôles ne sont pas incompatibles mais ça commence à faire beaucoup pour une seule personne.
Mais voyons plutôt de quoi il est question dans le détail.

Les expertises relatives à la gestion de projet en mode Agile sont essentielles pour répondre et pour satisfaire les attentes de nos clients

Rien à redire là dessus.

En tant que Responsable Technique / Scrum master senior, au sein d'une équipe et sous la responsabilité d'un chef de projet, vos principales missions consistent à :

Là, ça se complique. "sous la responsabilité d'un chef de projet" Voilà une bonne idée ! Ceux qui pensaient que l'agilité consistait à donner à l'équipe dans sa globalité les moyens de s'auto-organiser et d'être ainsi en mesure d'exercer collectivement la responsabilité du projet peuvent sortir leurs mouchoirs.

- Participer aux phases d'avant-vente (évangélisation et réponses à appel d'offres),

Pourquoi pas.

- Comprendre le contexte fonctionnel et technique du projet,

Ca veut dire qu'il existe des membres de l'équipe qui n'ont pas besoin de comprendre le contexte ?

- Former et coacher les équipes projets sur SCRUM,

Oui

- Participer à la définition des infrastructures techniques des SI,

Comme pour le contexte, il y aurait des membres de l'équipe qui seraient exclus d'une telle activité ?

- Préconiser des solutions techniques et chiffrer leurs mises en œuvre,

Si c'est le ScrumMaster qui chiffre les développements, ça commence à sentir le roussi.

- Vérifier et analyser les impacts techniques des solutions,

Encore une chasse gardée du scrummaster-senior-leader-technique ?

- Piloter les travaux de l'équipe de développement et en particuliers l'intégration technique,

Enfin ! Là au moins c'est clair : le scrummaster-senior-leader-technique dirige les développeurs

- Accompagner le projet jusqu'à la validation par le client final,

Ah bon ? la validation par le client final n'interviendrait qu'à la fin du projet ?

- Vérifier la mise en application de vos recommandations,

Et si les membres de l'équipe décident collectivement de ne pas les suivre ?

- Mettre en place et coordonner une démarche de tests de performances,

Encore une tache dédiée au scrummaster-senior-leader-technique ?

- Participer au déploiement opérationnel du système d'information de nos clients.

Il va falloir l'appeler scrummaster-senior-leader-technique-superman


Et quel profil recherche-t-on pour des telles responsabilités ?

vous avez déjà participé à un projet utilisant une méthodologie de type agile (Scrum, XP, RAD). Idéalement, vous avez été Scrum Master et pouvez justifier d'une certification.

Voilà, la messe est dite. "Idéalement", un ScrumMaster senior est un scrummaster certifié. Et il peut même avoir été un puma dans une autre vie.

Et que peut-on faire après avoir été scrummaster-senior-leader-technique-superman ?

Votre sens du service et de la relation client, votre rigueur d'analyse et votre goût pour le travail en équipe sont autant d'atouts qui vous permettront d'évoluer vers le management de projet ou l'expertise technique.


Vous avez compris ?
Si vous voulez évoluer vers le "management de projet" alors que vous n'êtes qu'un responsable technique de base, la certification CSM est une étape essentielle qui vous permettra de gravir les échelons de la hiérarchie dans une entreprise à la pointe des méthodes les plus en vogues pour le développement de logiciels.

A défaut de nous faire gravir des échelons, remercions donc la Scrum Alliance et ses certifications qui permettent aux candidats d'éliminer directement quelques annonces complètement bidons sur l'utilisation des méthodes agiles.

C# et Ruby, des syntaxes si différentes ?

Parmi les langages à la mode, s'il en est un qui semble avoir le vent en poupe, tout particulièrement dans la communauté "agile", c'est certainement Ruby. Je ne le connais pas assez bien pour pouvoir juger globalement de ses qualités et de ses défauts mais j'ai essayé de voir à quoi cela ressemblait d'un point de vue strictement syntaxique afin de pouvoir comparer avec les langages que je connais un peu plus et tout particulièrement C#.

Parmi les éléments de Ruby souvent mis en avant, j'ai l'impression que l'on trouve le "tout est objet".
Ce qui permet d'avoir des écritures un peu surprenantes au premier abord pour le programmeur plus habitué aux codes impératifs que déclaratifs. Par exemple :

3.times { puts 'Hello world!' }

Pourtant, en C# je pourrais tout aussi bien écrire :

3.Times( () => Console.WriteLine("Hello world!") );

Bien sûr, la méthode 'Times' n'est pas définie sur les 'int' mais rien ne m'empêche de l'écrire !

public static void Times(this int self, Action action)
{
  for(int i=0; i<self; i++)
    action();
}

En fait, la plupart de ces éléments qui apportent une grande lisibilité au code -pour peu que l'on ne reste pas enfermé dans un jeu restreint d'idiomes- sont utilisables dans la plupart des langages dignes de ce nom.

Par exemple, en Ruby, je peux facilement rajouter des unités de temps pour rendre les calculs plus explicites

module TimeUnits
  def seconds; self;              end
  def minutes; self * 60;         end
  def hours;   self * 60.minutes; end
  def days;    self * 24.hours;   end
end
class Fixnum; include TimeUnits; end

Ce qui permet de faire passer le test suivant :

assert_equal(184693.seconds, 2.days + 3.hours + 18.minutes + 13.seconds)

Mais je peux faire à peu près la même chose en C# :

Assert.That( 2.Days() + 3.Hours() + 18.Minutes() + 13.Seconds(), Is.EqualTo(184693.Seconds()) );

Il me suffit de rajouter les déclarations adéquates :

public static TimeSpan Days(this int self) { return new TimeSpan(self,0,0,0); }
public static TimeSpan Hours(this int self) { return new TimeSpan(0,self,0,0); }
public static TimeSpan Minutes(this int self) { return new TimeSpan(0,0,self,0); }
public static TimeSpan Seconds(this int self)	{ return new TimeSpan(0,0,0,self); }

Mais on peut faire encore mieux. On a vu les entiers mais qu'en est-il des intervalles d'entiers ?

En Ruby, on peut écrire quelque chose comme ça :

assert_equal( 70, (1..10).inject(15) {|sum, val| sum + val} );

(1..10) définit l'intervalle des entiers de 1 à 10 et la méthode 'inject' sur cet intervalle permet de réaliser un accumulation en appliquant un bloc de code sur chaque élément de l'intervalle.
Et en C# ?... C'est la même chose ! Les noms changent mais les éléments sont identiques.

Le code suivant n'utilise que des éléments standards du Framework .NET :

Assert.That( Enumerable.Range(1,10).Aggregate(15, (sum,val)=>sum+val), Is.EqualTo(70) );

Bon. Les intervalles, c'est fait. On va peut être aller regarder du côté des listes. La facilité d'utilisation des listes en Ruby, on ne la retrouve pas en C#.

Pour peu que l'on ait défini une méthode 'sum' comme celle-là :

class Array;
  def sum;
    inject( nil ) { |sum,x| sum ? sum+x : x };
  end;
end

On peut écrire le code suivant qui n'a pas besoin d'explication :

assert_equal( 9, [1,3,5].sum );

Mais, en fait, ce n'est vraiment un problème pour le C# où on peut écrire :

Assert.That( Sequence.Of(1,3,5).Sum(), Is.EqualTo(9) );

Il suffit de coder un moyen simple pour créer un IEnumerable :

public static class Sequence
{
  public static IEnumerable<T> Of<T>(params T[] items)
  {
    foreach(var item in items)
      yield return item;
  }
}

La méthode 'Sum', elle, fait déjà partie du framework.

Là où ça se complique un peu, c'est pour les listes dont les éléments n'ont pas le même type.

Si je veux reproduire une telle incantation:

[1, 'hi', 3.14].each {|item| puts item }

Je vais d'abord rajouter une méthode pour créer des IEnumerable<object> :

public static IEnumerable<object> Of(params object[] items)
{
  foreach(var item in items)
    yield return item;
}

Ensuite il me faudra un moyen pour appliquer une action à chaque élément de mon IEnumerable :

public static IEnumerable<T> Apply<T>(this IEnumerable<T> self, Action<T> action)
{
  foreach(var e in self)
  {
    action(e);
    yield return e;
  }
}

Le IEnumerable en type de retour me permettra, le cas échéant, d'enchainer les 'Apply' de plusieurs actions.

Enfin il ne me reste plus qu'à écrire le code qui va bien pour utiliser ces méthodes :

Sequence.Of(1, "hi", 3.14).Apply( x => Console.WriteLine(x) );

Et là, on se rend compte qu'il ne se passe rien ! Pas un seul affichage sur la Console !
En effet, nos IEnumerable construits à base de 'yield return' ne sont pas des listes au sens "objet" du terme. Il n'y a aucune instance de collection derrière ces déclarations.
Les boucles foreach(yield return) ne sont qu'une écriture très particulière pour combiner des opérations complexes sur des énumérations d'éléments, ce qui a d'ailleurs un effet bénéfique sur les performances par rapport à des objets 'List' utilisés à mauvais escient.

Alors comment fait-on pour que nos foreach soient réellement parcourus ? Le plus simple est d'avoir une méthode qui utilise les éléments de la liste sans elle même renvoyer un nouvel IEnumerable :

public static void Now<T>(this IEnumerable<T> self)
{
  foreach(var item in self);
}

Et, enfin, tout fonctionne :

Sequence.Of(1, "hi", 3.14).Apply( x => Console.WriteLine(x) ).Now();

Finalement, avec très peu de code, on peut faire faire au C# pas mal de chose intéressantes...

Note : normalement aucun troll ne passe par ici mais, au cas où, je précise que l'intégralite du code de ce billet a été écrite sous GNU/linux avec un environnement Mono pour tout ce qui concerne le C#.

Agile Tour Bordeaux 2010

J'étais jeudi à Bordeaux pour une des premières sessions de l'Agile Tour 2010. Après le SigmaT 15, j'y ai animé pour la 2ème fois l'atelier Stub et Mock montent sur scène devant une assistance motivée qui est largement entrée dans le jeu. J'espère que tout le monde a pris autant de plaisir que moi à y participer.

Je suis assez chanceux d'avoir été programmé en fin de matinée car la journée fut finalement plutôt chargée.

Je l'ai entamée avec l'excellent Kata-marrant d'Emmanuel Gaillot et Jonathan Perret. On peut décrire un tel atelier mais il est difficile d'imaginer son déroulement sans être présent dans la salle.
Tout ce que je peux dire, c'est que j'ai assisté à une performance hors du commun qui répand immédiatement la bonne humeur dans l'assistance. Et la prochaine fois que je me trouverai, sur un projet, face à une contrainte un peu trop forte, je me demanderai surement si celle-ci n'aurait pas eu sa place dans le chapeau d'Emmanuel et Jonathan.
Seule ombre au tableau : mon voisin de droite qui, rapidement, est visiblement peu intéressé et commence à trafiquer son téléphone portable pour finir par quitter la salle au milieu de l'atelier.
Note pour les éditeurs d'IDE : il y a peut être un marché pour divers types de refactorings inexplorés à ce jour ; par exemple, le "refactoring to ASCII art".

Ensuite, après une courte pause c'était au tour de "Stub et Mock", je n'y reviens pas.

Pour le début d'après-midi, j'ai choisi d'aller squatter à l'espace AgorAction initié par Luc Bizeul.
Cette d'idée d'avoir des sujets à la carte était finalement une très bonne chose puisque ce qui s'y échangeait m'intéressait finalement plus que les confs et ateliers du moment.

J'ai tout d'abord participé à une table qui évoquait le "Kata XP next gen", titre relativement accrocheur pour une discussion qui s'est focalisée sur la définition d'un exercice pour s'entrainer à comprendre le métier du client. On a parlé de l'écriture des user stories, on a évidemment évoqué le DDD mais on a fini par s'attacher à une approche que je trouve bien plus intéressante : les métaphores.
La "métaphore du système" était une des pratiques de XP qui m'a le plus intrigué et qui a indubitablement joué un rôle dans mon intérêt pour cette méthode il y a de ça quelques années. Depuis, la pratique est largement tombée en désuétude car les bonnes métaphores sont, j'en suis convaincu, très utiles mais extrêmement difficiles à créer. Alors l'idée d'un exercice qui permet de s'y entrainer mérite un peu d'attention.
Nous avons à peine effleuré la mise en oeuvre d'un tel exercice. Le principe de base serait d'avoir une personne qui joue le rôle d'un client qui a une connaissance approfondie de son métier et des besoins auxquels devraient répondre un logiciel dont il serait l'utilisateur. Le reste du groupe l'interroge pour en arriver à définir une métaphore de ce métier et de ces besoins ; la validation finale revient au client qui évalue la qualité de la métaphore obtenue.

Pour la 2ème salve de discussions, j'ai rejoint une table qui s'attelait à définir les pré-requis pour un développeur fraichement diplomé qui vise à intégrer une équipe agile. Je n'ai plus en tête les détails des qualités et compétences que l'on a listées (mais les compte-rendus de toutes les tables seront publiés d'après ce que j'ai cru comprendre).
Les pré-requis étaient classés en 3 catégories : savoir, savoir-être et savoir-faire. La colonne "savoir" était relativement succinte, ce qui ne m'étonne pas plus que ça car les valeurs et les principes agiles représentent une quantité de connaissances relativement limitée. La colonne "savoir-être" était la plus fournie ce qui montre à quel point l'attention au comportement des individus tient une place de choix dans la hiérarchie des besoins exprimés par les praticiens de l'agilité.
La colonne "savoir-faire" était bien plus squelettique. L'argument principal pour ce fait : la plupart des pré-requis que l'on peut y lister n'est pas spécifique à l'agilité. Cet aspect des choses me laisse un gout d'inachevé. Le leitmotiv "Practice ! Practice ! Practice !" est une réalité pour un développeur agile. Même si les techniques qui constituent le savoir-faire d'un bon développeur ne sont pas spécifiques à un fonctionnement agile, je n'ai finalement rencontré, hors communauté agile, que très peu de personnes qui y attachent une attention soutenue.

Pour finir cette journée, je suis aller voir l'agilité sans concession de l'équipe d'Arpinum. Une équipe qui fait bien plaisir à voir et qui a surement achevé de convaincre les sceptiques -s'il y en avait encore- sur l'intérêt des approches agiles.
A un moment, les questions de la salle se sont transformées en débat sur l'agilité, ce qui n'est certes pas forcément facile à gérer pour les orateurs mais témoigne néanmoins de l'intérêt de l'assistance pour le sujet présenté - et c'est quand même le principal, non ?
Leçon à retenir toutefois : les questions, c'est mieux à la fin de la présentation, pas pendant !
Pour la petite histoire, j'ai retrouvé mon voisin de droite du début de matinée, il était cette fois juste derrière moi et a réussi l'exploit d'interrompre les orateurs pour répondre à leur place sur une question posée par une personne de l'assistance. Il y a parfois des baffes qui se perdent.

Bref, une journée comme on aimerait en vivre plus souvent avec des interactions très riches. Un grand merci aux organisateurs pour m'avoir permis de la vivre comme participant et comme orateur. Et à l'an prochain ?

Le 21 octobre prochain, je serai à l'étape toulousaine de l'agile tour (on peut encore s'inscrire) qui aura une tonalité probablement différente en étant plus centrée sur les retours d'expérience de nombreuses entreprises. On verra bien ce que ça donnera. Il y aura surement des choses intéressantes même si le format bordelais correspond plus à mes attentes personnelles.

Pour d'autres retours sur cette journée : Agile Tour Bordeaux sur Twitter

- page 1 de 5