Artisanat du logiciel et méthodes agiles

En français

Agitation sur l'agilité

Fil des billets - Fil des commentaires

Communauté des méthodes agiles, membres éminents et crédibilité

Dans mon dernier billet, j'ai volontairement omis la revue d'une des solutions proposées à l'Architectural Design Challenge de James Shore. Je n'ai pas traité celle de l'auteur lui-même.

La raison ? Elle n'en valait pas la peine. Où plutôt elle devrait être montrée comme exemple de ce qu'il ne faut surtout pas faire. Il n'y a pas besoin d'y consacrer trop de temps pour s'en rendre compte.
James Shore est parti d'un architecture pré-conçue à 3 niveaux où chaque niveau dépend du suivant : UI -> domaine -> persistance. Et ça donne ça : JamesShoreClasses.png

Un vrai sac de noeuds où tout dépend de tout, où les interfaces n'introduisent aucun découplage (à part, à la marge, "PersistanceMechanism"). Le diagramme de séquence pour le scénario principal montre d'ailleurs très bien les incessants aller-retour entre les divers élements : JamesShoreSequence.png

Il faut dire que ces diagrammes sont de moi. Je les ai postés en commentaire du billet de James Shore mais celui-ci n'a pas daigné les commenter. Un commentateur a toutefois tiré la conclusion qui s'impose : This looks almost as bad as I thought ;-) ... To me it seems the "dependency oriented design style" is hindering the solution of such a simple problem.

Tout ça n'est pas très réjouissant mais il y a pire. James Shore présente son approche comme étant "mock-driven" et elle ne l'est pas du tout. Un autre commentateur l'a bien compris : the approach in this post shows internal conflict in trying to stick to pre-conceived designs while trying to use unit tests with mocks to achieve that.
On ne peut pas partir d'une architecture dite "à 3 niveaux" et utiliser une approche dirigée par les mocks. Faire cela, c'est nier l'intérêt principal des mocks qui consiste à découvrir les interactions entre divers composants d'un système en commençant par concevoir l'un d'entre eux.

James Shore annonce en avertissement I'm Not a Mockist mais alors pourquoi s'entêter à présenter une approche qu'il ne maitrise pas ?
Pour apprendre ? Cela serait tout à son honneur mais encore faudrait-il répondre aux commentaires qui remettent les choses dans la bonne voie - ce qui n'a pas du tout été le cas.

Et comme une cerise sur le gateau, un des premiers commentaires à ce billet est de Ron Jeffries : This is good stuff I hope to see the inevitable responses live up to this standard.. Ron Jeffries admet toutefois qu'il ne maitrise pas le sujet des mocks et qu'il cherche à comprendre ce que ça lui apporterait de plus que ce qu'il a déjà. Mais alors pourquoi donne-t-il un avis peu éclairé sur cette solution ?

Je ne sais pas trop que penser de tout ça. Ce billet de James Shore traite de pratiques de développement que je commence, je pense, à bien maitriser et je peux donc voir toute l'incongruité de ce qu'il raconte. Mais qu'en est-il pour les autres sujets ? Comment accorder de la crédibilité à une explication, à un point de vue, venant de personnes qui peuvent, on s'en rend compte, ne connaitre que très imparfaitement ce dont ils parlent avec assurance ?
Je vois là une dérive de "l'agilité-business" où ceux qui sont censés savoir et apporter leurs connaissances peuvent rarement se permettre de montrer leur ignorance sur certains domaines, alors que le courage et l'honnêteté nécessaires à la pratique des méthodes agiles devrait leur dicter la démarche opposée.
Mais c'est un autre (vaste) sujet...

Un switch évolutif en C#

Un billet sur le blog d'Excilys concernant les switchs en java me donne envie de parler un peu de codage en C#.

Tout développeur avec un peu d'expérience sait que les "switch" sont une grande source d'erreurs et une plaie pour la maintenabilité d'un code.
Un switch classique, ça donne quelque chose comme ça :

static class Switch
{
  public static string GetFunctionDescription (string functionName)
  {
    switch (functionName) {
    case "add":
      return "Compute the sum of two numbers";
    case "sub":
      return "Compute the difference of two numbers";
    default:
      throw new ArgumentException ("Unknown function");
    }
  }

  public static int Compute (string functionName, int op1, int op2)
  {
    switch (functionName) {
    case "add":
      return op1 + op2;
    case "sub":
      return op1 - op2;
    default:
      throw new ArgumentException ("Unknown function");
    }
  }
}

Et ça s'utilise comme ça :

Console.WriteLine( Switch.GetFunctionDescription("add") );
Console.WriteLine( "Result={0}", Switch.Compute("add",3,2) );

Dès que l'on veut rajouter un cas, on est presque sûr d'oublier quelque chose.
Alors, le polymorphisme de toute bonne conception orientée objet vient à notre secours et on peut remplacer nos cases par une interface et ses implémentations :

interface Function
{
  string Description { get; }
  int Compute (int op1, int op2);
}

class FunctionAdd : Function
{
  public string Description { get { return "Compute the sum of two numbers"; } }

  public int Compute (int op1, int op2) { return op1 + op2; }
}

class FunctionSub : Function
{
  public string Description { get { return "Compute the difference of two numbers"; } }

  public int Compute (int op1, int op2) { return op1 - op2; }
}

Du coup, on peut se contenter d'un switch unique qui sera bien plus facile à maintenir

static class Switch
{
  public static Function GetFunction (string functionName)
  {
    switch (functionName) {
    case "add":
      return new FunctionAdd();
    case "sub":
      return new FunctionSub();
    default:
      throw new ArgumentException ("Unknown function");
    }
  }
}

Console.WriteLine( Switch.GetFunction("add").Description );
Console.WriteLine( "Result={0}", Switch.GetFunction("add").Compute(3,2) );

Si on est vraiment allergique au mot-clef "switch", on peut aussi utiliser un dictionnaire pour référencer les cas en fonction de leur nom mais ça ne change pas grand chose en termes de maintenabilité. On a autant de classes dérivées que de "case" et on a un point central qui fait l'association entre les valeurs possibles et leur exécuteur.

static class Switch
{
  static Dictionary<string, Function> Functions { get; set; }

  static Switch ()
  {
    Functions = new Dictionary<string, Function> ();
    Functions["add"] = new FunctionAdd ();
    Functions["sub"] = new FunctionSub ();
  }

  public static Function GetFunction (string functionName)
  {
    if (!Functions.ContainsKey (functionName))
      throw new ArgumentException ("Unknown function");
    return Functions[functionName];
  }
}

Mais ce qui serait vraiment intéressant, ce serait d'évacuer complètement la maintenance d'un point central. Pour cela il faudrait pouvoir déclarer la valeur du "case" (dans notre exemple, le nom de la fonction) avec son exécution (dans notre exemple la classe qui implémente la fonction).

.NET offre un concept facile à mettre en oeuvre pour réaliser cela : les attributs.

Ainsi, on déclare un attribut pour nommer nos cas :

class CaseAttribute : Attribute
{
  public string Name { get; private set; }
  public CaseAttribute (string name) { Name = name; }
}

Et on l'utilise pour qualifier chacune de nos implémentations :

[Case("add")]
class FunctionAdd : Function
{
  public string Description { get { return "Compute the sum of two numbers"; } }

  public int Compute (int op1, int op2) { return op1 + op2; }
}

[Case("sub")]
class FunctionSub : Function
{
  public string Description { get { return "Compute the difference of two numbers"; } }

  public int Compute (int op1, int op2) { return op1 - op2; }
}

A partir de là, on peut implémenter un mécanisme générique pour réaliser les switchs, par exemple :

static class Switch<T> where T : class
{
  public static T On (string val)
  {
    var switchSelection = from type in Assembly.GetCallingAssembly ().GetTypes ()
      from attribute in type.GetCustomAttributes (false) as Attribute[]
      let caseAttribute = attribute as CaseAttribute
      where caseAttribute != null && caseAttribute.Name == val
      select type;
    
    if (switchSelection.Count () == 0)
      throw new ArgumentException ("Unknown case");
    
    if (switchSelection.Count () > 1)
      throw new ArgumentException ("Multiple implementations for same case !!!");
    
    return Activator.CreateInstance (switchSelection.First ()) as T;
  }
}

Et l'appel d'un switch reste relativement lisible :

Console.WriteLine( Switch<Function>.On("add").Description );
Console.WriteLine( "Result={0}", Switch<Function>.On("add").Compute(3,2) );

Avec l'implémentation ci-dessus, on est limité à utiliser les cas dans l'assembly où ils sont déclarés mais on pourrait bien sûr imaginer des choses plus évoluées...

La première itération et l'angoisse de la page blanche

Les méthodes agiles, à travers leurs approches itératives et incrémentales, ont pour caractéristique commune de maintenir en permanence (ou presque) un logiciel dans un état "prêt à livrer". Le travail suit donc un rythme très régulier et sans cassure : pas grosse phase de "conception" ou d'"intégration" pour ne citer que les passages les plus délicats de projets menés en mode moins agile.
Cet état "prêt à livrer" requiert toutefois une condition importante : qu'il y ait quelque chose à livrer ! Et c'est typiquement le problème de tout début de vie d'un produit quand s'opère le passage d'un néant à un premier livrable, aussi minimal soit-il.

Pour démarrer un projet, on entendra alors parler de "phase de lancement", ou bien de "sprint 0", ou encore de "phase exploratoire".
Quelle que soit la dénomination, il s'agit de mettre l'équipe (pris au sens le plus large possible) sur des rails pour commencer à travailler en mode incrémental, ce qui implique d'avoir une vision partagée à travers un backlog de produit et un socle technique.

Mais comment procéder lorsque l'on part d'une base de code vierge ? La tentation est grande de définir une architecture a priori au lieu de laisser celle-ci véritablement émerger des besoins. En effet, implémenter la moindre histoire utilisateur à partir de rien nécessite généralement bien plus de code que lorsqu'une architecture est déjà en place.

Et pourtant, Kent Beck, dans Extreme Programming Explained, conseille explicitement de choisir des histoires utilisateurs pour diriger, dès le départ, la construction du système complet :

The first iteration puts the architecture in place. Pick stories for the first iteration that will force you to create "the whole system," even if it is in skeletal form.
Picking stories for subsequent iterations is entirely at the discretion of the customer. The question to ask is, "What is the most valuable thing for us to be working on in this iteration?"

L'utilisation des histoires dès le début présente plusieurs intérêts :

  • les choix techniques sont faits pour répondre à un besoin réel et immédiat et non pas en prévision d'un hypothétique futur.
  • le travail de développement est fluidifié. Il n'y a pas de cassure entre une phase où on fait des choix fondamentaux et une phase où on commence à dérouler l'implémentation d'histoires utilisateur.

Pour pallier à la nécessité d'écrire du code à partir de zéro sans crouler sous les besoins techniques sous-jacents à la moindre histoire, on peut, par exemple, procéder de la façon suivante :

  • le client (ou le directeur de produit selon le nom en vigueur dans la méthode utilisée) liste 4 ou 5 histoires qui seront centrales dans la définition du produit
  • l'équipe découpe ces histoires en éléments de plus fine granularité correspondant chacun à une valeur ajoutée si le reste du système existait déjà. Par exemple, une histoire où "l'utilisateur visualise des résultats d'un calcul utilisant des valeurs présentes dans une base de données" peut être découpée en :
    • le rajout d'un calcul sans se soucier de la présence d'une base de données ou d'un dispositif d'affichage
    • le rajout d'une base de données en supposant que des calculs existent déjà à partir d'une autre source de données
    • le rajout d'une visualisation en supposant que des calculs existent déjà et utilisent un autre dispositif d'affichage
  • l'équipe estime ces élements (planning poker, etc.) et se crée ainsi une base de référence pour ses estimations futures
  • l'équipe démarre l'implémentation et le client commence à étoffer son backlog de produit avec des histoires qui viennent se rajouter sur le système tel qu'il a commencé à être défini

L'éthique de l'artisan du logiciel : proposition de traduction en français

Après le manifeste, voici les principes qui vont avec.

Le texte original en anglais est là : http://groups.google.com/group/software_craftsmanship/web/principles-of-software-craftsmanship.
Il est à l'état de brouillon mais n'en est pas moins intéressant.


L'éthique de l'artisan du logiciel

Nous veillons

Nous considérons qu'il est de notre responsabilité
d'acquérir la confiance des entreprises que nous servons
par conséquent,
nous donnons aux problèmes de nos clients l'importance qu'eux-mêmes y accordent et
nous engageons notre réputation sur la qualité du travail que nous produisons

Nous appliquons

Nous considérons qu'il est de notre responsabilité
d'écrire du code sans défaut, vérifié, lisible, compréhensible et malléable
par conséquent,
nous suivons minutieusement, même sous la pression, les pratiques que nous avons choisi et
nous travaillons nos techniques de manière régulière

Nous apprenons

Nous considérons qu'il est de notre responsabilité
d'améliorer notre savoir faire dans la recherche de la plus grande maitrise
par conséquent,
nous explorons en permanence de nouvelles technologies et
nous lisons et étudions les travaux des autres artisans

Nous partageons

Nous considérons qu'il est de notre responsabilité
de perpétuer l'art du Logiciel
par conséquent,
nous poussons les apprentis à l'acquérir et
nous engageons activement, avec les autres artisans, dialogue et pratique

Manifeste pour l'artisanat du logiciel : proposition de traduction en français

Lors de ma récente présentation au SigmaT, j'ai proposé la traduction en français suivante pour le Software Craftsmanship Manifesto.

Elle n'est certainement pas parfaite mais ça donne au moins une base.
Et, à mon avis, le plus gros problème vient de la traduction de "craftsmanship". Le terme français "artisanat" est chargé de multiples sens qui n'en font pas un choix idéal. Si quelqu'un a mieux à proposer...


Manifeste pour l'artisanat du logiciel

Mettons la barre plus haut

Souhaitant devenir des artisans du logiciel, nous élevons la barre du développement professionnel de logiciel, en le pratiquant et en aidant les autres dans l'apprentissage du savoir faire.
A travers ce travail nous en sommes arrivés à donner de la valeur :

Non seulement au logiciel opérationnel,

mais aussi au logiciel conçu dans les règles de l'art

Non seulement à la réactivité face au changement,

mais aussi à la création permanente de valeur

Non seulement aux individus et à leurs interactions,

mais aussi à une communauté de professionnels

Non seulement à la collaboration avec le client,

mais aussi aux partenariats productifs

Dans notre recherche des premiers éléments, nous avons découvert que les seconds étaient indispensables.

Artisanat du logiciel au SigmaT 14 : les slides

Et quelques liens (en anglais) suite aux questions évoquées après la présentation :

Artisanat du logiciel

craftsmanship_fr.png

Artisanat du logiciel au SigmaT 14

Cela faisait quelque mois que j'avais envie de parler d'artisanat du logiciel ou software craftsmanship en version originale. Ce sera chose faite vendredi prochain, le 18 juin lors du 14ème séminaire SigmaT.
Comme d'habitude, l'entrée est gratuite. Il suffit de s'inscrire en ligne.

Outre l'artisanat du logiciel, il y aura aussi Guillaume Saint Etienne qui parlera de TDD et de BDD, un retour d'expérience Scrum chez Sanofi-Aventis et une nouveauté SigmaT : un débat participatif sur les méthodes agiles.

Voici les points que j'essaierai d'aborder lors de ma présentation "Au delà de l'agilité, l'artisanat du logiciel" :

Agilité on the road again

Comme l'an dernier, l'agilité fait son tour de France et même son tour du monde.

Le 22 octobre, dans une semaine, c'est l'étape toulousaine. J'aurai le plaisir d'y animer un atelier sur le développement logiciel piloté par les tests. Il y aura bien évidemment de nombreuses interventions comme en atteste le programme de la journée.

Experienced Extreme Programmer

Quelqu'un qui prétend s'y connaitre un peu en méthodes agiles sans logo "Certified ScrumMaster" sur son blog, ça ne fait pas vraiment sérieux. Mais comme cette "certification" ScrumMaster ce n'est pas vraiment très sérieux non plus, il fallait trouver autre chose.

Emmanuel Chenu a la solution : sa proposition de logo autoproclamé "Experienced Extreme Programmer" est tout à fait ce qu'il me fallait.

XXP.png

Pas de taches dans les sprints

Une fois n'est pas coutume : je suis d'accord avec Jeff Sutherland :

The best teams I work with burn down story points. They only burn down when a story is done.

Quand on arrive à travailler avec demandes du client suffisamment élémentaires[1] et ayant une cohérence intrinsèque[2], il n'y a plus de raison pour gérer un sprint en planifiant des taches.

D'ailleurs, un burndown de sprint en taches est une véritable hypocrisie. Si un sprint ne comporte qu'une seule histoire utilisateur et que ce sprint est planifié en 10 taches, le burndown qui montre les 9 premières taches terminées n'apporte aucune valeur. Si la 10ème tache est nécessaire à la finition de l'histoire utilisateur, l'équipe n'a produit aucune valeur tant que cette dernière tache n'est pas terminée.

Notes

[1] c'est à dire ayant des tailles leur permettant de rentrer à plusieurs dans un sprint

[2] ce qui signifie que leur valeur ajoutée ne dépend que d'elle même et de l'existant

J'ai enfin ma certification de spécialiste en méthodes agiles

Il m'est arrivé de dire du mal des certifications pour tout ce qui concerne le développement logiciel. Je reconnais que mes reproches sur le manque de sérieux d'un diplôme obtenu en 2 jours intenses n'étaient pas toujours justifiés.

Après avoir longtemps hésité, j'ai fini par franchir le pas et me voilà désormais "Certified Agile Software Specialist". Si, comme moi, vous voulez bénéficier d'une certification reconnue internationalement et recommandée par les plus éminents membres de la communauté agile, n'hésitez pas : http://www.agilecertificationnow.com/.

Les deux sortes de TDD

Le Développement Dirigé par les Tests est une des pratiques emblématiques d'Extreme Programming. A ce titre, elle est devenue un passage presque obligé pour quiconque envisage d'évoluer vers les méthodes agiles.

Le problème avec les pratiques disruptives, c'est que, lorsqu'elles viennent s'insérer dans un contexte existant, leur mise en oeuvre peut souffrir d'approximations. Les méthodes agiles font face, bien plus que d'autres, à ce genre de mésaventures : la faiblesse dans la prise en compte des pratiques d'ingénierie est une réalité.

Société des Innovateurs pour la Généralisation de Méthodes Agiles de Toulouse

Lu sur le Journal Officiel


No d'annonce : 279
Paru le : 28/02/2009

Association : SOCIETE DES INNOVATEURS POUR LA GENERALISATION DES METHODES AGILES DE TOULOUSE (S.I.G.M.A.T.).

Identification WALDEC : W313011297

No de parution : 20090009
Département (Région) : Haute-Garonne (Midi Pyrénées)

Lieu parution : Déclaration à la préfecture de la Haute-Garonne.
Type d'annonce : ASSOCIATION/CREATION

Déclaration à la préfecture de la Haute-Garonne. SOCIETE DES INNOVATEURS POUR LA GENERALISATION DES METHODES AGILES DE TOULOUSE (S.I.G.M.A.T.).
Objet : fédérer et faire connaître les acteur de l’agilité de Toulouse et sa région, informer et initier aux méthodes agiles les personnes désireures de les découvrir, favoriser l’adoption des méthodes agiles dans le tissu économique régional.
Siège social : Hoegaarden Café - La Chunga, 52, route de Narbone, 31400 Toulouse.
Courriel : contact (at) sigmat.fr.
Site Internet : http://www.sigmat.fr.
Date de la déclaration : 9 février 2009.


Ca y est. L'association SIGMAT existe désormais officiellement !
Les inscriptions sont déjà ouvertes. On peut même s'inscrire en ligne.

Et bien sûr les séminaires trimestriels continuent. Le prochain, c'est demain, vendredi 27 mars, et il reste encore quelques places.

Architecte logiciel et agilité : c'est pas gagné...

Offre d'emploi Architecte logiciel

Au sein d'une équipe, vous êtes en charge de l'architecture technique du Pôle Système d'Information de notre client. Vous assurez la définition des recommandations et bonnes pratiques architecturales et de développement en environnement Microsoft, spécialisé .net. Vous mettez en place les nouveaux outillages de développement grâce à votre expertise (intégration continue, tests) avec une sensibilité pour les méthodes agiles. Vous étudiez et qualifiez l'introduction de nouveaux produits et frameworks au sein du système d'information de notre client.

Il n'y a pas beaucoup d'offres d'emploi qui mentionnent explicitement les méthodes agiles mais quand on en voit comme celle-là, on se dit que, finalement, ce n'est pas plus mal.

L'oryzus n'est toujours pas en voie d'apparition dans les ressources humaines.

Allo ? C'est pour un sondage !

Denis Dollfus, avec qui j'ai eu le plaisir de travailler il y a quelques années chez Reuters, lance une enquête sur l'état d'agilité des projets de développement logiciel en France.

J'encourage tous ceux qui font du développement logiciel à y répondre, même s'ils n'ont jamais entendu parler "d'agilité".
En fait, l'info qui serait intéressante c'est la comparaison entre les résultats obtenus au test et le résultat attendus par les intéressés.

En ce qui me concerne, pas de surprise. Je savais que les questions 18 et 24 m'empêcheraient d'atteindre le 100%

enquetedenis.png

Ceux qui ont réussi à atteindre le point (0,0), je les soupçonne d'avoir joué à chercher la réponse "qu'il ne faut pas donner". Quant à ceux qui dépasssent les 80% en ingénierie mais restent à zéro en management, je serais très curieux de voir comment ils fonctionnent...

Videos de Noël

Deux videos du dernier SigmaT, le 8ème du nom, sont en ligne. Celle de Claude Aubry n'est pas encore disponible car il est AFK.

Il y a donc celle de Pascal Roques qui nous a parlé de modélisation agile et que j'ai vraiment apprécié. Surtout quand elle permet de mettre en avant une idée toute simple : l'activité de modélisation en elle-même est au moins aussi importante que le résultat car elle permet à l'équipe de communiquer et de se forger une vision partagée.

Retour d'expérience

Le prochain SigmaT aura lieu le vendredi 12 décembre à 16h00. J'y présenterai un retour d'expérience sur l'utilisation de Scrum chez Varian Medical Systems (dont j'avais évoqué les prémisses il y a fort longtemps).

Je pense avoir quelques trucs intéressants à raconter mais je préfère prévenir que cela risque de ne pas être aussi passionnant que le retour d'expérience XP chez Igeoss. Je viens d'ailleurs de mettre en ligne la prestation de David Desmarest que j'avais filmée lors de l'Agile Tour.

Les autres interventions filmées le 16 octobre ne sont malheureusement pas encore disponibles pour des raisons techniques (mon camescope m'a laché avant que je puisse les récupérer).

Agilité, modélisation et méta-programmation

Je ne sais pas si c'est dû au cycle lunaire ou à quelque chose du même genre mais j'observe une floraison de billets "polémiques" sur les blogs traitant de méthodes agiles. Là, il s'agit de l'éternelle méfiance des agilistes envers les phases trop grosses de modélisation (le Big Design Up Front comme on dit) et, par extension, envers les approches de "développement piloté par les modèles".

Emmanuel Chenu écrit 2 billets pour réagir à un article de "Programmez!" et confronter l'agilité avec le pilotage par les modèles. Le touilleur express en rajoute une couche sur les promesses de maintenance facilitée par ces approches.

De bien belles perspectives pour les consultants en méthodes agiles

Ce n'est pas moi qui le dit, c'est James Shore dans son dernier billet. "Rescuing Scrum teams keeps me in business" avance même un de ses collègues.

La raison ? L'engouement pour Scrum a fait que nombre d'équipes insuffisamment préparées se retrouvent dans des situation inextricables de dette technique. Ils ont naïvement cru que l'on pouvait tirer bénéfice d'une gestion de projet agile sans en payer le prix.

- page 1 de 3