samedi 21 septembre 2013

Jenkins & SVN : Afficher la révision comme numéro de build

Le numéro de build indiqué par défaut lors de la construction dans Jenkins est un numéro qui s'incrémente à chaque construction. Ce numéro - mis à part de nous indiquer à combien de construction nous sommes rendu - n'apporte pas plus d'information.


Ce qui serait utile, par contre, c'est de savoir rapidement à quelle version de source cette construction correspond afin de disposer d'une meilleure traçabilité entre Source SVN -> artefact Jenkins.
Aucun plugin ne permet de le faire actuellement, nous allons voir comment on peut cependant le mettre en place rapidement.

Retour sur les versions de SVN

Dans notre contexte, nous avons plusieurs projets disponibles sur un repository SVN. Chaque projet est donc sur un sous-répertoire depuis la racine du dépot. A chaque commit (peu importe sur quel projet), le numéro de révision du dépôt est incrémenté.
Ce numéro de révision est global : il permet de restituer l'état d'un repository à un révision donnée.
Pour chaque sous répertoire, nous disposons d'un second indicateur : Last Changed Revision qui indique le dernier numéro de révision qui à modifié le répertoire en cours

Nous pouvons récupérer ces informations depuis la ligne de commande en se positionnant sur un répertoire de source précédemment checkoutée :

$ svn info
Path: .
Working Copy Root Path: D:\projets\toto\source\
URL: http:/xxx/usvn/svn/toto/trunk
Repository Root: http://xxx/usvn/svn/toto
Repository UUID: a1ebbc07-6c76-4030-a489-aa0d2fd72fa2
Revision: 11372
Node Kind: directory
Schedule: normal
Last Changed Author: fdupont
Last Changed Rev: 11360
Last Changed Date: 2013-09-11 17:23:54 +0200 (mer., 11 sept. 2013)

Les informations qui nous intéressent apparaissent dans les champs "Revision" et "Last Changed Rev".

Prise en compte dans Jenkins

Pour la prise en compte dans Jenkins, il faudra ajouter le plugin Hudson Groovy builder

Dans la configuration du build, ajouter une Pre steps avec execution de script Groovy "System". Exécuter en tant que script "System" signifie que le script sera exécuté dans la même JVM que Jenkins, ce qui permet d'avoir la main sur les objets Jenkins. C'est ce qui va nous permettre de modifier le nom du build ainsi que sa description.

Les deux lignes suivantes sont les imports des packages jenkins.
  import hudson.model.*
  import hudson.util.*
Récupère l'instance du build courant
  def build = Thread.currentThread().executable
On récupère ensuite le workspace du build courant, c'est à dire le répertoire dans lequel les sources sont chéckoutée. Ce répertoire contient le répertoire .svn qui sera utilisé par la commande svn info.
  def workspace = build.getWorkspace()
En groovy, le moyen le plus simple d'exécuter une commande shell et de récupérer le résultat est de passer par une tâche Ant.
  def ant = new AntBuilder()

  ant.exec(executable: "svn", outputproperty: "output", dir: workspace){
    arg(line: "info")

  }
La sortie est récupérée depuis la variable "outputProperty" puis sert à alimenter la variable svnInfo.
  svnInfo = ant.project.getProperty("output")
On utilise ensuite des expression régulière pour récupérer le numéro de révision ainsi que le LCR (Last Changed Revision.
  def pattern = /Last\s+Changed\s+Rev:\s+(\d+)/
  def matcher = (svnInfo =~ pattern)
  def lcr = "Last changed revivion : <b>" + matcher[0][1] + "</b>"
  
  pattern = /Revision:\s+(\d+)/
  matcher = (svnInfo =~ pattern)
  def rev = "r" + matcher[0][1]
Le nom du build est ensuite modifié avec l'intitulé de la révision et la description est renseignée avec le LCR.
  build.setDisplayName(rev)
  build.setDescription(lcr)

Au complet, ça nous donne :
  import hudson.model.* 
  import hudson.util.*

  def build = Thread.currentThread().executable
  def workspace = build.getWorkspace()
  def ant = new AntBuilder() 

  ant.exec(executable: "svn", outputproperty: "output", dir: workspace){ 
    arg(line: "info") 
  }

  svnInfo = ant.project.getProperty("output")
  def pattern = /Last\s+Changed\s+Rev:\s+(\d+)/ 
  def matcher = (svnInfo =~ pattern)
  def lcr = "Last changed revivion : " + matcher[0][1] + ""

  pattern = /Revision:\s+(\d+)/ 
  matcher = (svnInfo =~ pattern)
  def rev = "r" + matcher[0][1]

  build.setDisplayName(rev)
  build.setDescription(lcr)


Lors de la prochaine construction, depuis la View, on verra bien apparaitre notre numéro de révision


Dans la vue Constructions, le LCR apparait en tant que description :




Note complémentaire : pour les ceux qui utilisent SVN depuis Windows, l'outil en ligne de commande est internationalisé et répondra donc en français. Pour restituer les sorties consoles en anglais, ajouter la variable d'environnement suivante :
  set LC_MESSAGES=en_US
L'article original : http://jayflowers.com/WordPress/?p=258

vendredi 12 avril 2013

Les 10 commandements d'un développeur humble

Les 10 commandements d'un développeur humble,  (en anglais, the 10 commandments of egoless programming) sont apparus dans le livre de Gerald Weinberg : "The Psychology of Computer programming" dont la publication originale date de 1971, mais restent toujours d'actualité !

I. Comprend et accepte que tu feras des erreurs.

II. Tu n'es pas ton code

III. Peu importe combien de Karaté tu connais, quelqu'un d'autre en connaitra toujours plus

IV. Ne ré-écrit jamais le code d'un autre sans consultation

V. Traite les gens qui en connaissent moins que toi avec respect, égard et patience

VI. La seule constante dans le monde est le changement

VII. La seule autorité provient du savoir, pas de la position

VIII. Bat toi pour ce que tu crois, mais accepte la défaite avec dignité.

IX. Ne soit pas "le mec dans son coin"

X. Critique le code et pas les personnes. Soit respectueux envers les personnes, pas envers le code.


A méditer au quotidien....

lundi 28 janvier 2013

5 Bonnes raisons du MDA pour le développement mobile

 
Article co-écrit par Florent Dupont et Lamia Gaouar, qui prépare actuellement un doctorat SIC autour des développements Android et MDA à l'université de Tlemcen.

La démocratisation des plateformes nomades (mobiles et tablettes) poussent les entreprises à proposer toujours plus de services aux utilisateurs. Elles ont, en effet, bien compris tous les enjeux qui se trament derrière les applications mobile : communication améliorée, nouveaux services aux utilisateurs, régie publicitaire, avantage concurrentiel, etc.

Cet engouement pour les plateformes nomades offre de nouvelles perspectives de marché, notamment pour les entreprises éditrices (que ce soient des Mobile Agencies, des Web Agencies ou encore des SSII) qui peuvent proposer leur expertise de développement. Depuis 2011, le marché des ventes de mobile dépasse les ventes de PC et offre donc des perspectives de marché de développement d’applications mobile très importantes.

Ces éditeurs doivent cependant s’adapter aux plateformes de développement mobile qui sont foncièrement différentes de celle des applications Desktop. En effet, ces plateformes imposent des contraintes fortes, les ressources étant limitées : taille d’écran réduite, processeur faible, stockage limité, connexion lente et intermittente, RAM limitée. Toutes ces limitations impliquent une discipline de développement particulière pour que l’expérience utilisateur soit toujours efficace.

Au niveau logiciel, de multiples OS (Android, iOS, BlackBerry, Windows Phone) se disputent le marché de la mobilité. A chaque OS correspond une plateforme de téléchargement d’applications, des outils de développement et un langage de programmation permettant le développement et la distribution des applications :

 


Cette hétérogénéité des outils de développement et des langages, rend difficile le développement d’applications mobile multiplateformes. Elle pousse les développeurs à faire un choix sur la plateforme, tout en assurant la plus grande distribution possible.

Des outils pour aider les développeurs ?

Google a récemment apporté un élément de réponse avec le projet J2ObjC qui permet de convertir du code Java (Android) en code Objective-C (iOS). L’intérêt d’une telle démarche est de pouvoir récupérer le code fonctionnel d’une application Android afin de faciliter la conversion vers la plateforme iOS.
Mais cette approche pose encore de nombreuses questions :
  • Qu’en est-il de la conversion Objective-C vers Java ? Et vers d’autres OS  ?
  • Et plus généralement, comment capitaliser sur le fonctionnel d’une application indépendamment des préoccupations techniques afin d’en faciliter la migration ?  

Une réponse avec le MDA

L’approche MDA a su faire ses preuves pour le développement d’applications d’entreprise et peut également apporter beaucoup pour les applications mobile. Au travers de 5 points, nous allons voir pourquoi et comment l’approche MDA peut nous aider à assurer la pérennité des savoir-faire, le gain de productivité tout en répondant aux problématiques de fragmentation des plateformes mobile.

1. Réduire les problématiques de fragmentation

Chaque OS mobile détient une part du marché, et donc chacun possède sa communauté d’utilisateurs et de développeurs. Cette fragmentation pose un souci pour les entreprises désireuses de toucher un large public car le développement des applications multiplateformes est très coûteux en temps et en argent. Les entreprises se trouvent face à un dilemme :
  • Développer une application de qualité en un temps efficace et limiter sa distribution à une plateforme spécifique. 
  • Développer une application aux fonctionnalités réduites, mais proposée sur plusieurs plateformes et à un large panel d'utilisateurs.
Des solutions hybrides existent comme Cordova (application native construite à partir de vue Web et Html5) ou Flex 4.6 (exécution sous plateforme Flash) et permettent d’assurer du multiplateformes, mais leur prise en charge reste techniquement partielle. En réalité, une application native restera plus adaptée pour plusieurs raisons :
  • L’utilisateur dispose d’un environnement adapté à sa plateforme et à ses spécificités : l’expérience utilisateur reste optimale.
  • Le développeur tire profit de l’architecture spécifique et optimise l’application en fonction de la plateforme.
  • L’application peut évoluer et éventuellement tirer parti des fonctionnalités spécifiques à une plateforme ou OS.

L’approche MDA peut répondre à ces problématiques : décrire les besoins fonctionnels d’une application indépendamment de la plateforme d’exécution, et respecter les spécificités techniques de chaque plateforme. MDA permet de générer le code sans valeur ajoutée (boilerplate code) spécifique à chaque plateforme. On assure ainsi un gain de productivité, même sur des applications natives.

2. Capitaliser sur les concepts proches

Chaque OS mobile utilise son propre langage de programmation et arbore ses propres APIs mais les concepts généraux restent standards et communs. On peut se permettre de capitaliser des concepts communs entre différentes plateformes permettant de modéliser une application de manière générique, citons par exemple :
  • Activité : correspond à une page de l’application, elle est une notion commune à tous les OS. Une application est composée d’une ou de plusieurs activités.
  • Gestion des données de l’application : en séparant le code de l’interface graphique et le code fonctionnel.
  • Vues et actions associées : une vue est un objet graphique par lequel l’utilisateur interagit avec l’application ce qui provoque une action liée à la vue. Nous retrouvons la plupart des vues sur tous les OS mobile : bouton, saisie de texte, label, barre de navigation, bouton radio, case à cocher, etc.
  • Type d’évènements : une application doit prendre en charge certains évènements susceptibles d’apparaitre durant son exécution tels que les appels téléphoniques, les SMS, etc.
  • Applications natives : les applications natives telles que le calendrier, les contacts, les alarmes, le lecteur média sont communs à tous les OS.
L’approche MDA divise la conception de l’application en deux points de vue :
  • Un point de vue "fonctionnel" indépendant des détails liés à la plateforme d’exécution. On définit ce que l’on veut générer (le quoi). Dans cette partie, on modélise des notions abstraites telles que des écrans, boutons, objets métier, DAO, mais en restant indépendant de leur implémentation technique. Modéliser le fonctionnel de l’application assure la pérennité des savoir-faire.
  • Un point de vue "technique" dans lequel sera décrit l’architecture de la plateforme d’exécution. On définit comment on veut le générer (le comment). Dans cette partie, on spécifie comment la notion fonctionnelle doit être générée : quel langage (Objective C, Java), quelle version (Android 4.1 par exemple), quelle implémentation de BDD. Modéliser l’architecture technique assure la prise en compte de la plateforme d’exécution.
L’étape qui suit la description fonctionnelle et technique d’une application est la génération du code source, c’est le rôle du générateur (ex. MIA Studio, Acceleo). Il s’appuie sur le modèle fonctionnel et technique de l’application pour générer du code source que le développeur pourra enrichir manuellement (le traitement algorithmique et les ressources qui ne peuvent pas être déduits du modèle). La modélisation nous assure une pérennisation du savoir fonctionnel. La génération de code assure un gain de temps considérable entrainant un gain de productivité.

3. Elargir l’écosystème mobile

L’écosystème - tout ce qui vit autour d’une plateforme pour en faciliter le développement - existant sous JavaEE/.NET est large, mais sur plateforme mobile, cet écosystème est encore réduit. L’utilisation de librairies tierces dans les applications mobile est limitée par les différents OS pour plusieurs raisons :
  • Une taille d’application importante : l’utilisation massive de librairies est au contraire des bonnes pratiques pour le développement mobile (problématique d’espace mémoire).
  • Corrolaire du point précédent : une taille d’application trop importante peut être un frein à son téléchargement (debit limité et frais des réseaux 3G).
  • Le manque de visibilité des développements des librairies. Alors que les librairies pour applications JEE/.Net sont portées par de grands éditeurs (JBoss, Spring, Microsoft, etc.), les librairies mobile existantes sont quasi-exclusivement développées par des développeurs tiers. Le suivi et la maintenance ne sont donc pas toujours assurés.
  • Les éditeurs Google, Apple, Microsoft gardent la main sur les évolutions des SDK et ne garantissent donc pas la compatibilité des librairies tierces avec les nouvelles versions des plateformes.
Pour assurer la pérennité du code et élargir son périmètre de compatibilité à plusieurs versions, il est donc préférable d’être indépendant au maximum des librairies tierces et d’avoir un code standard au SDK. L'approche MDA réduit le temps de développement en générant du code standard au SDK, en respectant les bonnes pratiques d’architecture et de qualité.

4. Industrialiser le développement

La mise en place d’une approche MDA, conjointement avec les différents composants d’une usine logicielle (construction, Intégration continue, analyse qualimétrique), industrialise le développement et assure une bonne qualité au code.
L’industrialisation avec le MDA nécessite plusieurs éléments clés :
  • La mise en place d’un POC par une équipe d’architectes logiciels. Ce POC servira de base de code attendu pour faciliter la réalisation du générateur.
  • Un code généré ne doit pas être source d’erreurs et doit rester compatible avec les niveaux de qualimétrie logicielle (qualité, architecture).
  • Une formation des développeurs à l’utilisation du DSL et du générateur.
  • Un support technique permettant d’accompagner les développeurs sur les outils afin d’assurer un bon démarrage du projet.
  • Une communauté autour du générateur qui remonte les bugs. L’amélioration en continue du générateur profite aux développements en cours et aux prochains projets.
  • Une capitalisation sur les bonnes pratiques de développement afin de développer des futures applications encore plus rapidement.
Sur le marché, il y a encore peu de développeurs avec des compétences “mobile”. L’industrialisation des développements mobile par l’approche MDA, a encore plus de sens dans ce contexte, car il permet d’avoir un meilleur accompagnement et un meilleur suivi.

5. Réduire le coût de possession

Avec des budgets toujours plus serrés, les entreprises veulent réduire le coût de possession de leurs applications. L’approche MDA, et plus spécifiquement le DSL et le générateur de code ont une grande valeur de capitalisation et de réutilisabilité. Elles permettent ainsi de réduire les coûts de possession, notamment sur l’investissement initial et le coût de maintenance  :
  • Une conception facilitée par un DSL adapté, cadrant les besoins spécifiques aux plateformes mobile. 
  • Un générateur de code disponible “sur étagère” et utilisable rapidement permet de booster le démarrage d’un projet. 
  • Réduction du support technique : le code ou les patterns complexes et qui sont enclins aux erreurs (typiquement liés à la persistance, mapping ORM) sont générés.
  • Un code de qualité suivant les bonnes pratiques assure une meilleure maîtrise et une réduction des coûts de maintenance. 
  • Un processus itératif : l’outillage MDA par amélioration continue va réduire les coûts des projets progressivement au fur et à mesure de son amélioration.
Un OS peut aujourd'hui être leader du marché et demain perdre certains marchés. Un exemple, avec les annonces de Samsung, premier fabricant mondial de smartphones, qui compte  sortir de nouveaux smartphones en 2013 en abandonnant Android pour Tizen. Ou encore à l’image du géant chinois Huawei qui propose son propre OS mobile ou encore plus récemment Firefox avec FirefoxOS.



En conclusion, au lieu d'investir sur la technologie qui abrite une application, mieux vaut investir dans une technique de développement qui permet de capitaliser la fonctionnalité d'une application indépendamment de sa technologie. Une méthode qui intègre l'évolutivité et la pérénité dans son processus de développement comme l'approche MDA.



dimanche 13 janvier 2013

Code trop commenté : signe de mauvaise qualité ?

Les commentaires de certains programmes m'ont toujours surpris : Soit il n'y en a pas, soit il y en a trop ... Je suis toujours surpris par la quantité de commentaire de certains programmes, surtout lorsque ceux ci n'apportent rien et qu'ils polluent la lecture du code. 

En réalité, et au risque d'en faire bondir certains, il est préférable d'avoir peu de commentaires dans du code bien écrit, plutôt que l'inverse.
D'ailleurs, une méthode trop commentée est même peut-être un signe que quelque chose est louche, comme le dit si bien Martin Fowler.
Ne vous inquiétez pas, je ne dis pas que les développeurs ne devraient pas écrire de commentaires. Dans notre analogie olfactive, les commentaires ne sentent pas mauvais ; en fait ils sentent plutôt bon. La raison pour laquelle nous mentionnons les commentaires ici est qu'ils sont souvent utilisés comme déodorant. C'est étonnant de remarquer que souvent, un code généreusement documenté est en fait vraiment mauvais.

Les commentaires nous guident vers du mauvais code qui a toutes les mauvaises odeurs dont nous avons discuté dans le reste de ce chapitre. Notre première action est de supprimer cette "mauvaise odeur" en refactorant. Et dès que nous avons fini, nous nous rendons compte que les commentaires sont superflus.

Si vous avez besoin d'un commentaire qui explique ce qu'un bloc de code fait, essayez d'extraire la méthode. Si la méthode est déjà extraite mais que vous avez toujours besoin d'un commentaire pour expliquer ce qu'elle fait, alors renommer la. Si vous avez besoin de définir quelques règles à propos de l'état du système, introduisez des assertions.

Quand vous sentez le besoin d'écrire un commentaire, essayez d'abord de refactorer le code pour que chaque commentaire devienne superflu. Un bon endroit pour utiliser un commentaire est quand vous ne savez pas quoi faire. En plus de décrire ce qu'il fait, les commentaires indiquent les points sur lesquels vous n'êtes pas sûr. Un commentaire est une bonne place pour dire pourquoi vous avez fait quelquechose. Ce type d'information aide les futurs développeurs qui reprendront votre code, et spécialement ceux qui oublient vite.
Martin Fowler

Avoir un outil de qualimétrie (type Sonar) qui oblige les développeurs de mettre des commentaires Javadoc peut donc être contraignant sur certains aspects car il peut pousser à mettre du commentaire superflu sans aucune valeur ajoutée, car cet outil ne fait qu'une analyse du code source sans intelligence, sans contexte.

Quelques contre-exemples assez problématiques (issus de vrais code source sur de vrais projets !!) sur les accesseurs :

/**
* Accesseur en écriture sur l'attribut Name
* @param newName Nouveau nom à assigner à l'attribut name **/
public String setName(String newName) {
    this.name = name;
}
/**
* Accesseur le lecture sur l'attribut Name
* @return l'attribut Name
*/
public String getName() {
    return this.name;
}

Ou dans certains cas, quand un développeur prend conscience du peu d'intérêt du commentaire mais DOIT respecter les règles imposées par l'outil de qualimétrie (Sonar en l'occurence dans l'exemple suivant) et sort l'astuce du point commenté pour le code soit sans violations !

/**
* .
**/
public int getName() {
    return this.name;
}

En réalité le code des accesseurs est beaucoup plus lisible sans aucun commentaire : 
public void setName(String name) {
    this.name = name;
}

public int getName() {
    return this.name;
} 



Ceci nous amène à plusieurs règles pour l'écriture de bons commentaires :
  1. Privilégiez le pourquoi et non pas le comment. Documentez les classes et les opérations pour décrire leurs effets et leurs objectifs sans référence aux moyens par lesquels ils le font. Le commentaire ne doit pas faire référence aux détails d'implémentation (Cette règle s'applique également en tant que règle de nommage des classes et opérations).
  2. Ne dupliquez pas les commentaires entre les interfaces et les classes d'implémentations. En cas de refactoring, il sera difficile de maintenir une documentation à jour aux différents endroits. Il est préférable de positionner le commentaire sur l'interface et de laisser la classe d'implémentation sans commentaire. 
  3. Privilégiez la concision des commentaires. N'oubliez pas qu'un commentaire est rarement lu, surtout s'il est long. Il est préférable de vérifier automatiquement la validité de paramètres dans le code avec des assertions plutôt que d'écrire dans le commentaire ce qui est attendu.
  4. Privilégiez les conventions de codage pour comprendre l'objectif d'une méthode. Par convention, on sait qu'une méthode commençant par get est un accesseur en lecture. Même chose avec les méthode set qui indique un accesseur en écriture. Il n'est pas nécessaire de ré-expliquer un comportement dont la lecture du code saute aux yeux !
  5. Privilégiez un vocabulaire commun à tous les développeurs pour que chacun puisse appréhender rapidement le sens d'une fonction juste en lisant son nom. En réalité, il est préférable de nommer correctement une méthode plutôt que d'écrire du commentaire pour expliquer ce qu'elle fait. Il peut être utile de définir une liste de mot-clés à utiliser pour que les développeurs s'appuient sur une même convention de codage.
  6. Prenez du recul sur le besoin d'un commentaire. Ne vous forcez pas à écrire un commentaire parce que l'outil de qualimétrie a remonté une violation, ou parce qu'un taux de commentaire minimal n'est pas respecté. Posez vous la question "Est ce que ce commentaire a une valeur ajoutée ?" si la réponse est non, alors supprimer le !  

L'info en plus : Personnaliser cette règle sous Sonar

  • La Javadoc n'est pas requise sur une méthode annoté @Override. Le commentaire sera automatiquement hérité. (Privilégiez cette approche à l'utilisation de inheritDoc qui nécessite un commentaire). N'hésitez donc pas à en tartiner les méthodes déjà commentées dans les interfaces et dans les classes parentes (notamment equals, hashCode, toString, etc.);
  • le paramètre allowMissingPropertyJavadoc de Sonar permet de ne pas remonter d'erreurs pour les getter et setter non commentés.

Pour aller plus loin, je vous conseille les lectures suivantes :

samedi 7 juillet 2012

Retour d'expérience : bonnes pratiques d'une équipe d'architecture logicielle

Je termine une mission d'architecture logicielle dans une cellule Méthodologie de Développement et MDA dans une grande DSI française. Au sein de cette équipe, nous définissons et mettons en place des architectures logicielles pour les projets.
Le travail s'axe autour de plusieurs aspects :
  • Formation et accompagnement des équipes projets sur les phases de conception (modélisation, Design Pattern), développement, déploiement.
  • Conception d'outillage pour la démarche MDA : langage de modélisation interne, outils de modélisation et générateur de code;
  • Réalisation et mise à disposition des outils du poste de développeur.
Le tout dans un contexte de méthodologie agile.
Je voulais vous remonter mon retour d'expérience pour partager les bonnes pratiques qui ont fait le succès de cette approche.

Faciliter le passage de connaissance pour consolider l'équipe

Afin de renforcer l'esprit d'équipe, les membres de l'équipe "tournent" sur le support au développement. Forcément, en pratique, certains auront certaines affinités sur des sujets selon leurs propres expériences (on avait le "specialiste performance", le "specialiste sécurité", etc), mais on essaie toujours de partager cette connaissance.
On consolide l'équipe avec cette approche. En cas d'indisponibilité, chaque membre de l'équipe peut reprendre le travail de l'autre rapidement. On est également plus réactif, car si un membre n'est pas disponible, on ne se retrouve pas bloqué à l'attendre. Mais surtout, chaque membre monte en compétence sur les différents sujet Même chose sur la méthodologie agile : A chaque sprint, le rôle de Scrum master tourne.
Pour faciliter les passages de connaissances entre les membres de l'équipe un blog permet de poster des solutions de certaines problématiques techniques qui pourront servir pour les autres membres plus tard. Lorsque le blog n'est pas suffisant, et que nous avons des besoins d’interaction, nous faisons un point technique "démo/tutoriel" avec le vidéoprojecteur.

Faciliter le passage de connaissance aux équipes projets

"Quand un homme à faim, mieux vaut lui apprendre à pêcher que de lui donner du poisson" disait Confucius.
C'est dans cet état d'esprit que nous faisons le support aux développeurs. Nous privilégions le passage de connaissance afin que les développeurs soient autonomes et montent en compétences, plutôt que de corriger leurs problèmes sans explications.
Ce passage de connaissance se fait de plusieurs manières : Un blog et une FAQ avec des articles expliquants les cas les plus récurrents (mise en place de la sécurité par exemple), du pair-programming avec les développeurs et même des screencasts.

Proximité de l'équipe

L'équipe au complet est localisée dans un même bureau. Quand le Product Owner, le Scrum master et les membres de l'équipe sont dans un même espace de travail, on favorise les échanges et on facilite la communication tous les membres de l'équipe. Les problèmes sont remontés au plus tôt et on sait plus facilement sur quoi travaille chacun de nous.
Pour aller encore plus loin dans l'échange et le suivi, nous avons - en tant que bons agilistes - notre stand-up meeting quotidien (limité à 15 minutes pour l'équipe, attention !), où chacun revient sur ces 3 questions "Qu'ai-je fait hier", "Sur quoi ai-je été bloqué" et "Que fais-je aujourd'hui". En essayant de ne pas s'égarer...
La proximité est également "virtuelle" Nous partageons des outils de travail : boite mail commune à l'équipe, outil de suivi commun à l'équipe.

Capitaliser sur les outils pour développer durablement

Lors de nouveaux besoins des équipes projets, certains outils spécifiques ont été développés. Il a rarement été question d'outillage "jetable". Chaque outil est développé selon les besoins actuels, puis remonté dans le référentiels des outils. Si un nouveau besoin se fait ressentir, alors on fait des évolutions sur l'outil.
Cette approche présente plusieurs intérêts :
- Lors d'un nouveau besoin : on se limite au cas d'utilisation actuel en ne développant que les fonctionnalités utiles au moment T.
- Lors de la réutilisation : on ne repart pas de zéro : on réutilise l'outil existant dans le référentiel
- Lorsque de nouveaux besoins se font ressentir : on fait les évolutions mais seulement sur le nouveau cas d'utilisation, en refactorant si besoin le code existant.
On garde une approche incrémentale, en se focalisant seulement sur les besoins en cours et en ne surdimensionnant pas les outils (on reste agiles).

Appliquer à soi-même les conseils que l'on prodigue aux autres

Nous poussons les équipes projets à avoir une approche TDD et d'intégration continue. Nous appliquons à nous-même ces préconisations. Notre outillage suit une approche TDD et il est placé dans une chaîne d'intégration continue afin de valider au plus tôt les problèmes.
Nous avons mis en place cette approche car nous nous sommes rendu compte que lors d'évolutions ou de corrections de bug sur notre outillage, nous pouvions amener des régressions. Même si nous sommes une équipe d'architectes logiciels, nous sommes avant tout des développeurs et à ce titre, nous devions également suivre les même processus de développement que les projets "métier" afin d'assurer un outillage de qualité.

Se remettre en question pour s'améliorer

Nous mettons un point d'honneur à l'amélioration continue grâce, entre autre, aux rétrospectives de Sprint.
Tout n'est pas parfait et nous l'acceptons. D'ailleurs, je pense que c'est ce qui fait que ça fonctionne bien : accepter que tout n'est pas parfait, permet de s'améliorer. Lors de la rétrospective de Sprint, nous remontons donc tout ce qui ne va pas au niveau organisationnel, humain ou technique et on tente de mettre en place des solutions pour améliorer ces points lors itérations suivantes.
L'autre point d'amélioration continue, ce sont les retours d'expérience auprès des équipes projets. Lorsque les projets sont terminées (ou en phase avancées de développement), nous faisons un point avec le lead developer, le responsable de l'équipe, l'architecte. et nous prenons en  compte les remarques et critiques sur notre outillage, nos formations, notre support. Nous prenons en compte également les idées qui permettraient d'améliorer le travail des développeurs.

En conclusion

Toutes ces bonnes pratiques nous ont permis de rester ouverts sur les développeurs et de nous améliorer en continu et surtout d'éviter le syndrome de la tour d'ivoire.
Peut-être utilisez vous d'autres bonnes pratiques de développement ("Eat your own dog food" par exemple) ou d'agilité (Kanban) ou d'apprentissage (Shu ha ri)
N'hésitez pas à nous remonter vos retours d'expériences en interne ou en mission pour que l'on puisse partager sur ces sujets.

lundi 23 avril 2012

Agilité : Améliorer son planning poker


A Devoxx France, Petra Cross nous a donné sont point de vue sur l'agilité telle qu'elle est utilisée chez Google dans son talk "Day to day software development at Google" pour être efficace et éviter de perdre trop de temps. Je trouve interessant de poster à ce sujet, car nous avons toujours du mal a estimer les user stories de manière abstraite et avons tendance à pendre trop de temps dans la négociation (et s'égarer dans les explications). Petra nous donne des astuces intéressantes pour mieux mettre en place son planning poker.

Comment s’abstraire du temps dans la macro-estimation des user stories ?
L’estimation des stories se fait normalement de manière abstraite. On parle de macro-estimation en point. Je m’explique. L’estimation des stories ne doit pas être faite avec la notion de temps (durée prévue pour la réalisation en jours/homme) mais avec une notion de points sans unité.

Pourquoi cette abstraction ? Car elle permet de mieux estimer une story et éviter les écarts de temps en fin d’itération. En voulant macro-estimer en j*h, on va faire en sorte que la somme des estimations de tâches corresponde avec l'estimation de la story. Or, le résultat est forcément biaisé, car la macro-estimation suit une suite de Fibonacci (1, 2, 3, 5, 8…) et ce qui va induire des décalages dans les estimations qui, elles, ne sont suivent pas cette suite. 

Alors comment bien macro-estimer ?
Il faut pouvoir juger de la complexité d’une story et non pas de son temps de réalisation prévu. L’idée est de définir, avant le début du premier sprint (et donc avant les premières estimations) 2 étalons sur des stories déjà réalisées par l’équipe et dont tous les membres maîtrisent la complexité. Tous les membres de l’équipe doivent se mettre d’accord pour définir ce qu’est :
  • un story A de 2 points
  • un story B de 5 points

par exemple
  • la story « implémentation de page d’information utilisateur » est estimée à 2 points;
  • la story « implémentation du tableau d’affichage des indicateurs » est estimée à 5 points

Avoir un seul étalon de 1 point n’est pas suffisant car il est difficile de savoir ce que représenteront des stories plus grandes. Avoir 2 stories étalons va permettre de mieux estimer car il est plus facile de faire des comparaisons entre plusieurs valeurs.

par exemple
  • Je considère que cette story X est plus simple à réaliser que la story étalon A => alors elle est estimée à 1 point
  • Je considère qu’elle est plus complexe que l'étalon A, mais plus simple que l'étalon B => alors elle est estimée à 3 points.
  • Je considère qu’elle est plus complexe que l'étalon B => Alors elle est estimée à 8 points.

Une fonctionnalité ne doit pas être estimée à plus de 8 points. Si les membres de l'équipe estiment la story comme ayant plus de 8 points alors il faut découper la story en plusieurs moins complexes.

Petra propose également un point de vue intéressant sur l'étape de négociation des valeurs estimées. La négociation entre les membres ne se fait que si les estimations ont un écart important (sur l'échelle de fibonacci). Si l'écart est minime, alors, c'est la majorité qui l'emporte.

Par exemple, sur une équipe avec 3 membres Paul, Bill, John : 
Si une story est estimée à 2 par Paul, 2 par Bill et 3 par John (je note 2-2-3) => l'écart entre l'estimation de John (3) et les estimations de Paul et Bill (2) étant minime, alors on considère l'estimation finale à 2 sans négociation des membres. l'estimation 2 étant majoritaire. 
idem, si on a le cas 3-3-2 => l'estimation sera alors de 3.
Si on a 3-3-8 (ou 1-1-3), alors on négocie car l'écart est important. Mais, pour éviter que la négociation soit trop longue, les membres de l'équipes vont d'abord poser des questions fermées permettant de mieux comprendre le périmètre la story avant de se mettre d'accord sur une estimation finale.

par exemple, "Est-ce que le bouton valider doit être implémenté dans cette story ?", "Doit on prendre en compte les calculs de taux dans cette story ?"

S'il n'y toujours pas consensus à la suite des questions fermées, alors, on pourra envisager des négociations ouvertes.

La prise en compte de points abstraits n'étant pas naturelle  (puisque sans unité) son utilisation ne sera pas forcément efficace dès les premiers sprints. Mais normalement, après 3-4 sprints, tous les membres devraient mieux appréhender son utilisation.

Il ne reste plus qu'à essayer de mettre en place cette solution. Je reste ouvert si vous avez d'autres solutions / façons de faire !