<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:media="http://search.yahoo.com/mrss/"
> <channel><title>Blog Xebia France &#187; Guillaume Bodet</title> <atom:link href="http://blog.xebia.fr/author/gbodet/feed/" rel="self" type="application/rss+xml" /><link>http://blog.xebia.fr</link> <description>J2EE, Agilité et SOA</description> <lastBuildDate>Wed, 08 Feb 2012 09:23:16 +0000</lastBuildDate> <language>fr</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <copyright>CC BY-NC-ND 2.0 http://creativecommons.org/licenses/by-nc-nd/2.0/fr/</copyright> <managingEditor>blog-france@xebia.com (Xebia France)</managingEditor> <webMaster>blog-france@xebia.com (Xebia France)</webMaster> <ttl>1440</ttl> <image> <url>http://blog.xebia.fr/videos/xebia-podcast.png</url><title>Blog Xebia France</title><link>http://blog.xebia.fr</link> <width>144</width> <height>144</height> </image> <itunes:new-feed-url>http://blog.xebia.fr/feed/podcast/</itunes:new-feed-url> <itunes:subtitle>Les podcasts de Xebia France vous permettent de suivre l&#039;actualité autour de Java, de l&#039;agilité, des technologies Web et bien d&#039;autres. Xebia France est une entreprise spécialisée dans les technologies Java et JEE en environnement agi[...]</itunes:subtitle> <itunes:summary>Les podcasts de Xebia France vous permettent de suivre l&#039;actualité autour de Java, de l&#039;agilité, des technologies Web et bien d&#039;autres. Xebia France est une entreprise spécialisée dans les technologies Java et JEE en environnement agile.</itunes:summary> <itunes:keywords>Xebia, Java, JEE, SOA, Agile, Méthodes, Agiles</itunes:keywords> <itunes:category text="Technology" /> <itunes:category text="Technology"> <itunes:category text="Software How-To" /> </itunes:category> <itunes:category text="Technology"> <itunes:category text="Tech News" /> </itunes:category> <itunes:author>Xebia France</itunes:author> <itunes:owner> <itunes:name>Xebia France</itunes:name> <itunes:email>blog-france@xebia.com</itunes:email> </itunes:owner> <itunes:block>no</itunes:block> <itunes:explicit>no</itunes:explicit> <itunes:image href="http://blog.xebia.fr/videos/xebia-podcast.png" /> <item><title>Architecture agile</title><link>http://blog.xebia.fr/2009/10/08/architecture-agile/</link> <comments>http://blog.xebia.fr/2009/10/08/architecture-agile/#comments</comments> <pubDate>Thu, 08 Oct 2009 15:07:45 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <category><![CDATA[ADDM]]></category> <category><![CDATA[Architecture]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=2824</guid> <description><![CDATA[Les méthodes agiles articulent le développement autour d&#8217;équipes dotées d&#8217;une grande autonomie technique – elles comprennent typiquement chacune au moins un architecte ou développeur très expérimenté, susceptible de structurer les choix de conception (nous avons dessiné le profil de cet architecte agile dans un article paru il y a quelques mois). Cette approche décentralisée des [...]]]></description> <content:encoded><![CDATA[<p>Les méthodes agiles articulent le développement autour d&#8217;équipes dotées d&#8217;une grande autonomie technique – elles comprennent typiquement chacune au moins un architecte ou développeur très expérimenté, susceptible de structurer les choix de conception (nous avons dessiné le profil de cet architecte agile dans <a
href="http://blog.xebia.fr/2008/01/29/un-nouveau-type-darchitecte-larchitecte-agile/">un article paru il y a quelques mois</a>). Cette approche décentralisée des choix d&#8217;implémentation conduit naturellement à une interrogation : comment, dans ces conditions, garantir la consistance globale de l&#8217;architecture du système ?</p><p>Les méthodes agiles à proprement parler ne fournissent pas de solution clé en main dans ce domaine. C&#8217;est donc au travers du système de valeurs et des retours d&#8217;expérience que l&#8217;on cherchera à répondre à cette question.</p><p>Le premier élément de réponse provient de l&#8217;une des pratiques issues de l&#8217;eXtreme Programming et nommée la <em>métaphore</em>. Une métaphore est une abstraction de niveau élevé destinée à décrire les principes d&#8217;architecture mis en oeuvre dans un système ou un sous-système. Difficile à mettre en forme, le principe de métaphore se traduit souvent par un bref dossier d&#8217;architecture – 10 pages maximum – que chaque équipe est chargée de maintenir et de publier (généralement dans un wiki).<br
/> Un très bon exemple illustrant ce principe de la métaphore a été récemment fourni par l&#8217;équipe Chrome de Google, qui a publié sa métaphore sous la forme d&#8217;<a
href="http://www.google.com/googlebooks/chrome/index.html">une BD de 38 pages</a>. Y sont expliqués la vision du produit et les principes architecturaux qui guident sa mise en oeuvre, ainsi que les raisons des choix réalisés.</p><p>La seconde réponse à la question de l&#8217;architecture est dérivée d&#8217;une pratique d&#8217;ingénierie héritée du Lean Manufacturing, et que l&#8217;on retrouve dans la plupart des méthodologies, agiles ou non : les standards de développement.</p><p>Les systèmes organiques mis en place par certains acteurs majeurs du Web fonctionnent sur ce principe : une myriade d&#8217;équipes de petite taille sont chargées de développer des services ou composants fortement intégrés. Chaque équipe inclut un technicien chevronné qui prend le rôle de « <em>Architecture Owner</em> ». Elle conservent une totale autonomie technique et la maîtrise de leur cycle de vie mais sont soumises à un ensemble de règles qui régissent la façon dont ces composants sont interfacés avec le reste du système.</p><p>Ces règles couvrent, sans exhaustivité :</p><ul><li>l&#8217;exploitabilité (socle technique pris en charge par les équipes d&#8217;exploitation)</li><li>la supervision (indicateurs, alertes, traces, journaux, etc.)</li><li>l&#8217;assemblage (afin d&#8217;automatiser les déploiements)</li><li>la qualité de service (charge, temps de réponse, sécurité, etc.)</li><li>l&#8217;interopérabilité (protocoles et paradigmes d&#8217;échange, modalités d&#8217;intégration, etc.)</li></ul><p>Ces règles sont mises au point par le collège des architectes (<em>architecture owners</em>) et consolidées par un « <em>Chief Architect</em> » dont le rôle est de les diffuser et d&#8217;en garantir la consistance. Des ateliers sont régulièrement organisés, réunissant les architectes des différents produits, afin d&#8217;échanger sur les solutions aux problématiques transverses qui peuvent se poser.</p><p>Au besoin, certains concepts d&#8217;architecture <strong><em>éprouvés</em></strong> peuvent être encapsulés dans des composants partagés. On peut, par exemple, mettre à disposition des équipes une API de persistance qui encapsule les stratégies de partitionnement des bases de données et la gestion transactionnelle. Une autre API prendra en charge les paradigmes d&#8217;échange (essentiellement asynchrone) mis en oeuvre dans l&#8217;architecture. Ces développements sont idéalement pris en charge par des équipes <em>ad hoc</em>, et placés sous la responsabilité collective. Si le contexte l&#8217;exige, on peut constituer une équipe dédiée (cf. un peu plus bas).</p><p>Notons que cette approche n&#8217;est envisageable que si l&#8217;architecture globale est fortement modulaire.</p><p>Une autre approche possible est mise en place sur certains projets agiles de grande taille. Cette solution consiste, au sein d&#8217;un projet nécessitant plusieurs équipes, à spécialiser une équipe dans les aspects architecturaux (on parle d&#8217; « Architecture Team », en complément de « Feature Teams » chargées de développer les fonctionnalités du produit). C&#8217;est une telle organisation que nous vous avons présentée dans <a
href="http://blog.xebia.com/tag/prorail/">ce retour d&#8217;expérience</a>. Sur des projets de très grande taille, d&#8217;autres équipes spécialisées peuvent émerger : intégration du système, équipe de tests dédiée, etc.</p><p>Quelle que soit la structure choisie, on retiendra un certain nombre de principes, exprimés par Scott Ambler (Practice Leader Agile Development chez IBM Rational) dans <a
href="http://www.agilejournal.com/content/view/146/">un article parut en 2006 dans le Agile Journal</a> :<ul><li><strong>Modéliser à plusieurs</strong> – l&#8217;architecture et la modélisation devraient être réalisées en groupe, afin de bénéficier de l&#8217;expérience de chacun et de consolider une vision commune, une culture collective</li><li><strong>Se focaliser sur la collaboration plutôt que sur la documentation</strong> – un architecte agile est un membre actif des équipes de développement, et non un simple producteur de documents à destination des dites équipes ; cela ne signifie pas qu&#8217;il ne faut pas documenter, mais la documentation doit être vue comme un effort secondaire</li><li><strong>Prouver par le code</strong> – le prototypage doit être systématisé afin de lever les risques au plus tôt</li><li><strong>Rester simple</strong> – une des pierres angulaire du développement agile : le modèle et l&#8217;architecture n&#8217;ont besoin de satisfaire que les besoins identifiés</li><li><strong>Utiliser les outils les plus simples</strong> – bien souvent, un simple tableau et quelques marqueurs suffisent</li><li><strong>Adresser les grandes problématiques très tôt</strong> – les paradigmes d&#8217;architecture doivent être identifiés dès les phases initiales du projet, sous la forme d&#8217;une vision (ou d&#8217;une métaphore, pour reprendre la terminologie XP) ; à l&#8217;échelle du SI, cela peut se traduire par un plan d&#8217;urbanisme de très haut niveau, assorti de règles d&#8217;intégration de type SOA (mise en place de services HTTP, mode de communication prioritairement asynchrone, politiques de gestion de versions et d&#8217;adressage, modalités d&#8217;intégration des IHM, etc.)</li><li><strong>Penser aux détails « just-in-time »</strong> &#8211; les détails du modèle et de l&#8217;architecture sont élaborés le plus tard possible par les équipes de développement ; au même titre que le développement, la conception est une activité continue</li><li><strong>Permettre à l&#8217;architecture d&#8217;émerger avec le temps</strong> – même si une vision est conçue au départ, les détail émergerons au rythme des évolutions du système</li><li><strong>Voyager léger</strong> – ne pas écrire 50 pages quand 5 suffisent ; ne pas écrire 5 pages quand un diagramme suffit ; ne pas faire un diagramme si une métaphore suffit.</li><li><strong>Maintenir quelques diagrammes de haut niveau</strong> – voyager léger ne signifie pas que toute documentation disparaît ; quelques diagrammes permettant de naviguer dans l&#8217;architecture sont utiles</li><li><strong>Rester flexible</strong> – le type de diagramme de haut niveau dépend du système et du contexte ; ils ne devraient pas faire l&#8217;objet d&#8217;une règle rigide</li><li><strong>Publier les modèles d&#8217;architecture</strong> – ils doivent être accessibles aux membres de l&#8217;équipe et à tous ceux qui souhaitent les consulter</li><li>Piloter l&#8217;architecture par les besoins</li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/10/08/architecture-agile/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Teamicide offshore</title><link>http://blog.xebia.fr/2009/09/08/teamicide-offshore/</link> <comments>http://blog.xebia.fr/2009/09/08/teamicide-offshore/#comments</comments> <pubDate>Tue, 08 Sep 2009 06:00:08 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <category><![CDATA[ADDM]]></category> <category><![CDATA[offshore]]></category> <category><![CDATA[projet]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=2771</guid> <description><![CDATA[Certains d&#8217;entre vous connaissent probablement le phénomène du teamicide, décrit par Tom de Marco et Timothy Lister dans le fameux (et indispensable) Peopleware. Le teamicide, c&#8217;est un ensemble de pratiques managériales dont la conséquence directe et inéluctable est la destruction définitive de tout esprit d&#8217;équipe au sein des personnels concernés. Souvent pratiqué par inadvertance, le [...]]]></description> <content:encoded><![CDATA[<p>Certains d&#8217;entre vous connaissent probablement le phénomène du <em>teamicide</em>, décrit par Tom de Marco et Timothy Lister dans le fameux <em>(et indispensable)</em> <a
href="http://www.amazon.fr/Peopleware-Productive-Projects-Teams-Second/dp/0932633439">Peopleware</a>. Le teamicide, c&#8217;est un ensemble de pratiques managériales dont la conséquence directe et inéluctable est la destruction définitive de tout esprit d&#8217;équipe au sein des personnels concernés. Souvent pratiqué par inadvertance, le teamicide est particulièrement fréquent dans les projets informatiques, avec des résultats souvent désastreux pour ces projets – et une expérience navrante pour ceux qui y participent et chez qui les symptômes oscillent généralement entre dépression nerveuse et indifférence cynique.</p><p>Rappelons rapidement les principales techniques de teamicide décrites dans Peopleware :</p><ul><li><strong>Le management défensif</strong> – résultat direct d&#8217;une défiance irréfléchie envers l&#8217;équipe, et qui se manifeste sous diverses formes plus ou moins spectaculaires, mais toujours avec le même objectif : réduire autant que possible les degrés de liberté des membres de l&#8217;équipe.</li><li><strong>La bureaucratie</strong>, qui, dans le développement logiciel, prend souvent la forme d&#8217;une méthodologie formelle impliquant un grand nombre de documents d&#8217;étape dont l&#8217;intérêt douteux n&#8217;en entame pas moins le caractère sacré. Dans les organisations les plus avancées dans le domaine, on observe souvent une cellule spéciale qui agit en tant que police de la Méthode et vérifie scrupuleusement qu&#8217;aucune équipe n&#8217;a enfreint les tables de la Loi. Cette approche permet de cumuler bureaucratie et management défensif.</li><li>L<strong>a séparation physique des individus</strong>, dont on comprend sans peine qu&#8217;elle réduit mécaniquement les relations interpersonnelles entre eux.</li><li><strong>La fragmentation du temps</strong> – demander aux gens de travailler à temps partiel sur plusieurs projets simultanément est l&#8217;une de ces recettes magiques qui, outre qu&#8217;elle réduit fortement l&#8217;efficacité des individus, interdit à coup sûr l&#8217;émergence du moindre esprit d&#8217;équipe <em>(quelle équipe, au fait ?)</em>.</li><li><strong>La réduction de la qualité</strong>, qui est une technique plus subtile mais non moins efficace et populaire de teamicide. Il n&#8217;est tout bonnement pas imaginable qu&#8217;une équipe émerge formée d&#8217;individus honteux de leur travail&nbsp;&#8230;</li><li><strong>Les délais arbitraires et intenables</strong>, qu&#8217;un nombre encore impressionnant de cadres s&#8217;acharnent à considérer comme un moyen astucieux de conserver une équipe sous pression. Mettre d&#8217;emblée une équipe en situation d&#8217;échec, en lui fixant des objectifs qu&#8217;elle n&#8217;a aucune chance d&#8217;atteindre, est pourtant le plus sûr moyen de voir s&#8217;évaporer toute trace de motivation, tant collective qu&#8217;individuelle&nbsp;&#8230;</li></ul><p>Fort de ces quelques indices, on comprend aisément que le développement offshore est un terrain spontanément très propice au teamicide. Tellement propice au demeurant que la plupart des organisations offshore baissent d&#8217;emblée les bras et ne cherchent même pas à construire des équipes – elles se contentent d&#8217;agréger des jours-homme au meilleur coût dans l&#8217;espoir souvent déçu que cette masse d&#8217;effort pourra être canalisée vers un résultat tangible. Elles utilisent pour cela des techniques de management qui pour la plupart finissent par achopper, précisément parce qu&#8217;elles sont de nature teamicidaires et que l&#8217;on n&#8217;échappe jamais vraiment à l&#8217;impératif de constituer d&#8217;authentiques équipes pour réussir un projet.</p><p>Depuis plus de trois ans maintenant, Xebia mène des projets agiles distribués, grâce à des équipes transcontinentales dont une partie des membres est localisée à Gurgaon, dans la banlieue de Delhi. Rappelons que la construction d&#8217;équipes de petite taille et fortement autonomes est une condition <em>sine qua non</em> de succès dans un projet agile, fût-il mené en offshore. Tout l&#8217;enjeu de l&#8217;approche <a
href="http://www.xebia.fr/publications/développement-offshore-distribué-en-méthodes-agiles">ADDM (Agile Distributed Delivery Model)</a> est donc précisément de parvenir à constituer de véritables équipes dont les membres sont distants de 6000 km les uns des autres et issus de substrats culturels radicalement différents.</p><p>Cet impératif nous a permis de découvrir, parfois dans la douleur, tout un jeu de techniques teamicidaires inédites. Attention : l&#8217;usage d&#8217;une ou plusieurs de ces techniques constitue le meilleur moyen d&#8217;échouer rapidement dans un projet agile distribué. En voici les 10 principales,  :</p><ol><li>Impliquer l&#8217;équipe offshore après quelques sprints, une fois que l&#8217;équipe locale a bien compris les enjeux du projet, réalisé les principaux choix techniques et élaboré une road-map</li><li>Une fois l&#8217;équipe offshore intégrée, continuer de prendre localement les principales décisions en matières d&#8217;architecture et de conception. Communiquer fréquemment sur l&#8217;incapacité de l&#8217;équipe offshore à bien comprendre ces choix, et sur les erreurs qui en découlent.</li><li>Attribuer à l&#8217;équipe offshore tous les problèmes du projet, fussent-ils dus à des exigences floues, à de la dette technique ou encore à des choix technologiques erronés. Vous serez surpris de constater à quel point il est aisé, aux yeux de vos commanditaires, de faire porter le chapeau à l&#8217;équipe distante.</li><li>Rester condescendant lors des rétrospectives, sans jamais donner de feedback honnête à l&#8217;équipe offshore. Lui assurer systématiquement que son travail est excellent, quelle qu&#8217;en soit la réalité.</li><li>Ne jamais colocaliser toute l&#8217;équipe et maintenir l&#8217;équipe offshore à distance du Product Owner, des utilisateurs, et plus généralement de toutes les parties prenantes du projet. Invoquer le coût du voyage permet très aisément de convaincre le management du bien fondé de cette mesure.</li><li>Si malgré tout une période de colocalisation est organisée, s&#8217;assurer que les développeurs offshore ne programment jamais en binôme avec leurs pairs locaux. Si possible, placer les premiers dans un bureau distinct.</li><li>Confier à l&#8217;équipe offshore les tâches dont personne d&#8217;autre ne veut, et réserver les user stories les plus stimulantes pour l&#8217;équipe locale.</li><li>Remanier le code durant le weekend, ou en l&#8217;absence de l&#8217;équipe offshore <em>(l&#8217;après-midi, si ce sont des Indiens)</em>, en se gardant de l&#8217;informer sur ce refactoring.</li><li>Ré-écrire le code produit par l&#8217;équipe offshore, sans communiquer avec elle sur les raisons de cette mesure. En complément, faire en sorte que le management soit informé du retard pris par le projet en raison de cette ré-écriture.</li><li>Ne jamais permettre à l&#8217;équipe offshore de corriger les problèmes qu&#8217;elle a elle-même introduits.</li></ol> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/09/08/teamicide-offshore/feed/</wfw:commentRss> <slash:comments>13</slash:comments> </item> <item><title>Pourquoi les projets agiles ne peuvent pas (vraiment) être menés au forfait</title><link>http://blog.xebia.fr/2009/02/04/pourquoi-les-projets-agiles-ne-peuvent-pas-vraiment-etre-menes-au-forfait/</link> <comments>http://blog.xebia.fr/2009/02/04/pourquoi-les-projets-agiles-ne-peuvent-pas-vraiment-etre-menes-au-forfait/#comments</comments> <pubDate>Wed, 04 Feb 2009 15:00:55 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <category><![CDATA[Contrats]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/?p=1423</guid> <description><![CDATA[En matière de sous-traitance du développement logiciel, la pratique contractuelle la plus fréquente est celle dite du projet au forfait. La notion de forfait n&#8217;a, en principe, pas de rapport avec le processus de développement ou les pratiques d&#8217;ingénierie utilisée dans la réalisation du projet. Il s&#8217;agit simplement, dans l&#8217;esprit des contractants, de fixer les [...]]]></description> <content:encoded><![CDATA[<p>En matière de sous-traitance du développement logiciel, la pratique contractuelle la plus fréquente est celle dite du projet au forfait. La notion de forfait n&#8217;a, en principe, pas de rapport avec le processus de développement ou les pratiques d&#8217;ingénierie utilisée dans la réalisation du projet. Il s&#8217;agit simplement, dans l&#8217;esprit des contractants, de fixer les contours exacts de leur relation commerciale, et de définir leurs obligations mutuelles – en terme de coûts, de délais, de mode de paiement et de livraison. Dans un État de droit, et pour autant qu&#8217;elles ne soient pas abusives, ces dispositions contractuelles ont force de loi, et protègent efficacement les parties prenantes.</p><p>A bien y regarder cependant la neutralité du forfait vis à vis du processus de développement est moins évidente. Conçu historiquement pour satisfaire aux exigences de mise en concurrence des fournisseurs du Département de la Défense américain, le contrat au forfait est né du même substrat que le processus de développement en cascade  &#8211; initialement décrit en 1970 par Winston W. Royce dans <em><a
href="http://www.cs.umd.edu/class/spring2003/cmsc838p/Process/waterfall.pdf">Managing the developpement of large software systems</a></em>.</p><p>Ce processus de développement est aujourd&#8217;hui fortement remis en question, sous le constat empirique de son échec relatif, et sous l&#8217;impulsion des méthodes agiles. Je pense quant à moi que la &laquo;&nbsp;cascade&nbsp;&raquo; sera perçue dans quelques années comme l&#8217;aveuglement juvénile d&#8217;une industrie encore adolescente, à la recherche de son identité.</p><p>La question qui nous intéresse ici est de savoir si le projet au forfait survivra à la cascade. Autrement dit s&#8217;il est possible de mener au forfait un projet agile sous-traité. Certains le pensent, et certains intégrateurs proposent au demeurant de tels contrats. J&#8217;entends quant à moi démontrer ici que l&#8217;agilité et le forfait reposent sur des logiques financières radicalement antinomiques, qui les rendent difficilement conciliables.</p><p>Un petit tour du côté de l&#8217;étymologie devrait alerter les adeptes du forfait. Forfait vient du vieux français <em>fors faire</em> qui signifie&#8230; <em>faire du mal</em> !</p><p>Dans un contrat au forfait, le client définit ce qu&#8217;il souhaite sous la forme d&#8217;un cahier des charges. En retour, le fournisseur doit s&#8217;engage à livrer ce qui est décrit pour un coût et dans un délai fixes – les deux faisant l&#8217;objet d&#8217;une négociation initiale ou d&#8217;une mise en concurrence.</p><p>Ce contrat n&#8217;est pas franchement équitable : il est conçu pour protéger le client et fait porter très fortement le risque sur le fournisseur, qui doit s&#8217;engager sur un délai, sur un coût et sur un périmètre (fixé par le cahier de charges). L&#8217;efficacité réelle de cette protection reste cependant en grande partie illusoire : il n&#8217;est pas rare que le déploiement d&#8217;une application relève de l&#8217;intérêt vital d&#8217;une organisation et que l&#8217;abandon suivi d&#8217;un contentieux judiciaire ne soit pas une véritable option, quels que soient les recours légaux qu&#8217;autorise le contrat.</p><p>De leur côté, et très schématiquement, les méthodes agiles reposent sur un mode de développement que l&#8217;on dit incrémental. Le développement est réalisé en cycles courts, de durée fixe, au terme desquels un logiciel partiel mais opérationnel est livré. Le périmètre de chaque cycle est déterminé au début du cycle, ou peu avant. Les autres fonctionnalités sont maintenues dans un Product Backlog qui est par principe ouvert au changement. En d&#8217;autres termes, si au cours du projet certains besoins apparaissent, changent ou disparaissent, ces modifications sont intégrées dans le Product Backlog, et potentiellement implémentées dans le cycle suivant. La réalisation incrémentale permet en outre une gestion des priorités : les fonctionnalités les plus importantes (celles qui ont le plus de valeur) sont placées en haut de la liste, et implémentées en premier. Ce pilotage par la valeur, couplé au caractère incrémental de la réalisation est au cœur de la logique financière des projets agiles – nous y reviendrons.</p><p>En somme, pour adhérer aux paradigmes des méthodes agiles, l&#8217;un des termes du contrat forfaitaire classique doit être abandonné : le périmètre fixe, généralement incarné par des spécifications techniques et fonctionnelles détaillées.</p><p>C&#8217;est cet abandon qui me semble improbable.</p><p>Pour bien comprendre en quoi cet abandon est incompatible avec un contrat forfaitaire, un petit détour par la la micro-économie est nécessaire.</p><p>Le développement incrémental permet de produire en premier lieu les fonctionnalités ayant la plus grande valeur d&#8217;usage pour le client (c&#8217;est lui qui fixe les priorités). Cette caractéristique renvoi à ce que les économistes appellent l&#8217;utilité marginale décroissante.<br
/> Le concept d&#8217;utilité marginale décroissante est classiquement illustré par le phénomène de la soif : lorsque vous êtes assoiffé, la première gorgée d&#8217;eau vous procure une très forte satisfaction (une très grande utilité, donc). A mesure que vous vous désaltérez, chaque nouveau verre vous apporte une satisfaction moindre que le précédent. Si vous devez payer chaque verre, vous cesserez de boire dès que le coût du verre vous semblera excessif en regard de la satisfaction de le boire. Si le verre est gratuit, vous boirez jusqu&#8217;à étanchement total de la soif – c&#8217;est-à-dire jusqu&#8217;au stade où un verre supplémentaire vous causerait du désagrément (il faut vraiment arréter, sinon <a
href="http://www.marianne2.fr/index.php/_moteur/Morte-d-une-overdose-d-eau!_a173568.html">il est possible d&#8217;en mourir !</a>).</p><p>Le développement incrémental produit le même phénomène : les fonctionnalités à plus forte valeur ajoutée sont produites en premier. Il est donc naturel que la valeur ajoutée des cycles successifs diminue.</p><p>Le graphique suivant illustre schématiquement ce principe d&#8217;utilité marginale décroissante :</p><div
align="center"><img
src="http://blog.xebia.fr/wp-content/uploads/2009/01/utilite-marginale-croissante.png" alt="Utilité marginale croissante" title="Utilité marginale croissante" /></div><p>A chaque cycle, la valeur totale du logiciel augmente, mais la variation de valeur entre deux cycles successifs (c&#8217;est-à-dire la valeur marginale) diminue.</p><p>Cette vision est bien sûr très stylisée (j&#8217;ai utilisée un fonction linéaire de l&#8217;utilité marginale pour construire le graphe). Dans la réalité, la valeur marginale est nettement plus variable : au cours du développement, certains besoins à forte valeur ajoutée peuvent émerger ; ils seront intégrés au cycle suivant, augmentant sensiblement son utilité marginale. Symétriquement, certaines fonctionnalités déjà développées peuvent se révéler décevantes : leur valeur d&#8217;usage est moindre que celle escomptée – ce qui réduit d&#8217;autant la valeur acquise.</p><p>Ajoutons qu&#8217;au même titre que la satisfaction marginale du buveur d&#8217;eau, la valeur marginale du développement peut devenir négative : en effet, toute fonctionnalité une fois développée et déployée possède un coût de possession intrinsèque (ressources, maintenance, supervision, etc.) qui peut dépasser sa valeur propre. Une fonctionnalité inutile dans un logiciel possède typiquement cette caractéristique (il suffit d&#8217;être utilisateur des dernières versions de Microsoft Office pour se faire une idée précise de ce phénomène).</p><p>En micro-économie, la notion d&#8217;utilité marginale décroissante est utile pour  expliquer le fonctionnement élémentaire des marchés. Si vous devez payer vos verres d&#8217;eau, vous cesserez de boire – et donc de payer &#8211; dès que le prix d&#8217;un verre vous semblera supérieur à son utilité marginale.</p><p>Le même principe est en oeuvre dans un projet agile : le développement devrait prendre fin lorsque le coût d&#8217;un cycle supplémentaire excède sa valeur marginale.</p><p><strong>Or avec un forfait, ce moment n&#8217;arrive jamais !</strong></p><p>Je m&#8217;explique, vous allez voir, c&#8217;est très simple.</p><p>Dans un forfait, le prix total est négocié frontalement, et peut donc être considéré en théorie comme un invariant. A contrario, les dépenses totales du fournisseur augmentant avec le temps, sa marge est directement dépendante de la durée des développements (et de ses coûts journaliers).<br
/> S&#8217;il applique un processus de développement incrémental, il se trouve dans la situation décrite par ce graphique (pour simplifier, on suppose que chaque cycle implique la même dépense que le précédent) :</p><div
align="center"><img
src="http://blog.xebia.fr/wp-content/uploads/2009/01/equilibres.png" alt="Equilibres" title="Equilibres" /></div><p>A chaque nouveau cycle, la dépense totale du fournisseur augmente, et sa marge totale baisse en proportion. Au-delà d&#8217;un certain seuil, sa marge devient négative, et il travaille à perte. Pour sa survie, il est indispensable que le projet prenne fin avant le franchissement de ce seuil fatidique.</p><p>Logiquement, lorsque la valeur totale du logiciel atteint le prix du forfait, le projet devrait s&#8217;interrompre (cet événement a lieu après le 8ème cycle dans notre modèle). A ce moment, la marge du fournisseur est positive, et le client a obtenu une valeur d&#8217;usage à hauteur de son investissement. Malheureusement, rien n&#8217;incite dans ce modèle le client à déclarer le projet achevé. En effet, ici, le coût marginal d&#8217;un cycle est nul – réaliser une itération supplémentaire n&#8217;impute pas le budget total. Le client est donc incité à prolonger les développements aussi longtemps que la valeur marginale d&#8217;une itération est positive, poussant virtuellement le fournisseur à boire le calice jusqu&#8217;à la lie.</p><p>Le seul moyen pour le fournisseur de maîtriser ce risque est de définir en amont – contractuellement – le périmètre de sa production logicielle. Il demande au client de s&#8217;engager dès le départ sur des spécifications détaillées du logiciel, et protège ce périmètre en le plaçant sous un strict contrôle du changement – chaque évolution faisant l&#8217;objet d&#8217;un juteux avenant. Dès lors le changement devient un coût pour le client, qui a le choix entre le refuser (au risque de mécontenter ses utilisateurs) ou le payer (au risque de voir son budget exploser de façon incontrôlée). L&#8217;un des principes cardinaux des méthodes agiles, l&#8217;acceptation du changement, devient tout simplement impraticable.</p><p>Dans sa dynamique financière, le contrat au forfait s&#8217;avère donc incompatible avec les prédicats du développement incrémental – la glaciation des spécifications est intrinsèque à la gestion du risque par le fournisseur, et c&#8217;est en facturant au prix fort le changement qu&#8217;il optimisera sa marge. Cette aversion au changement est intrinséquement contradictoire avec les principes agiles.</p><p>Il reste bien sûr possible de bricoler quelques dispositions contractuelles offrant un terrain plus favorable aux méthodes agiles dans un projet au forfait. Mais aucune ne pourra effacer véritablement l&#8217;incompatibilité fondamentale entre un contrat focalisé sur le coût, et une pratique de développement incrémentale et adaptative.</p><p>Cela ne signifie évidemment pas que les méthodes agiles sont incompatibles avec la notion de contrôle budgétaire ou de maîtrise des coûts, bien au contraire. Mais il est indispensable, pour assurer le succès des méthodes agiles dans un contexte de sous-traitance, de repenser la façon dont sont conçues les relations contractuelles entre les parties. Cet aspect fera l&#8217;objet d&#8217;un très prochain article.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2009/02/04/pourquoi-les-projets-agiles-ne-peuvent-pas-vraiment-etre-menes-au-forfait/feed/</wfw:commentRss> <slash:comments>26</slash:comments> </item> <item><title>ESB : Enterprise Spaghetti Bus ?</title><link>http://blog.xebia.fr/2008/01/15/esb-enterprise-spaghetti-bus/</link> <comments>http://blog.xebia.fr/2008/01/15/esb-enterprise-spaghetti-bus/#comments</comments> <pubDate>Tue, 15 Jan 2008 18:17:32 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[SOA]]></category> <category><![CDATA[ESB]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/01/15/esb-enterprise-spaghetti-bus/</guid> <description><![CDATA[Lors d&#8217;une récente séance de brainstorming avec plusieurs de mes collègues français et hollandais, un intéressant concept a émergé : celui de l&#8217;Enterprise Spaghetti Bus. Je vous en fait part, je suis sûr que vous aurez l&#8217;occasion de le replacer&#8230; Le concept du plat de spaghetti est familier à quiconque a eu l&#8217;occasion de travailler [...]]]></description> <content:encoded><![CDATA[<p>Lors d&#8217;une récente séance de <i>brainstorming</i> avec plusieurs de mes collègues français et hollandais, un intéressant concept a émergé : celui de l&#8217;Enterprise Spaghetti Bus. Je vous en fait part, je suis sûr que vous aurez l&#8217;occasion de le replacer&#8230;<p/><p>Le concept du plat de spaghetti est familier à quiconque a eu l&#8217;occasion de travailler sur des architectures distribuées à grande échelle (ou à petite échelle d&#8217;ailleurs). Le principe en est simple : à force de multiplier les interactions point-à-point entre des composants ou systèmes hétéroclites, on tisse une véritable toile de dépendances croisées qui, à une vitesse surprenante, conduit l&#8217;ensemble du système à la sclérose. Faire évoluer un composant (ou service) devient une tâche impossible, impactant un nombre croissant (et souvent inconnu) de systèmes tiers qui en sont les clients et, du coup, les victimes.<p/> Le schéma suivant résume l&#8217;idée :<p/><p
align="center"><img
src='http://blog.xebia.fr/wp-content/uploads/2008/01/esb-point-to-point-01_small.png' alt='esb-point-to-point-01.png' /></p><p>En règle générale, on cherche donc, lorsque l&#8217;on conçoit une architecture distribuée, à adhérer au paradigme ravioli plutôt qu&#8217;à celui spaghetti. Dans l&#8217;architecture ravioli, chaque composant est petit, et faiblement couplé aux autres ; il encapsule de la viande et d&#8217;autres aliments pour le système ; on peut enlever ou changer un raviolo (oui, au singulier, c&#8217;est raviolo, ne serait-ce que pour faire plaisir à une charmante italienne de ma connaissance) sans impacter les autres ravioli. A l&#8217;occasion, je vous parlerai plus en détail de la Théorie Générale des Pâtes Appliquée au Génie Logiciel (<em>Pasta Theory on Software</em>, en anglais)&#8230;<p/><p>Pour revenir aux problèmes d&#8217;architecture, les ESB sont à première vue un moyen simple de s&#8217;affranchir du modèle point-à-point au profit du modèle <em><a
href="http://en.wikipedia.org/wiki/Spoke-hub_distribution_paradigm">spoke-hub</a></em>, en d&#8217;autres termes de transformer à peu de frais votre plat de spaghetti en plat de ravioli. Le schéma suivant illustre cette évolution :<p
align="center"><img
src='http://blog.xebia.fr/wp-content/uploads/2008/01/esb-point-to-point-02_small.png' alt='esb-point-to-point-02.png' /></p><p>Présenté de la sorte, l&#8217;ESB fait figure de composant magique. Mais cette vision &#8211; que certains n&#8217;hésitent pas à exploiter sans vergogne dans leurs arguments commerciaux &#8211; néglige la nature duale du couplage dans une architecture distribuée.<p/> En effet, lorsque deux composants (ou systèmes ou services ou applications) établissent une communication point-à-point, ils établissent une dépendance à deux niveaux :<ul><li>au niveau technique : les deux systèmes doivent trouver un protocole de communication partagé &#8211; et ceci est vrai quelle que soit la sémantique d&#8217;échange, synchrone ou asynchrone</li><li>au niveau fonctionnel : les deux systèmes doivent s&#8217;entendre sur un format d&#8217;échange</li></ul><p>Appliqué tel quel, un ESB ne fait que résoudre la problématique de couplage au niveau technique &#8211; et c&#8217;est rarement le niveau le plus critique (les protocoles de <em>remoting</em> ne changent qu&#8217;exceptionnellement, et leurs évolutions assurent le plus souvent la rétrocompatibilité).<p/> Si le couplage fonctionnel n&#8217;est pas pris en compte, l&#8217;ESB ne fait que déplacer le problème &#8211; et nous obtenons notre fameux Enterprise Spaghetti Bus :</p><p
align="center"><img
src='http://blog.xebia.fr/wp-content/uploads/2008/01/esb-point-to-point-03_small.png' alt='esb-point-to-point-02.png' /></p><p>D&#8217;aucuns prétendront que cette situation est préférable, puisqu&#8217;elle permet de gérer la complexité en un point unique, et d&#8217;utiliser les services de transformation offerts par l&#8217;ESB pour gérer les évolutions dans les formats déchange ; l&#8217;argument est probablement recevable sur le court terme, tant que le nombre de services et de versions permet une combinatoire de taille raisonnable. Mais il ne fait aucun doute que rapidement, cette combinatoire va exploser &#8211; et avec elle le coût d&#8217;évolution de chaque service.<p/> La parade à l&#8217;Enterprise Spaghetti Bus existe : elle consiste à définir un format pivot, ou <i>modèle canonique</i>, auquel se conforme les producteurs et consommateurs de services. La mise en conformité &#8211; c&#8217;est-à-dire la conversion du format de données interne dans le format canonique &#8211; peut être réalisée par chaque sous-système, ou par l&#8217;ESB (la première solution a ma préférence, mais ce n&#8217;est pas le sujet du moment).  Chaque composant est désormais uniquement couplé au modèle canonique, et la figure rassurante du plat de ravioli semble de nouveau à portée de main.<p/> Reste un problème épineux auquel tous ceux qui tentent de mettre en place une architecture orientée services sont potentiellement confrontés : qui définit et maintient le (ou les) modèle(s) canonique(s) ? Les apôtres de l&#8217;urbanisation bureaucratique et de la gouvernance centralisée tendent à promouvoir un long et coûteux travail de modélisation transverse en amont. Je crois cette approche fondamentalement erronée : au mieux, elle risque d&#8217;aboutir à un report sans fin de la mise en oeuvre ; au pire, elle conduit à la mise en place d&#8217;un modèle rigide, excessivement complexe, mal adapté aux besoins réels des applications et hermétique au changement. Incrémentaliste convaincu, je crois au contraire que le modèle canonique doit être construit de façon progressive et collaborative, en prenant en compte les besoins à mesure qu&#8217;ils se présentent ; cela suppose que l&#8217;architecture intègre les évolutions du modèle canonique &#8211; faute de quoi le problème, une nouvelle fois, aura juste été déplacé. Il doit donc être possible de <em>refactorer</em> le modèle canonique &#8211; une opération que les ESB, précisément, rendent possible. Mais ceci est une autre histoire&#8230;</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/01/15/esb-enterprise-spaghetti-bus/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Scrum ou XP ? Scrum ET XP !</title><link>http://blog.xebia.fr/2008/01/10/scrum-ou-xp-scrum-et-xp/</link> <comments>http://blog.xebia.fr/2008/01/10/scrum-ou-xp-scrum-et-xp/#comments</comments> <pubDate>Thu, 10 Jan 2008 15:56:47 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <category><![CDATA[eXtreme-Programming]]></category> <category><![CDATA[SCRUM]]></category> <category><![CDATA[XP]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2008/01/10/scrum-ou-xp-scrum-et-xp/</guid> <description><![CDATA[Lors des Rencontres Agiles, que nous avons co-organisées en décembre dernier &#8211; et qui, soit dit en passant, ont rencontré un fort et encourageant succès -, plusieurs personnes m&#8217;ont demandé si, pour démarrer un projet agile, il était préférable de choisir eXtreme Programming (XP) ou Scrum. La réponse est simple : il faut adopter les [...]]]></description> <content:encoded><![CDATA[<p>Lors des <a
href="http://www.rencontresagiles2007.com/">Rencontres Agiles</a>, que nous avons co-organisées en décembre dernier &#8211; et qui, soit dit en passant, ont rencontré un fort et encourageant succès -, plusieurs personnes m&#8217;ont demandé si, pour démarrer un projet agile, il était préférable de choisir eXtreme Programming (XP) ou Scrum. La réponse est simple : il faut adopter les deux !</p><p>La complémentarité de Scrum et XP est communément admise. Scrum se positionne au niveau de la gestion et de l’organisation de projet là où XP se positionne au niveau des activités de développement. C’est la raison pour laquelle ces deux approches fonctionnent si bien ensemble : elles adressent des problématiques différentes et se complètent mutuellement.</p><p>Je vous propose, dans cet article, une présentation sommaire de Scrum et de la façon dont elle (il? non, allez, c&#8217;est plutôt une fille) s&#8217;articule avec eXtreme Programming&#8230; Bonne lecture !</p><h3>Scrum</h3><p>Davantage qu&#8217;une méthode formelle, Scrum peut être vu comme un framework méthodologique &#8211; ses fondateurs parlent d&#8217;<em>organisationnal pattern</em> &#8211; dont l&#8217;implémentation doit être ajustée en fonction des caractéristiques techniques, organisationnelles et culturelles des projets qui souhaitent la mettre en oeuvre (Scrum, au demeurant, ne limite pas son champ d&#8217;application aux seuls projets informatiques : ses principes sont applicables pour toute activité visant à produire un résultat).</p><p>Dans ses grandes lignes, Scrum définit un jeu minimal d&#8217;acteurs, de cérémonies et d&#8217;artefacts qui permettent de relever les défis principaux du développement incrémental : la planification, la gestion du temps et la gestion des obstacles. Scrum est entièrement piloté par la Valeur Métier – la gestion des risques, en particulier, est réalisée au travers de ce prisme.  Scrum identifie trois acteurs :</p><ul><li>le <strong>Product Owner</strong> (Directeur de Produit), qui possède l&#8217;expertise fonctionnelle et est à même de réaliser les arbitrages nécessaires à la priorisation des développements. Son rôle est absolument essentiel, et son respect des règles du jeu est la pierre angulaire du succès d&#8217;un projet agile.</li><li>le <strong>Scrum Master</strong>, membre de l&#8217;Equipe, et dont la tâche principale est d&#8217;optimiser la capacité de production de l&#8217;Equipe en l&#8217;aidant à travailler de façon autonome et à s&#8217;améliorer constamment. Il est également le garant de la bonne implémentation de Scrum.</li><li>l&#8217;<strong>Equipe</strong>, dont la taille doit être réduite (7 à 9 personnes est généralement admis comme une borne supérieure), et qui prend en charge le développement du produit (planification, conception, codage, tests, documentation) sans spécialisation des rôles. La particularité d&#8217;une Equipe Scrum est d&#8217;être « auto-organisée », et donc dépourvue de hiérarchie. Cet aspect constitue une rupture radicale avec les approches managériales traditionnelles, qui privilégient un contrôle centralisé généralement incarné par le Chef de Projet.</li></ul><p>L&#8217;unité de temps, dans Scrum, est le <strong>Sprint</strong>. Un sprint est une itération courte (de l&#8217;ordre de 2 à 4 semaines) dont le périmètre est garanti et défini lors d&#8217;une cérémonie de planification initiale.</p><p>Le schéma suivant décrit l&#8217;articulation générale de Scrum  :</p><p
align="center"><a
href="http://blog.xebia.fr/wp-content/uploads/2008/01/scrum_small.png" title="Scrum"><img
src="http://blog.xebia.fr/wp-content/uploads/2008/01/scrum_small.png" alt="Scrum" /></a></p><p>Scrum définit également trois artefacts (nous conservons les noms anglais pour rester consistant avec la littérature sur le sujet) :</p><ul><li>le <strong>Product Backlog</strong>, que nous décrivons plus loin</li><li>le <strong>Sprint Backlog</strong>, également décrit plus loin</li><li>le <strong>Burndown Chart</strong>, qui est une représentation graphique très simple de l&#8217;avancement du projet (un Burndown Chart est produit pour chaque Sprint, un autre pour la version du produit)</li></ul><p>Le Product Backlog est fondamental à Scrum – sans lui, rien n&#8217;est possible.</p><p>Le Product Backlog est la liste des fonctionnalités du logiciel. Les éléments du backlog sont rédigés sous forme de « User Stories » (une User Story est une forme simplifiée et faiblement détaillée de cas d&#8217;utilisation), et doivent se focaliser sur les objectifs métier du produit. A minima, un élément du backlog (ou une histoire) comporte typiquement les informations suivantes :</p><ul><li>un identifiant – unique, il permet de tracer l&#8217;élément quand on le renomme</li><li>un nom &#8211; court et descriptif, suffisamment clair pour que le Directeur de Produit et l&#8217;Equipe comprennent approximativement de quoi il est question</li><li>l&#8217;importance – un chiffre permettant de hiérarchiser l&#8217;importance de l&#8217;élément aux yeux du Directeur de Produit. Sa valeur absolue ne signifie rien, seule la valeur relative compte</li><li>l&#8217;estimation initiale – exprimée en points de complexité, et dont la valeur est déterminée par l&#8217;Equipe. Pour établir cette estimation, on utilise le plus souvent une technique issue de l&#8217;eXtreme Programming : le <a
href="http://en.wikipedia.org/wiki/Planning_poker">Planning Poker</a>.</li><li>comment faire la démo ? &#8211; cela correspond globalement à la spécification d&#8217;un test fonctionnel simple.</li><li>des notes – aussi brèves que possible, visant à clarifier certains points ou à renvoyer vers d&#8217;autres ressources</li></ul><p>Le Product Backlog peut également contenir des éléments techniques – mais il est indispensable alors qu&#8217;ils soient libellés selon un angle métier, afin que le Directeur de Produit puisse lui affecter une valeur.</p><p>Le Product Backlog peut être conservé sous différentes formes, la plus fréquente – et probablement la plus efficace &#8211; étant un simple tableau Excel partagé.</p><p>Le Product Backlog n&#8217;est pas un document figé : tout au long du projet, les histoires peuvent être modifiées, fusionnées ou segmentées (celles bien sûr qui ne sont pas encore achevées) ; de nouvelles histoires peuvent être ajoutées, d&#8217;autres supprimées ; l&#8217;importance et l&#8217;estimation initiale peuvent être revues, à la hausse ou à la baisse.Au début de chaque Sprint a lieu la cérémonie qui est probablement la plus importante de Scrum : le Sprint Planning (planification du Sprint). Le Sprint Planning réunit l&#8217;Equipe et le Directeur de Produit pour déterminer l&#8217;objectif et le contenu du Sprint à venir. C&#8217;est durant cette cérémonie que l&#8217;estimation fine de la charge de développement de chaque histoire est déterminée. Ces histoires sont découpées en tâches dont chacune fait l&#8217;objet d&#8217;une estimation de charge – exprimée en heures ou en jours. Il est important de noter que c&#8217;est l&#8217;Equipe qui détermine la charge afférente à chaque tâche. Le principal résultat de cette cérémonie est le Sprint Backlog, qui regroupe l&#8217;ensemble des fonctionnalités que l&#8217;Equipe s&#8217;engage à produire durant l&#8217;itération naissante, et liste les tâches correspondantes.</p><p>La charge totale du Sprint Backlog ne doit pas excéder la capacité de production de l&#8217;Equipe (il existe plusieurs techniques que nous n&#8217;aborderons pas ici pour établir cette capacité de production, ou vélocité estimée).</p><p>Au terme de chaque sprint, le produit partiel est livré avec le niveau de qualité attendu pour son exploitation en production – cette caractéristique est à l&#8217;origine du qualificatif « incrémental » souvent associé aux méthodes agiles. Les histoires implémentées font l&#8217;objet d&#8217;une démonstration publique.</p><p>Les méthodes agiles sont inspirées des pratiques industrielles de la production en flux tendus et du zéro-défaut – un ensemble de pratiques désignées dans l&#8217;industrie par le terme Lean. L&#8217;une des caractéristiques de cette approche est de ne jamais figer les méthodes de travail, mais d&#8217;intégrer dans l&#8217;activité une introspection permanente sous-tendue par la recherche systématique d&#8217;axes d&#8217;amélioration. Une autre caractéristique est de ne jamais utiliser la qualité comme variable d&#8217;ajustement. Dans Scrum (et d&#8217;une façon générale pour toutes les méthodes agiles), la qualité du produit est de la responsabilité de l&#8217;Equipe, et ne fait pas l&#8217;objet de négociations.</p><p>Afin de faciliter cette démarche, Scrum intègre un certain nombre de cérémonies additionnelles – une cérémonie est une réunion dont la durée est fixée et dont les produits en entrée et en sortie sont définis. La limite de temps pour chacune des cérémonies fait partie de l&#8217;ADN de Scrum (on parle de <em>time boxing</em>).</p><p>Voici les principales cérémonies préconisées par Scrum :</p><ul><li>le <strong>Sprint planning</strong>, que nous avons déjà abordé</li><li>la mêlée quotidienne (<strong>Daily Scrum</strong>), courte cérémonie (de l&#8217;ordre de 15 minutes) menée chaque jour avec les membres de l&#8217;Equipe et le Directeur de Produit, et dont l&#8217;objectif est de maintenir chacun au courant de l&#8217;activité de tous, de déterminer les tâches de la journée et d&#8217;identifier les éventuels obstacles qui ralentissent ou empêchent la progression du sprint</li><li>la revue de sprint (<strong>Sprint Review</strong>), qui consiste pour l&#8217;essentiel, au terme de chaque itération, à faire une démonstration publique du résultat du sprint ; cette cérémonie permet de garantir le caractère incrémental du développement (pour être démontré, le produit doit être utilisable) mais aussi de recueillir un retour régulier des commanditaires aux fins d&#8217;ajuster le contenu du backlog de produit</li><li>la rétrospective (au moins 1 heure), qui réunit l&#8217;équipe et le Product Owner au terme de chaque sprint afin d&#8217;identifier les erreurs commises lors du sprint précédent et de définir un plan d&#8217;actions (concret et affecté) en vue d&#8217;améliorer le processus ; la rétrospective est une cérémonie capitale qui incarne l&#8217;un des principes fondamentaux énoncés par le Manifeste Agile : « A intervalles réguliers, l&#8217;équipe réfléchit sur les moyens de devenir plus efficace, puis adapte et ajuste son comportement en conséquence ».</li></ul><p>Une dernière question peut se poser : quels outils utiliser pour assurer le suivi de projet ? Il existe un certain nombre d&#8217;offres logicielles dans ce domaine. Dans la pratique, nous préconisons de débuter avec l&#8217;outillage le plus élémentaire : une feuille Excel, des post-it et un mur. Avec l&#8217;expérience, et en adhérant aux principes généraux de la méthode (inspecter et s&#8217;adapter), le Scrum Master pourra choisir d&#8217;utiliser d&#8217;autres outils. Dans la pratique, une telle démarche n&#8217;est que rarement nécessaire.</p><p>Scrum, on le voit, adresse la problématique du processus de production du logiciel, l&#8217;organisation et la dynamique du projet. Le développement incrémental, néanmoins, suppose des pratiques d&#8217;ingénierie logicielle rigoureuses et efficicaces, que Scrum ne couvre pas &#8211; rappelons que Scrum est avant tout un style organisationnel. C&#8217;est précisément sur ce terrain des techniques de génie logiciel incrémental que l&#8217;eXtreme Programming trouve tout son sens, en proposant un certain nombre de pratiques reconnues aujourd&#8217;hui comme l&#8217;<em>état de l&#8217;art</em>.</p><h3>eXtreme Programming – XP</h3><p>La première des pratiques de l&#8217;eXtreme Programming, la plus fondamentale également, est le test automatisé.</p><p>L&#8217;approche incrémentale suppose une vision minimaliste – on aurait envie de dire zen &#8211; du développement : seules les fonctionnalités effectivement nécessaires sont développées, et le design adopté doit être le plus simple imaginable permettant d&#8217;implémenter intégralement la fonctionnalité (ce principe est souvent désigné sous l&#8217;acronyme KISS : Keep It Simple and Stupid). Le Manifeste Agile définit au demeurant la simplicité comme « l&#8217;art de maximiser le volume de ce qui ne doit pas être fait ». Conséquence de cette recherche de simplicité, certains choix de design, suffisants à un moment donné, peuvent s&#8217;avérer inadaptés lors de développements ultérieurs. L&#8217;ajustement se fait alors par refactoring (ou ré-ingénierie), qui consiste à modifier le design voire l&#8217;architecture d&#8217;un composant sans changer son comportement. Le refactoring – une opération techniquement triviale avec les environnements de développement java, plus délicate lorsqu&#8217;il s&#8217;agit de la base de données – comporte un risque de régression évident, risque couvert en principe par la pratique des tests unitaires. L&#8217;équation est alors simple : sans tests unitaires, le refactoring devient rapidement impossible ; sans refactroring, les choix d&#8217;implémentation ne peuvent plus être remis en question ; sans remise en question, le développement incrémental devient illusoire, et c&#8217;est tout l&#8217;édifice du développement agile qui s&#8217;écroule.</p><p>Le test automatisé n&#8217;est pas seulement une bonne pratique du développement agile : il en est l&#8217;épine dorsale.</p><p>XP inclut la systématisation des tests automatisés &#8211; unitaires, fonctionnels, d&#8217;intégration, de performance, le plus est le mieux. Poussée à l&#8217;extrême, cette pratique a donné naissance au principe du TDD (<em>Test Driven Development</em>). Le TDD modifie sensiblement la pratique du développement. Son principe est d&#8217;une redoutable simplicité, mais sa mise en oeuvre est un véritable défi. Voici comment Henrik Kniberg résume le TDD :</p><blockquote><p><em>Test-driven development means that you write an automated test, then you write just enough code to make that one test pass, then you refactor the code primarily to improve readability and remove duplication. Rinse and repeat.</em></p></blockquote><p>Traduction : le développeur écrit en premier lieu un test automatisé de la fonctionnalité qu&#8217;il souhaite implémenter, développe ensuite juste assez de code pour satisfaire le test et finalement remanie le code pour améliorer le design et supprimer la duplication.</p><p>Outre les bénéfices classiques des tests unitaires, le TDD possède deux vertus cardinales : il permet de maintenir le focus du développeur sur les fonctionnalités réellement utiles ; il a des effets spontanés et profonds sur la qualité du design.</p><p>Au delà du TDD, XP comprend un certain nombre de pratiques dont la mise en place est souvent associée à l&#8217;adoption des méthodes agiles – sans pour autant sue cette mise en place soit obligatoire.<br
/> Voici, sans exhaustive, les plus importantes de ces pratiques :</p><ul><li>le <strong>Refactoring</strong> ; nous l&#8217;avons déjà rapidement abordé, c&#8217;est une pratique intrinsèque du développement incrémental et qui mériterait un billet à part entière. Pour une bonne introduction aux technique de refactoring objet, je vous invite à consulter le site que Martin Fowler a consacré au sujet : <a
href="http://www.refactoring.com/">refactoring.com</a>.</li><li>l&#8217;<strong>Intégration Continue</strong> ; cette pratique consiste à déclencher de façon systématique le système de build – qui comprend notamment la compilation et l&#8217;exécution des tests automatisés – chaque fois qu&#8217;un membre de l&#8217;équipe valide des sources dans le référentiel projet ; c&#8217;est une pratique essentielle pour détecter et corriger au plus tôt les problèmes d&#8217;intégration des développements (principe de <em>fail fast</em>)</li><li>la <strong>Propriété Collective</strong> ; la propriété collective du code consiste à ne pas spécialiser certains membres de l&#8217;équipe sur certains composants – et donc à favoriser la polyvalence au sein de l&#8217;équipe. Elle est évidemment favorisée par des pratiques telles que la programmation en binôme qui favorise l’appropriation d’une base commune de code. Les équipes avec un haut niveau d’appropriation collective de code sont réputées pour être plus robustes : un sprint ne sera par exemple pas forcément menacé par l’absence ponctuelle d’un membre de l’équipe.</li><li> les <strong>Normes de développement</strong> ; sans être une particularité de l&#8217;eXtreme Programming, les normes de développement en sont un élément clé, facilitant les tests, l&#8217;intégration continue et l&#8217;appropriation collective de la base de code. Elles renforcent également la consistance des APIs.</li><li>la Programmation en binôme (<strong>Pair Programming</strong>), qui consiste à développer à deux sur un même poste ; cette pratique, souvent mal comprise, n&#8217;est que rarement systématisée. Il ne faut par contre pas s’interdire son utilisation ponctuelle, par exemple sur une nouvelle technologie, une problématique pointue, un fonctionnel plus complexe, ou plus simplement, si l’un des membres de l’équipe demande de l’assistance. C&#8217;est aussi une pratique utile lors des montée en charge de l&#8217;équipe : elle permet d&#8217;intégrer plus rapidement les nouveaux développeurs et de leur communiquer la culture de l&#8217;équipe.</li><li>un <strong>Rythme soutenable</strong> ; ce principe est commun à toutes les méthodes agiles, et directement issu du <em>heijunka</em> Lean ; il part du principe qu&#8217;il n’y a rien de plus contre-productif à moyen terme que de maintenir une équipe de développement sous la pression d’une charge de travail supérieure à sa capacité de production &#8211; cela revient à étrangler la poule aux œufs d’or et se traduit généralement par une baisse massive de la qualité et de la motivation.</li></ul><p>Certaines des pratiques de l&#8217;eXtreme Programming ont irrigué Scrum (ou le contraire, peu importe) : « une équipe », « une même pièce », la notion de « stories », le « rythme soutenable » ou encore le « planning game », raison pour laquelle ces deux approche sont très complémentaires.</p><p>Cet article vous a proposé un rapide aperçu de Scrum et XP et aura, je l&#8217;espère, contribué à mettre en exergue la complémentarité des deux approches. Beaucoup de notions ont été évoquées de façon trop brève, et je reviendrai dessus dans de prochains billets&#8230; N&#8217;hésitez pas à laisser vos commentaires et questions !</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2008/01/10/scrum-ou-xp-scrum-et-xp/feed/</wfw:commentRss> <slash:comments>17</slash:comments> </item> <item><title>Rencontres Agiles 2007</title><link>http://blog.xebia.fr/2007/12/05/rencontres-agiles-2007/</link> <comments>http://blog.xebia.fr/2007/12/05/rencontres-agiles-2007/#comments</comments> <pubDate>Wed, 05 Dec 2007 19:16:32 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/12/05/rencontres-agiles-2007/</guid> <description><![CDATA[Le 18 décembre prochain, se tiendront à la Défense les premières Rencontres Agiles. Il s&#8217;agit d&#8217;une conférence cosponsorisée par XEBIA, OCTO et SFEIR et dont le principe est d&#8217;une simplicité enfantine : Une salle de 200 places, inscription gratuite Une matinée complète, sans interruption Des sessions de 20 minutes pour aller rapidement à l’essentiel (no [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: center"><a
href='http://www.recontresagiles2007.com' rel='attachment wp-att-152' title='Rencontres Agiles 2007'><img
src='http://blog.xebia.fr/wp-content/uploads/2007/12/recontresagiles2007.png' alt='Rencontres Agiles 2007' /></a></p><p>Le 18 décembre prochain, se tiendront à la Défense les premières Rencontres Agiles.<br
/> Il s&#8217;agit d&#8217;une conférence cosponsorisée par <a
href="http://www.xebia.fr">XEBIA</a>, <a
href="http://www.octo.com/">OCTO</a> et <a
href="http://www.sfeir.com/">SFEIR</a> et dont le principe est d&#8217;une simplicité enfantine :<ul><li>Une salle de 200 places, inscription gratuite</li><li>Une matinée complète, sans interruption</li><li>Des sessions de 20 minutes pour aller rapidement à l’essentiel (no fluff, just stuff).</li><li>Une sélection des meilleurs acteurs de l’Agile en France aujourd’hui.</li></ul><p>Le programme se construit de manière incrémentale &#8211; il est publié au fur à mesure sur <a
href="http://www.rencontresagiles2007.com">le site de la conférence</a>. Au menu : une dizaine de sessions couvrant des pratiques, des retours d’expérience et des démonstrations d’outils.<br
/> Si vous voulez en savoir le maximum sur l’agilité aujourd’hui en France en une matinée, inscrivez-vous dés maintenant sur <a
href="http://www.rencontresagiles2007.com">le site de la conférence</a> !</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/12/05/rencontres-agiles-2007/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Chroniques de la performance : À propos de contentions&#8230;</title><link>http://blog.xebia.fr/2007/11/29/chroniques-de-la-performance-a-propos-de-contentions/</link> <comments>http://blog.xebia.fr/2007/11/29/chroniques-de-la-performance-a-propos-de-contentions/#comments</comments> <pubDate>Thu, 29 Nov 2007 22:15:31 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/11/29/chroniques-de-la-performance-a-propos-de-contentions/</guid> <description><![CDATA[J&#8217;ai été, il y a peu, confronté à un problème de performances que l&#8217;on peut qualifier d&#8217;intéressant &#8211; dans la bouche d&#8217;un expert technique, ce mot a généralement tendance à provoquer une bouffée de panique chez les plus chevronnés des managers. Je vous explique. Le programme consiste à appliquer massivement un traitement identique à un [...]]]></description> <content:encoded><![CDATA[<p>J&#8217;ai été, il y a peu, confronté à un problème de performances que l&#8217;on peut qualifier d&#8217;<em>intéressant</em> &#8211; dans la bouche d&#8217;un expert technique, ce mot a généralement tendance à provoquer une bouffée de panique chez les plus chevronnés des managers.</p><p>Je vous explique.</p><p>Le programme consiste à appliquer massivement un traitement identique à un volume important de données – bref, c’est un batch. Objectif opérationnel : assurer la capacité du système à traiter 50000 dossiers par heure.<br
/> L’architecture d’exécution de ce batch est relativement classique : un contrôleur est chargé d’obtenir auprès d’un service métier une liste de dossiers à traiter, de segmenter cette liste en lots, puis de soumettre les lots à un pool  de threads qui vont réaliser les traitements en parallèle – chaque lot est traité dans une transaction distincte. Le traitement unitaire d’un dossier est relativement long, de l’ordre de 2 secondes ; les lots sont donc petits – 4 dossiers – pour limiter la durée des transactions.</p><p>Au-delà de son rôle de segmentation et de répartition des lots, le contrôleur fournit un ensemble de services de pilotage, qui n’ont pas vraiment de relation avec notre problème, mais que je mentionne pour information : état d’avancement du traitement, interruption, reprise, calcul de statistiques variées, rapports d’erreurs, etc.</p><p>Typiquement, avec une telle architecture, le débit total du système est une fonction du temps de traitement unitaire et du nombre de threads simultanés :</p><p
style="text-align: center"><code>Débit Horaire = (3600 / Temps Unitaire) * Nombre de threads</code></p><p>Pour mon batch, le calcul théorique est simple : le traitement de chaque dossier demandant 2 secondes, un thread peut traiter 1800 dossiers par heure. Le débit cible étant de 50000 dossiers par heure il est donc théoriquement nécessaire de démarrer un pool de 30 threads.<br
/> Ce calcul cependant part d’une hypothèse audacieuse : il suppose que les temps de traitement unitaire resteront stables quel que soit le nombre de threads. En somme, que la montée en charge du système est parfaitement linéaire.</p><p>Or les tests grandeur réelle réalisés en pré-production montrent un comportement assez éloigné de notre équation platonicienne :</p><p
style="text-align: center"><img
src="http://blog.xebia.fr/wp-content/uploads/2007/11/tu_initial.png" alt="Temps unitaire par dossier selon le nombre de threads" /></p><p>Exprimé sous forme de débit, ce même graphe montre une pente inquiétante :</p><p
style="text-align: center"><img
src="http://blog.xebia.fr/wp-content/uploads/2007/11/debit_initial.png" alt="Débit réel comparé au débit théorique" /></p><p>Le débit horaire s’écarte de plus en plus de la valeur théorique idéale et tend vers une valeur désespérément éloignée du débit cible. Pire, il aurait tendance à se dégrader lorsque le nombre de threads devient trop élevé. Pas de panique, cependant, ce comportement ne saurait déstabiliser le briscard de la performance que je suis : de telles courbes révèlent simplement que le système atteint une limite qui interdit la montée en charge. Reste à déterminer quel composant physique ou logiciel en est à l’origine.</p><p>La première réaction est naturellement de vérifier qu’aucun composant physique n’arrive à saturation. Les outils <em>ad hoc</em> sont utilisés pour contrôler la consommation CPU, l’overhead du GC, le paging, la bande passante, les I/O disque, etc., je vous épargne le détail. Deux éléments intéressants sont tirés de cette analyse : premièrement, aucun composant physique n’approche ses limites de capacité ; deuxièmement, leur niveau de charge épouse presque parfaitement l’évolution du débit présenté dans la figure 2. En d&#8217;autres termes, l’usage des ressources physiques, par exemple la charge moyenne des processeurs, présente la même évolution que le débit : leur montée en charge est freinée et s’écarte inexorablement de la progression théorique linéaire.<br
/> Une nouvelle fois, ce sont des caractéristiques relativement communes des systèmes parallélisés : cela signifie que les threads d’exécution entrent en compétition pour obtenir certains verrous, ou pour accéder à certaines sections critiques ; plus le nombre de threads augmente et plus la compétition devient serrée : il faut de plus en plus de temps pour acquérir les verrous.</p><p>Dans notre système, deux composants sont susceptibles de créer ces conditions :</p><ul><li>la base de données, qui gère des verrous à différents niveaux</li><li>le code java, au travers de blocs synchronisés</li></ul><p>Quiconque a déjà travaillé sur un système transactionnel fortement parallélisé sait que les contentions sur la base de données en sont le principal écueil. Pour assurer l’isolation des transactions, les SGBD posent des verrous en lecture et/ou en écriture sur des lignes, des pages ou des tables – en cas de très forte charge, la granularité des verrous est parfois modifiée dynamiquement, passant par exemple de la ligne (ROW LOCK) à la page (PAGE LOCK).<br
/> Notre système batch a été conçu en conséquence : la base est partitionnée selon des axes fonctionnels stricts, les opérations de lecture et d’écriture ont été soigneusement séquencées, les verrous sont posés au niveau des pages et le contrôleur sait exploiter certaines caractéristiques du stockage physique pour calculer et répartir les segments entre les différents threads. Une analyse des contentions sur la base de données a démontré l’efficacité de ces stratégies : le niveau de contention reste remarquablement bas, et n’explique en aucun cas la forte dégradation observée lors de la montée en charge.</p><p>Reste une seule explication : des contentions dans les couches d’exécution Java. Et une question : comment identifier l’origine de ces contentions, et les corriger ?</p><p>Un premier test est réalisé pour valider l’hypothèse de contentions applicatives dans le code java : il consiste à démarrer 5 processus dotés chacun d’un pool de 4 threads – un total de 20 threads, donc, permettant d’atteindre un taux de parallélisation qui dans nos tests précédents mettaient fortement en exergue la dégradation des temps de traitements unitaires. Ce test est concluant : distribués sur 5 processus distincts, les threads ne sont plus soumis à une compétition mortifère, et la montée en charge se réalise de façon satisfaisante.</p><p>Une solution envisageable serait d’adopter cette architecture, et de distribuer les traitements sur plusieurs processus. Le contrôleur, cependant, n’a pas été conçu pour coordonner plusieurs processus. L’évolution la plus simple, consistant à séparer le contrôleur des composants métiers – par exemple au moyen d’EJBs – implique d’introduire une couche de distribution qui nous semble d’autant moins souhaitable que le contrôleur est en charge du pilotage des transactions : le séparer des traitements signifie distribuer les transactions, et tous les petits soucis que cette décision implique généralement. Cela signifie aussi probablement l’introduction d’un serveur d’applications dans l’architecture de batch, avec les difficultés afférentes en terme de déploiement et d’exploitation. D’autres évolutions plus massives sont envisageables : par exemple s’appuyer sur des tables techniques pour stocker les segments, et découpler complètement une phase de pré-processing – consistant à calculer les lots – et une phase de traitement – consistant à piocher des lots dans la base et à les traiter. On peut même imaginer des solutions plus exotiques, à base de files JMS&#8230; Mais pour tout dire, nous aimons la compacité de notre architecture initiale, et ne sommes pas prêts à l’abandonner sans résister un peu. La question reste donc entière : comment débusquer l&#8217;origine de nos contentions aux fins de les liquider ?</p><p>L’analyse statique du code n’a rien donné : le contrôleur, à l’instar des composants métiers, utilise un bon zillion de bibliothèques tierces, plus ou moins open source et au flot d’exécution volontiers cryptique. Impossible dans ces conditions de déterminer l’origine exacte des contentions par simple consultation des sources : une analyse <em>runtime</em> est nécessaire.</p><p>Reste à trouver le bon outil dans la sacoche du plombier java. Même avec l&#8217;aide gracieuse de Google, la récolte reste maigre en matière d&#8217;outillage&#8230;</p><p>Autant l’offre est pléthorique lorsqu’il s’agit de profiler la consommation CPU ou mémoire des applications Java, autant l’analyse des contentions reste une discipline peu outillée. Certes les profilers java offrent pour la plupart un module d’analyse de threads ; mais leur overhead est tel qu’il est difficile, voire impossible d’instrumenter un traitement fortement multi-threadé comme notre batch : au-delà de 3 ou 4 threads, les informations collectées perdent de leur pertinence, et les temps unitaires s’allongent tellement que toute tentative d’analyse relève de l’acrobatie la plus pure.<br
/> Tordons rapidement le cou à hprof, le profiler intégré au JDK – le notre, en l’occurrence, est un JDK IBM 1.4.2 SR8 ; la documentation indique une option « monitor=y », qui, je cite, « tells hprof to generate information on contention monitors used to synchronize the work of multiple threads » (je vous laisse traduire). Bigre, nous voilà sauvés ! Pas tout à fait&#8230; Outre que le faire fonctionner a demandé une montée de version du JDK – la version que nous utilisions à l’origine générait un très joli core lors de l’activation de hprof -, les informations obtenues se sont révélées d’une rare inutilité (fondamentalement, un état des moniteurs java au moment de la sortie du processus. Aucun intérêt !).<br
/> Exit hprof, donc.<br
/> Autre approche : générer de façon répétée des Thread Dump à l’aide de l’instruction <code>kill -3</code>, puis comparer les différents dumps à l’aide d’un outil <em>ad hoc</em> (en l’occurrence un utilitaire disponible sur le site alphaWorks, et dont je donne le nom complet pour souligner le sens du marketing des ingénieurs IBM : <a
href="http://www.alphaworks.ibm.com/tech/jca">IBM Thread and Monitor Dump Analyzer for Java Technology</a>). Bien que prometteuse, cette solution n’a une nouvelle fois pas donné de résultat définitif : elle nous a permis d’identifier quelques méthodes candidates, mais sans qu’il fût possible de quantifier leurs responsabilités respectives.</p><p>Reste une solution : retrousser ses manches et écrire un profiler spécialisé en s’appuyant sur JVMPI.<br
/> JVMPI (pour Java Virtual Machine Profiling Interface) est, comme son nom le suggère, une API native de profilage de la JVM (remplacée par JVMTI à partir de Java 5, mais c&#8217;est une autre histoire). L’API fonctionne sur un système de callback : l’agent (c’est ainsi que l’on nomme le programme s’appuyant sur l’API) s’enregistre auprès de la JVM en précisant les types d’événements dont il souhaite être notifié – vous aurez probablement reconnu le pattern Observer.<br
/> Ces événements concernent la plupart des opérations techniques de bas niveau réalisées par la JVM : chargement d’une classe, allocation mémoire, exécution d’une méthode, démarrage d’un thread, etc. Parmi ces événements, deux retiennent particulièrement notre attention : <code>MONITOR_CONTENDED_ENTER</code> et <code>MONITOR_CONTENDED_ENTERED</code>. Le premier indique qu&#8217;un thread souhaite exécuter un bloc synchronisé, et tente d&#8217;acquérir un moniteur à cette fin (pour mémoire, la notion de moniteur en java est très proche de celle de verrou dans le reste du monde); le second indique que le thread a obtenu le moniteur en question et entame l&#8217;exécution du bloc synchronisé. L&#8217;intervalle de temps entre les deux événements correspond par conséquent à la durée totale de l&#8217;attente – autrement dit à la durée de la contention.<br
/> Munis de ces rudiments de JVMPI, il est possible de formuler les spécifications exhaustives de notre petit outil de profilage : la durée de toutes les contentions rencontrées par le programme est mesurée. Si cette durée est supérieure à un certain seuil (disons 5 millisecondes), le nom de la méthode correspondante est loggué dans un fichier, ainsi qu’une pile d’appels simplifiée.</p><p>Bien. Il ne reste plus qu&#8217;à coder.</p><p>Le point d&#8217;entrée d&#8217;un agent JVMPI est la méthode JVM_OnLoad. C&#8217;est dans cette méthode que l&#8217;on va informer le sous-système JVMPI des événements que l&#8217;on souhaite activer (<code>EnableEvent</code>), et de la méthode callback qui sera invoquée lors des occurrences de ces événements (<code>NotifyEvent</code>) :</p><pre class="brush: cpp; title: ; notranslate">
JNIEXPORT jint JNICALL _JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
{
    ...
    /* Register callback method */
    jvmpi-&gt;NotifyEvent = jtprof_notify_event;
    /* Enable events */
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_CLASS_LOAD, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_CLASS_UNLOAD, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_MONITOR_CONTENDED_ENTER, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_THREAD_START, NULL);
    jvmpi-&gt;EnableEvent(JVMPI_EVENT_THREAD_END, NULL);
    ...
    return JNI_OK;
}
</pre><p>La méthode <em>callback</em>, <code>jtprof_notify_event</code>, se contente de déterminer la nature de l&#8217;événement et de déclencher un <em>handler</em> spécialisé :</p><pre class="brush: cpp; title: ; notranslate">
static void jtprof_notify_event(JVMPI_Event *event)
{
    switch(event-&amp;gt;event_type) {
        case JVMPI_EVENT_JVM_SHUT_DOWN:
            handle_jvm_shut_down_event();
            return;
        ...
        case JVMPI_EVENT_THREAD_START:
            handle_thread_started_event(event);
            return;
        case JVMPI_EVENT_THREAD_END:
            handle_thread_end_event(event);
            return;
        case JVMPI_EVENT_MONITOR_CONTENDED_ENTER:
            handle_monitor_contented_enter(event);
            return;
        case JVMPI_EVENT_MONITOR_CONTENDED_ENTERED:
            handle_monitor_contented_entered(event);
            return;
        ...
    }
}
</pre><p>Les choses semblent relativement simples. L&#8217;API JVMPI offre même un système de stockage <em>thread local</em> (méthode <code>GetThreadLocalStorage</code>), permettant de conserver une structure de données quelconque dédiée à chaque thread. Je vous épargne les détails de la création et de la destruction de cette structure de données – les curieux pourront jeter un oeil sur le code source. Sachez simplement qu&#8217;elle est créée lors de l&#8217;événement THREAD_START, détruite lors de l&#8217;événement THREAD_END, et qu&#8217;elle permet notamment de conserver la date de la demande d&#8217;acquisition du moniteur par le thread.</p><p>Au final, le code permettant de mesurer la durée d&#8217;acquisition d&#8217;un moniteur est relativement trivial :</p><pre class="brush: cpp; title: ; notranslate">
static void handle_monitor_contented_enter(JVMPI_Event *event){
    thread_local_context *ctx = (thread_local_context*)jvmpi-&gt;GetThreadLocalStorage(event-&gt;env_id);
    //Error handling code
    ....
    ctx-&gt;timer = system_current_time_millis();
}
static void handle_monitor_contented_entered(JVMPI_Event *event){
    long finish = system_current_time_millis();
    long total;
    thread_local_context *ctx = (thread_local_context*)jvmpi-&gt;GetThreadLocalStorage(event-&gt;env_id);
    //Error handling code
    ....
    total = finish – ctx-&gt;timer;
    ctx-&gt;timer = 0;
    if (total &gt; __contention_threshold){
        //Log contention details
        ....
    }
}
</pre><p>Les choses, bien sûr, sont en réalité un poil plus complexes – fallait pas rêver, non plus.<br
/> Par souci d&#8217;efficacité, en effet, la structure de données <code>JVMPI_Event</code> ne contient, pour chaque événement, qu&#8217;un jeu minimal d&#8217;informations. En pratique, cela signifie que le nom de la méthode invoquée n&#8217;est pas disponible sous forme littérale, mais sous la forme d&#8217;un identifiant interne créé lors du chargement de la classe correspondante.<br
/> Logguer cet identifiant ne serait bien sûr pas d&#8217;un grand intérêt. Il faut pouvoir l&#8217;associer au nom qualifié de la méthode. Pour cela, l&#8217;événement <code>CLASS_LOAD</code> doit être traité. Cet événement fournit la définition complète de la classe et de toutes ses méthodes – y compris leur nom littéral. Notre programme conserve donc ces informations dans un tableau associatif (dont le code source est très largement inspiré de celui de hprof). Ce tableau peut ensuite être consulté lors du traitement d&#8217;une contention afin de déterminer le nom de la méthode appelante à partir de son identifiant. Une technique similaire est mise en oeuvre pour expliciter la pile d&#8217;appels. Je vous laisse consulter <a
href="http://blog.xebia.fr/wp-content/uploads/2007/11/jtprof.zip" title="jtprof.zip">le code source</a> pour les détails&#8230;</p><p>Le programme doit être compilé sous forme de bibliothèque dynamique (extension <code>.dll</code> sous Windows, <code>.so</code> sous Unix), inclu dans le LIB_PATH (ou son équivalent) et intégré à la JVM grâce à l&#8217;option <code>-Xrunjtprof</code> (jtprof est le nom donné à la bibliothèque). Voici le type de sorties obtenues :</p><pre class="brush: java; title: ; notranslate">
[JTPROF] Contention report [id=-2002923824,thread=Contention-Thread-4,blocked=305ms]
[JTPROF] Stack trace:
[JTPROF]	 org.test.Contentions.blockABitMore (Contentions.java:36)
[JTPROF]	 org.test.Contentions.run (Contentions.java:25)
[JTPROF]	 java.lang.Thread.run (Thread.java:595)
...
[JTPROF] Thread end [id=-2002912512, name=Contention-Thread-6, duration=1519ms, blocked=1416ms]
</pre><p>Une fois mis au point, cet outil s&#8217;est révélé très précieux. Son overhead est très faible – les événements les plus gourmands, comme les sites d&#8217;allocation mémoire ou la consommation CPU des méthodes, ne sont pas traités. Il nous a fourni un état très précis du niveau de contention, et de la localisation de celles-ci. Une douzaine de méthodes ont été corrigées (la plupart des contentions étaient de très courte durée &#8211; rarement plus de 50ms &#8211; mais leur fréquence et leur durée avaient tendance à augmenter).<br
/> Au terme de ces optimisations, la courbe des débits se présente comme suit :</p><p
style="text-align: center"><img
src="http://blog.xebia.fr/wp-content/uploads/2007/11/debit_final.png" alt="Débit réel comparé au débit théorique" /></p><p>Il reste un léger décrochage au-delà de 25 threads, mais cette fois-ci, son origine ne fait pas de doute : notre machine de test est simplement saturée, et la contention, cette fois-ci, porte sur l&#8217;accès aux processeurs.</p><p>Ceux qui ont suivi depuis le début se souviennent peut-être de l&#8217;équation présentée plus haut dans cet article :</p><p
style="text-align: center"><code>Débit Horaire = (3600 / Temps Unitaire) * Nombre de threads</code></p><p>S&#8217;ils n&#8217;ont pas complètement oublié le programme de mathématiques du Brevet des Collèges, ils auront probablement compris que l&#8217;augmentation du nombre de threads n&#8217;est pas le seul levier du débit : réduire le temps de traitement unitaire en est un autre. Mais ceci est une autre histoire&#8230;</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/11/29/chroniques-de-la-performance-a-propos-de-contentions/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Le wannabisme agile</title><link>http://blog.xebia.fr/2007/11/22/le-wannabisme-agile/</link> <comments>http://blog.xebia.fr/2007/11/22/le-wannabisme-agile/#comments</comments> <pubDate>Thu, 22 Nov 2007 07:45:31 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/11/22/le-wannabisme-agile/</guid> <description><![CDATA[Dans une récente interview sur InfoQ, que nous évoquions il y a peu dans notre revue de presse, Jeff Sutherland fait état d&#8217;un ensemble de tests que la société Nokia applique aux processus de développement logiciel pour déterminer s&#8217;ils utilisent réellement une approche itérative et incrémentale, et plus spécifiquement s&#8217;ils adhèrent ou non à la [...]]]></description> <content:encoded><![CDATA[<p>Dans une récente <a
href="http://www.infoq.com/interviews/jeff-sutherland-scrum-rules">interview sur InfoQ</a>, que nous évoquions il y a peu dans <a
href="http://blog.xebia.fr/2007/10/29/revue-de-presse-xebia-29/#JeffSutherland">notre revue de presse</a>, Jeff Sutherland fait état d&#8217;un ensemble de tests que la société Nokia applique aux processus de développement logiciel pour déterminer s&#8217;ils utilisent réellement une approche itérative et incrémentale, et plus spécifiquement s&#8217;ils adhèrent ou non à la méthodologie Scrum. Je ne reviendrai pas sur ces tests &#8211; Jeff les explique mieux que moi &#8211; mais j&#8217;aimerais attirer votre attention sur un phénomène que j&#8217;observe depuis quelque temps chez certains de nos clients : le wannabisme agile.</p><p>A quoi reconnaît-on un projet wannabe agile ? Le plus souvent à la rupture sémantique qui s&#8217;opère entre l&#8217;équipe technique, chargée du développement, et la maîtrise d&#8217;ouvrage, cliente du développement. Les membres de la première s&#8217;évertuent à adopter les signes extérieurs de l&#8217;agilité &#8211; cycles courts, tests unitaires, intégration continue, contrôle qualité, etc. &#8211; quand les seconds ignorent tout des principes du développement itératif et incrémental, et ne voient dans l&#8217;organisation du projet qu&#8217;une aberration supplémentaire, qu&#8217;ils affublent le plus souvent d&#8217;un qualificatif d&#8217;ordinaire réservé aux maisons de joie : <i>&laquo;&nbsp;ce projet, c&#8217;est le bordel!&nbsp;&raquo;</i>.<p/> Quelques signes permettent d&#8217;identifier rapidement le wannabisme agile.<p/> Un projet wannabe agile fonctionne souvent par itérations courtes &#8211; d&#8217;une durée rarement inférieure au mois, cependant, et plus probablement de l&#8217;ordre de 6 à 8 semaines -, mais le contenu des itérations suit un plan précis, établi au préalable. On parle en général de <i>lots</i>. Chaque lot a été précisément circonscrit lors des phases de spécification, et son contenu a été contractualisé au même titre que sa date de livraison. Le démarrage d&#8217;un lot de développement est entièrement conditionné par la validation préalable des spécifications détaillées de son contenu, et il n&#8217;est pas rare, dans un projet wannabe agile, que la livraison d&#8217;un lot subisse certaines avaries : variation imprévue de périmètre, retard de livraison, qualité médiocre attribuée en générale au manque de temps.<p/> L&#8217;équipe wannabe agile s&#8217;efforce d&#8217;utiliser l&#8217;outillage nécessaire au développement incrémental : test unitaires (généralement JUnit), tests fonctionnels (Fitness), refactoring, automates de build et d&#8217;assemblage (Maven), intégration continue (Hudson), contrôles qualités (CheckStyle, Metrics,etc.)&#8230; Mais ses efforts se heurtent très souvent aux contraintes du planning : sous la pression des livraisons, les tests unitaires se raréfient, puis disparaissent. Personne ne comprend plus vraiment à quoi peut bien servir Fitness, dont l&#8217;usage est tout bonnement abandonné. L&#8217;intégration continue a du mal à fonctionner, et est rapidement ressentie comme une lourdeur inutile. Checkstyle est temporairement désactivé : trop de rouge, on le réactivera quand on aura le temps de faire les corrections&#8230; Inéxorablement, le développement accumule une dette technique qui ne sera jamais épongée.<p/> Le chef de projet de l&#8217;équipe wannabe agile est sommé, parfois à son corps défendant, de fournir un diagramme de Gantt complet et correctement ajusté sur les 6 prochains mois. Les jalons en sont bien sûr ceux du contrat initial de lotissement. Il utilise pour le bâtir la méthode dite <i>du chausse-pied</i> dont les résultats, bien que farfelus, ont le mérite de satisfaire son management.<p/> Faute d&#8217;une organisation adéquate, l&#8217;équipe wannabe agile est incapable d&#8217;identifier le sponsor fonctionnel (celui que la littérature anglo-saxone désigne sous le nom <i>Product Owner</i>). Dans le meilleur des cas, il est identifié mais inaccessible&#8230; La mort dans l&#8217;âme (et encore, pas toujours !), elle attend donc la validation définitive des spécifications détaillées avant de démarrer ses développements.<p/> Le projet wannabe agile est en général dysfonctionnel : faute d&#8217;un alignement global, compris et accepté de tous, sur les paradigmes du développement itératif et incrémental, l&#8217;introduction homéopathique des pratiques agiles risque de passer pour du simple amateurisme ; symétriquement, privé de ses poumons &#8211; collaboration étroite avec les utilisateurs, <i>product backlog</i> proprement alimenté, itérations de durée fixe et dont le contenu est déterminé en fonction de la capacité de production de l&#8217;équipe, <i>feedback</i> technique et fonctionnel permanent, mesure d&#8217;avancement systématique -, le développement wannabe agile est condamné à l&#8217;asthme, puis à l&#8217;asphyxie.<p/> Que penser du wannabisme agile ? En règle général, les projets wannabe agiles sont le résultat d&#8217;une initiative exclusive d&#8217;une équipe de développement, voire d&#8217;un chef de projet, qui a obtenu l&#8217;accord plus ou moins tacite de sa direction. Il cherche à obtenir les fruits du développement incrémental &#8211; maîtrise des coûts, qualité de la production, tolérance au changement, adéquation aux besoins &#8211; sans bénéficier de l&#8217;écosystème indispensable à la réussite d&#8217;une telle initiative. Faute de soutien actif de sa hiérarchie et de la collaboration étroite de la maîtrise d&#8217;ouvrage, cette initiative est vouée à l&#8217;échec &#8211; au risque de la décrédibiliser durablement.<p/> La mise en place de Scrum est l&#8217;affaire de quelques heures. Mais l&#8217;adoption d&#8217;une méthode de développement itératif et incrémental nécessite une véritable révolution culturelle dans la gestion de projet informatique, révolution qui déborde largement du cadre étroit de l&#8217;équipe de développement : les spécifications détaillées écrites doivent être abandonnées au profit des tests, la communication MOA-MOE doit être décloisonnée, les architectes sur piédestal doivent être mis à terre, les pratiques contractuelles castratrices du développement au forfait doivent être proscrites, le planning doit être ajusté en permanence&#8230; C&#8217;est à ce prix qu&#8217;une véritable pratique de développement agile est accessible. Et à ce prix seulement.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/11/22/le-wannabisme-agile/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Off-shoring agile : C&#8217;est difficile, mais ça marche !</title><link>http://blog.xebia.fr/2007/10/31/off-shoring-agile-cest-difficile-mais-ca-marche/</link> <comments>http://blog.xebia.fr/2007/10/31/off-shoring-agile-cest-difficile-mais-ca-marche/#comments</comments> <pubDate>Wed, 31 Oct 2007 14:01:42 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Méthodes agiles]]></category> <category><![CDATA[Off-shoring]]></category> <category><![CDATA[SCRUM]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/10/31/off-shoring-agile-cest-difficile-mais-ca-marche/</guid> <description><![CDATA[L&#8217;offshore est devenu une réalité du développement logiciel. Néanmoins, un grand nombre de projets échouent dans ce domaine faute d&#8217;adopter une approche efficace de la distribution des équipes. Au-delà des avantages strictement financiers, l&#8217;off-shoring amène son lot de complexité et de risques, et ouvre des boulevards aux gaspillages de toute sorte. Ce billet, librement traduit [...]]]></description> <content:encoded><![CDATA[<p>L&#8217;offshore est devenu une réalité du développement logiciel. Néanmoins, un grand nombre de projets échouent dans ce domaine faute d&#8217;adopter une approche efficace de la distribution des équipes. Au-delà des avantages strictement financiers, l&#8217;off-shoring amène son lot de complexité et de risques, et ouvre des boulevards aux gaspillages de toute sorte.<p/> Ce billet, librement traduit de mon excellent collègue indien Vikas Hazrati (<a
href="http://www.theserverside.com/news/thread.tss?thread_id=45367">billet original sur TheServerSide</a>), vise à présenter comment Xebia réussit à faire fonctionner les projets off-shore en s&#8217;appuyant sur les principes du Toyota Manufacturing Process, connu également sous le nom de &laquo;&nbsp;Lean&nbsp;&raquo;. Nous appelons cette méthodologie &laquo;&nbsp;Lean Agile Off-shoring&nbsp;&raquo;.<p/> Davantage que des économies de bouts de chandelle, notre objectif, lorsque nous avons fondé notre filiale indienne, était de bénéficier de la somme de talents disponibles en Inde pour développer plus rapidement des logiciels de meilleure qualité. Pour gérer les projets, nous avons choisi d&#8217;adopter Scrum en raison des solides compétences que nous possédons dans ce domaine, et des succès que nous avons rencontrés dans la conduite de projet agiles avec Scrum. Les principes du &laquo;&nbsp;Toyota Way of Working&nbsp;&raquo; &#8211; que l&#8217;on peut au demeurant appliquer à tout type de développement logiciel &#8211; nous ont permis d&#8217;ajuster le modèle pour obtenir aujourd&#8217;hui un processus de développement mature et doté de mécanismes organiques d&#8217;amélioration perpétuelle &#8211; en un mot, Lean.<p/><p>Le projet sur lequel cette méthodologie a été mise au point est la refonte d&#8217;un système de traitement automatisé appartenant à une administration centrale hollandaise. Le système traite certaines données salariales en provenance des employeurs et d&#8217;autres en provenance du système de taxation sur le revenu. Il valide ces données puis crée automatiquement la déclaration de revenu pour la période considérée. Le système traite 16 millions de transactions par mois, avec un débit d&#8217;environ 50 transactions par seconde.<br/><br
/> L&#8217;équipe était composée de 14 personnes, 6 en Europe, 8 en Inde.</p><p>La suite présente un ensemble de principes qui ont émergé de cette expérience, et qui nous permettent aujourd&#8217;hui de mener des projets de toute taille avec un niveau de productivité et de qualité qui nous épate nous-mêmes !</p><h3>Principe #1 &#8211; Définir une philosophie à long terme et s&#8217;y tenir</h3><p>Le projet a été démarré avec une idée en tête : il ne serait pas une initiative isolée, mais un laboratoire destiné à asseoir un modèle de développement off-shore hautement productif, stable et reproductible.<br
/> Deux principes immuables en ont découlé :<ul><li>aucun compromis ne doit être fait, jamais, sur la qualité des développements</li><li>toute l&#8217;équipe doit, en permanence, inventer et affiner ses pratiques pour supprimer les pertes de temps et les activités sans valeur ajoutée</li></ul><h3>Principe #2 &#8211; Créer un flot de communication continu</h3><p>Nous avons décidé d&#8217;être agiles dans toutes nos actions, et en conséquence de ne pas suivre un plan défini. Néanmoins, sans plan, il est aisé de s&#8217;égarer en chemin. C&#8217;est là que l&#8217;intégration et la communication continues prennent tout leur sens et jouent un rôle vital.<br/><br
/> Nous avons adopté un modèle consistant à envoyer régulièrement des ambassadeurs (Scrum Master ou développeurs) d&#8217;un site à l&#8217;autre, afin de permettre au contexte client de voyager au-delà des frontières, de renforcer la confiance mutuelle des membres de l&#8217;équipe, et d&#8217;établir cette culture commune indispensable au succès d&#8217;un projet agile.<br/><br
/> La communication a également été facilitée par la mise en place d&#8217;outils de communication permanents sur les deux sites, visant à la construction d&#8217;un véritable &laquo;&nbsp;lieu de travail virtuel&nbsp;&raquo; &#8211; caméras, écrans, micros, tableaux numériques, etc. Parler à un membre de l&#8217;équipe distante ne doit guère demander plus d&#8217;effort qu&#8217;à un collègue local.<br/><br
/> Enfin, un seul référentiel de source était partagé par les deux équipes, avec un système d&#8217;intégration continue pour permettre la détection &#8211; et la correction &#8211; immédiate des problèmes.</p><h3>Principe #3 &#8211; Utiliser un système &laquo;&nbsp;pull&nbsp;&raquo; pour éviter la surproduction</h3><p>Corollaire du principe précédent, il est indispensable de produire le logiciel conformément aux demandes du commanditaire &#8211; le fameux &laquo;&nbsp;product backlog&nbsp;&raquo; de Scrum ; si le backlog est peu fourni, la durée des itérations est réduite, ou le temps ainsi libéré est consacré au refactoring, à l&#8217;amélioration du processus ou des livrables, bref à s&#8217;assurer que le client obtient ce qu&#8217;il veut, au moment où il le veut, et avec des critères de qualité très élevés.<br/></p><h3>Principe #4 &#8211; Niveler la charge (<i>heijunka</i>)</h3><p>Toyota parle d&#8217;éviter le <i>muda</i> (gaspillage), le <i>muri</i> (personnes surchargées) et le <i>mura</i> (irrégularité).<p/> En gardant en mémoire ces objectifs, les principales sources de gaspillage dans un projet off-shore sont : des fonctionnalités superflues, des spécifications inutilement détaillées, des couches de communication superfétatoires entre l&#8217;équipe et le commanditaire, la difficulté à accéder à l&#8217;information, des erreurs non détectées par les tests.<p/> Un soin tout particulier a été porté dans la définition du périmètre d&#8217;une itération, en ne développant que les cas d&#8217;usage connus et sur la base de <i>story cards</i> ne comportant que les détails nécessaires à l&#8217;itération en cours. Le code était développé directement à partir de ces <i>story cards</i>, en s&#8217;assurant que les développeurs, y compris off-shore, aient un contact direct avec le commanditaire.<br/><br
/> Afin de niveler la charge de travail, le <i>sprint backlog</i> (c&#8217;est-à-dire la liste des fonctionnalités qui doivent être développées au cours d&#8217;une itération) était systématiquement établi en conformité avec la vélocité observée de l&#8217;équipe. Il n&#8217;y a rien de plus contre-productif à moyen terme que de maintenir une équipe de développement sous la pression d&#8217;une charge de travail supérieure à sa capacité de production &#8211; cela revient à étrangler la poule aux œufs d&#8217;or et se traduit généralement par une baisse massive de la qualité et de la motivation.<p/> Mesurer la vélocité réelle de l&#8217;équipe, et prévoir la charge en conséquence, est une activité critique.</p><h3>Principe #5 &#8211; Stopper le développement pour régler les problèmes</h3><p>Nous avons mis en place une culture dans laquelle le travail est interrompu si un problème survient qui met en péril la qualité de la production.<p/> Lorsque les équipes distantes/locales ont eu le sentiment que leur communication n&#8217;était pas satisfaisante, nous avons mis en place une machine de communication continue de chaque côté, dotée de haut-parleurs et de vidéo.<p/> Lorsque les équipes ont déterminé que les revues de <i>sprint</i> ne donnaient pas les résultats attendus, nous les avons interrompues, avons déclenché une séance de brainstorming avec tous les membres de l&#8217;équipe, et avons mis en place une nouvelle méthode permettant en particulier de consacrer moins de temps à la revue.<p/> S&#8217;il y avait un problème avec l&#8217;intégration continue ou les tests de performance, nous réglions le problème avant de poursuivre le développement de fonctionnalités additionnelles.<p/> Quand les testeurs fonctionnels ont manqué de temps pour tester le flot de fonctionnalités développées, nous avons suspendu les développements fonctionnels le temps que l&#8217;équipe de test absorbe son trop-plein.<p/> Cette culture a non seulement permis de mettre en place rapidement des contre-mesures, mais a également amené à anticiper certains problèmes et à s&#8217;ajuster en conséquence.</p><h3>Principe # 6 &#8211; Standardiser les processus communs</h3><p>La standardisation est la base de l&#8217;amélioration continue ; elle permet de diffuser l&#8217;expérience des uns dans la pratique des autres, de responsabiliser les membres des équipes, de promouvoir l&#8217;apprentissage organisationnel. Le standard, cependant, n&#8217;est jamais gelé : il reste au service des objectifs du projet, et doit être mis en question chaque fois qu&#8217;il va à son encontre.<p/> Nous avons mis en place des processus standardisés pour le développement à base de test (TDD), pour la gestion des demandes et la résolution des incidents, pour l&#8217;assemblage et pour les tests. En aucun cas, bien sûr, ces processus n&#8217;étaient figés : ils étaient aussi agiles et vivants que le reste du projet. Simplement, leur existence permettait de démarrer sur une base stable, et de fournir le socle de la culture de l&#8217;équipe &#8211; et un point de départ pour les améliorations futures.</p><h3>Principe #7 &#8211; Utiliser des contrôles visuels</h3><p>Une devise simple : tout doit toujours être visible pour tout le monde dans l&#8217;équipe &#8211; et cela inclut bien sûr le commanditaire.<p/> Le <i>product backlog</i>, géré dans Jira, était commun aux équipes locales et distantes, de même que les diagrammes de suivi (<i>burn down chart</i>) et les états d&#8217;avancement quotidien &#8211; le tout ouvert au client. Même transparence pour le système de gestion des bugs, dans lequel le client pouvait d&#8217;ailleurs déclarer les incidents d&#8217;exploitation. Le système d&#8217;intégration continue (Cruise Control) déclenchait un build complet à chaque <i>check-in</i> &#8211; avec un retour visuel sur le statut du build et une alarme sonore en cas d&#8217;échec du build.<p/> Les murs et tableaux &#8211; physiques ou virtuels &#8211; comportaient suffisamment d&#8217;information visuelle pour que n&#8217;importe quel commanditaire puisse prendre connaissance de l&#8217;état du projet en moins de 10 minutes.<p/> D&#8217;une façon générale, quelques codes visuels simples et partagés sont le meilleur moyen de s&#8217;assurer que tout le monde possède un niveau d&#8217;information adéquat.</p><h3>Principe #8 &#8211; Utiliser des technologies adaptées à l&#8217;équipe et aux processus</h3><p>Un véritable projet <i>lean</i> possède deux vertus cardinales.<p/> Tout d&#8217;abord, il transfert un maximum de tâches et de responsabilités aux développeurs &#8211; ce sont eux qui sont chargés de créer la véritable valeur ajoutée du projet ; ensuite, il possède, nous l&#8217;avons vu, les boucles de rétroaction permettant de détecter et régler les problèmes le plus tôt possible.<p/> Les individus sont la principale richesse d&#8217;un projet agile ; c&#8217;est donc à eux de décider et d&#8217;adapter la technologie pour qu&#8217;elle satisfasse leurs besoins &#8211; et non la technologie qui dicte la façon dont les choses doivent être faites. Par exemple, nous avons migré toute la logique de présentation de Struts à Spring MVC par ce que cela faisait plus de sens dans le contexte, et que l&#8217;équipe s&#8217;était mise d&#8217;accord sur cette évolution. Les meilleures décisions techniques sont prises par l&#8217;équipe, et non, comme c&#8217;est trop souvent le cas, par un panel d&#8217;architectes autonomes déconnectés des enjeux du projet.</p><h3>Principe #9 &#8211; Privilégier le leadership interne</h3><p>Les individus sont, répétons-le, la principale richesse d&#8217;un projet.<p/> Dans ce projet off-shore, nous étions décidés à promouvoir les leaders à l&#8217;intérieur même de l&#8217;équipe. Plutôt que d&#8217;engager des <i>scrum masters</i> externes, nous avons donc envoyé certains membres de l&#8217;équipe &#8211; locale et indienne &#8211; suivre une formation de <i>scrum master</i> &#8211; et nul besoin de préciser que ce sont eux qui connaissaient le mieux l&#8217;équipe et ont su le mieux développer leur leadership dans le respect des autres.</p><h3>Principe #10 &#8211; Développer un esprit d&#8217;équipe</h3><p>Une communication sans tabou, un travail efficace, une faible spécialisation des rôles, un bon salaire, les meilleurs outils et matériels, un environnement de travail agréable, un équilibre vie personnelle &#8211; vie professionnelle préservé, un perfectionnement continu, une bonne rotation des responsabilités. Voici quelques uns des éléments qui, mis en œuvre avec intelligence et tact, permettent de créer des équipes ultra-performantes.<p/> Une communication saine entre les différentes localisations est un élément clé du succès dans un projet off-shore. Pour gérer cela nous avons, dès le début du projet, favorisé les visites sur le site pair, afin de créer les relations inter-personnelles nécessaires, et avons par la suite régulièrement réitéré ces échanges afin de maintenir la cohésion &#8211; ces voyages, bien sûr, n&#8217;avaient pas pour but d&#8217;accélérer la production, mais de maintenir un climat sain entre les deux sites.<p/> Les gens sont souvent découragés &#8211; ou peu enclins &#8211; à poser des questions, à parler des problèmes, à mettre en garde contre des objectifs improbables ou à proposer des alternatives aux propositions faites par leurs supérieurs. Nous avons activement promu une culture du questionnement et de la pro-activité. Une fois que les membres de l&#8217;équipe eurent réalisé qu&#8217;ils avaient la liberté, et la responsabilité, de prendre des décisions, ils sont devenus des contributeurs actifs, et des co-équipiers remarquables.</p><h3>Principe #11 &#8211; Développer les relations avec partenaires et fournisseurs comme des extensions de votre propre entreprise</h3><p>Etablir une relation honorable et honnête avec partenaires et fournisseurs est l&#8217;un des piliers du Toyota Way of Working.<p/> Nous avons autant que possible suivi ce précepte en ouvrant Wiki et Jira au commanditaire et aux sociétés tierces chargées de développer d&#8217;autres modules du même projet. Avantage immédiat, une confiance spontanée dans notre travail : nous n&#8217;avions rien à cacher.<p/> Non seulement cette transparence a permis de légitimer notre modèle de développement off-shore, mais elle a également permis d&#8217;échanger et d&#8217;apprendre de nos partenaires.</p><h3>Principe #12 &#8211; Mettre la main à la pâte !</h3><p>Il n&#8217;y a rien de mieux que de mettre la main à la pâte pour juger de la situation ; nous n&#8217;avions donc pas d&#8217;analyste fonctionnel dédié, ni d&#8217;architecte je-sais-tout (Architectus Matrix) : tout le monde devait coder, et cette activité prenait largement le pas sur toutes les autres. Point.</p><h3>Principe #13 &#8211; Evaluer plusieurs alternatives face à un problème, puis implémenter rapidement celle qui a été choisie</h3><p>Nous avons systématiquement considéré et évalué plusieurs solutions à un problème donné avant d&#8217;en choisir une &#8211; au besoin au travers d&#8217;expérimentations limitées dans le temps ; une fois déterminée la solution appropriée elle était adoptée rapidement et de façon consistante.<p/> Cette approche a pu être mise en œuvre pour toutes sortes de difficultés, dans toutes sortes de domaines : traduction des documents, organisation des journées &#8211; il y a 4 heures de décalage entre l&#8217;Europe et l&#8217;Inde -, choix de bibliothèques ou d&#8217;APIs, etc.</p><h3>Principe #14 &#8211; Devenir une organisation apprenante grâce à l&#8217;introspection permanente (<i>hansei</i>) et à l&#8217;amélioration continue (<i>kaizen</i>)</h3><p>C&#8217;est le principe le plus important, celui qui pilote tous les autres : nous réalisons une évaluation rigoureuse de chaque itération afin de déterminer ce qui fonctionne bien et ce qui pourrait être amélioré &#8211; et comment l&#8217;améliorer. Chaque itération est ainsi plus mature et plus efficace que la précédente.<p/> Nous sollicitons l&#8217;avis immédiat du client et de l&#8217;équipe afin que tout dysfonctionnement soit corrigé sans délai, et qu&#8217;aucun problème ne s&#8217;installe durablement.<p/> En guise d&#8217;astuce, pour chaque problème que nous rencontrons, nous recherchons la cause première en posant cinq fois la question &laquo;&nbsp;Pourquoi ?&nbsp;&raquo;.</p><h3>Conclusion</h3><p>Nous continuons, chaque jour, d&#8217;apprendre et d&#8217;améliorer. La métaphore du développement <i>lean</i> a été appliquée avec succès au développement off-shore. Les principes de Toyota, appliqués au développement logiciel off-shore, offrent un véritable pont vers l&#8217;hyper-productivité et la haute qualité.</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/10/31/off-shoring-agile-cest-difficile-mais-ca-marche/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Top ten des problèmes de performances des applications J2EE (4 &amp; 3)</title><link>http://blog.xebia.fr/2007/10/04/top-ten-des-problemes-de-performances-des-applications-j2ee-4-3/</link> <comments>http://blog.xebia.fr/2007/10/04/top-ten-des-problemes-de-performances-des-applications-j2ee-4-3/#comments</comments> <pubDate>Thu, 04 Oct 2007 06:44:11 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[vidéo]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/10/04/top-ten-des-problemes-de-performances-des-applications-j2ee-4-3/</guid> <description><![CDATA[Nous vous proposons aujourd&#8217;hui la quatrième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE. Nous y déroulons le top 10 des problèmes de performances en environnement java&#160;/ J2EE en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir. Cette vidéo [...]]]></description> <content:encoded><![CDATA[<p>Nous vous proposons aujourd&#8217;hui la quatrième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE.<br
/> Nous y déroulons <a
href="http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/">le top 10 des problèmes de performances en environnement java&nbsp;/ J2EE</a> en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir.</p><p>Cette vidéo traite des numéros&nbsp;:</p><ul><li><strong>04&nbsp;: Les bibliothèques tierces</strong></li><li><strong>03&nbsp;: Mauvais usage de la concurrence</strong></li></ul><div
align="center"> <object
width="700" height="350"><param
name="movie" value="http://www.vcasmo.com/swf/vcasmo.swf"></param><param
name="flashvars" value="pid=621"></param><param
name="allowFullScreen" value="true"></param> <embed
src="http://www.vcasmo.com/swf/vcasmo.swf" flashvars="pid=621" allowFullScreen="true" type="application/x-shockwave-flash" width="700" height="350"></embed></object></div> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/10/04/top-ten-des-problemes-de-performances-des-applications-j2ee-4-3/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Top ten des problèmes de performances des applications J2EE (6 &amp; 5)</title><link>http://blog.xebia.fr/2007/09/27/top-ten-des-problemes-de-performances-des-applications-j2ee-6-5/</link> <comments>http://blog.xebia.fr/2007/09/27/top-ten-des-problemes-de-performances-des-applications-j2ee-6-5/#comments</comments> <pubDate>Thu, 27 Sep 2007 06:33:06 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[vidéo]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/09/27/top-ten-des-problemes-de-performances-des-applications-j2ee-6-5/</guid> <description><![CDATA[Nous vous proposons aujourd&#8217;hui la troisième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE. Nous y déroulerons le top 10 des problèmes de performances en environnement java&#160;/ J2EE en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir. Cette vidéo [...]]]></description> <content:encoded><![CDATA[<p>Nous vous proposons aujourd&#8217;hui la troisième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE.<br
/> Nous y déroulerons <a
href="http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/">le top 10 des problèmes de performances en environnement java&nbsp;/ J2EE</a> en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir.</p><p>Cette vidéo traite des numéros&nbsp;:</p><ul><li><strong>06&nbsp;: Utilisation impropre des caches</strong></li><li><strong>05&nbsp;: Utilisation excessive de la mémoire</strong></li></ul><div
align="center"> <object
width="700" height="350"><param
name="movie" value="http://www.vcasmo.com/swf/vcasmo.swf"></param><param
name="flashvars" value="pid=620"></param><param
name="allowFullScreen" value="true"></param> <embed
src="http://www.vcasmo.com/swf/vcasmo.swf" flashvars="pid=620" allowFullScreen="true" type="application/x-shockwave-flash" width="700" height="350"></embed></object></div> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/09/27/top-ten-des-problemes-de-performances-des-applications-j2ee-6-5/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Top ten des problèmes de performances des applications J2EE (8 &amp; 7)</title><link>http://blog.xebia.fr/2007/09/19/top-ten-des-problemes-de-performances-des-applications-j2ee-8-7/</link> <comments>http://blog.xebia.fr/2007/09/19/top-ten-des-problemes-de-performances-des-applications-j2ee-8-7/#comments</comments> <pubDate>Wed, 19 Sep 2007 06:44:57 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[vidéo]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/09/19/top-ten-des-problemes-de-performances-des-applications-j2ee-8-7/</guid> <description><![CDATA[Nous vous proposons aujourd&#8217;hui la deuxième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE. Nous y déroulerons le top 10 des problèmes de performances en environnement java&#160;/ J2EE en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir. Cette vidéo [...]]]></description> <content:encoded><![CDATA[<p>Nous vous proposons aujourd&#8217;hui la deuxième d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE.<br
/> Nous y déroulerons <a
href="http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/">le top 10 des problèmes de performances en environnement java&nbsp;/ J2EE</a> en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir.</p><p>Cette vidéo traite des numéros&nbsp;:</p><ul><li><strong>08&nbsp;: Usage incorrect de Java EE</strong></li><li><strong>07&nbsp;: Utilisation abusive du XML</strong></li></ul><div
align="center"> <object
width="700" height="350"><param
name="movie" value="http://www.vcasmo.com/swf/vcasmo.swf"></param><param
name="flashvars" value="pid=619"></param><param
name="allowFullScreen" value="true"></param> <embed
src="http://www.vcasmo.com/swf/vcasmo.swf" flashvars="pid=619" allowFullScreen="true" type="application/x-shockwave-flash" width="700" height="350"></embed></object></div> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/09/19/top-ten-des-problemes-de-performances-des-applications-j2ee-8-7/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Top ten des problèmes de performances des applications J2EE (10 &amp; 9)</title><link>http://blog.xebia.fr/2007/09/13/top-ten-des-problemes-de-performances-des-applications-j2ee-10-9/</link> <comments>http://blog.xebia.fr/2007/09/13/top-ten-des-problemes-de-performances-des-applications-j2ee-10-9/#comments</comments> <pubDate>Thu, 13 Sep 2007 07:11:02 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[Performance]]></category> <category><![CDATA[J2EE]]></category> <category><![CDATA[vidéo]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/09/13/top-ten-des-problemes-de-performances-des-applications-j2ee-10-9/</guid> <description><![CDATA[Nous vous proposons aujourd&#8217;hui la première d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE. Nous y déroulerons le top 10 des problèmes de performances en environnement java&#160;/ J2EE en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir. Cette vidéo [...]]]></description> <content:encoded><![CDATA[<p>Nous vous proposons aujourd&#8217;hui la première d&#8217;une série de cinq vidéos consacrées aux problèmes de performances des applications java / J2EE.<br
/> Nous y déroulerons <a
href="http://blog.xebia.fr/2007/05/03/le-top-10-des-problemes-de-performances-des-applications-j2ee/">le top 10 des problèmes de performances en environnement java&nbsp;/ J2EE</a> en les illustrant par des cas concrets et en proposant pour chacun des mesures permettant de s&#8217;en prémunir.</p><p>Cette vidéo traite des numéros&nbsp;:</p><ul><li><strong>10&nbsp;: Logging excessif</strong></li><li><strong>09&nbsp;: Mauvaise configuration du serveur d&#8217;application</strong></li></ul><div
align="center"> <object
width="700" height="350"><param
name="movie" value="http://www.vcasmo.com/swf/vcasmo.swf"></param><param
name="flashvars" value="pid=616"></param><param
name="allowFullScreen" value="true"></param> <embed
src="http://www.vcasmo.com/swf/vcasmo.swf" flashvars="pid=616" allowFullScreen="true" type="application/x-shockwave-flash" width="700" height="350"></embed></object></div> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/09/13/top-ten-des-problemes-de-performances-des-applications-j2ee-10-9/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Des closures en Java</title><link>http://blog.xebia.fr/2007/05/10/des-closures-en-java/</link> <comments>http://blog.xebia.fr/2007/05/10/des-closures-en-java/#comments</comments> <pubDate>Thu, 10 May 2007 08:28:14 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[closure]]></category> <category><![CDATA[développement]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/05/10/des-closures-en-java/</guid> <description><![CDATA[Le débat autour de l&#8217;introduction des closures dans le langage Java fait rage &#8211; avec toute la mesure et l&#8217;absence de pédanterie dont sait faire preuve notre profession sur ce type de sujet. Selon toute vraisemblance, les closures seront l&#8217;une des fonctionnalités phare de Java 7. Reste à savoir sous quelle forme. Deux écoles ont [...]]]></description> <content:encoded><![CDATA[<p>Le débat autour de l&#8217;introduction des closures dans le langage Java fait rage &#8211; avec toute la mesure et l&#8217;absence de pédanterie dont sait faire preuve notre profession sur ce type de sujet. Selon toute vraisemblance, les closures seront l&#8217;une des fonctionnalités phare de Java 7. Reste à savoir sous quelle forme.<br
/> Deux écoles ont émergé sur le sujet : la première, désignée <em><a
href="http://www.javac.info/">BGGA</a></em> (du nom de ses auteurs et promoteurs, Gilad Bracha, Neal Gafter, James Gosling et Peter von der Ahe), propose une extension syntaxique relativement complexe mais permettant d&#8217;introduire dans le langage tous les idiomes nécessaires à un support des closures similaire à celui disponible dans Ruby ou Smalltalk : function types, free variables, blocks, etc. ; la seconde désignée par l&#8217;acronyme <em><a
href="http://docs.google.com/View?docid=k73_1ggr36h">CICE</a></em> (pour Concise Inner Class Expressions) et soutenue par Joshua Bloch, Doug Lea et &laquo;&nbsp;Crazy Bob&nbsp;&raquo; Lee, propose plus modestement une simplification de la syntaxe java dans le but de désinhiber l&#8217;usage des Inner Class en lieu et place des closures.<br
/> L&#8217;occasion de faire ici un point sur ces deux approches et d&#8217;apporter, sinon une pierre à l&#8217;ouvrage, du moins des éclaircissements sur les termes du débat.</p><p>La définition la plus répandue des closures est la suivante (Neal Gafter fournit un historique des closures <a
href="http://gafter.blogspot.com/2007/01/definition-of-closures.html">dans son blog [en]</a>) :</p><p><em>A <strong>closure</strong> is a <strong>function</strong> that captures the <strong>bindings</strong> of free variables in its <strong>lexical context</strong>.<br
/> </em><br
/> En substance, une closure est un bloc de code référençable, manipulant optionnellement des variables dites &laquo;&nbsp;libres&nbsp;&raquo; &#8211; libres en ce sens qu&#8217;elles sont définies non dans le bloc de code, ni de façon globale, mais par le contexte dans lequel le bloc est exécuté.</p><p>Un peu de code valant souvent mieux qu&#8217;un long discours, voici un exemple très simple d&#8217;utilisation des closures en Ruby (Ruby fait un usage intensif des closures, ce qui est probablement à l&#8217;origine de l&#8217;affection que lui porte ses utilisateurs). Cet exemple est tiré de<a
href="http://www.martinfowler.com/bliki/Closure.html"> l&#8217;article de Martin Fowler sur le sujet [en]</a>.</p><p>Imaginons que vous souhaitiez extraire d&#8217;une liste d&#8217;employés une sous-liste comprenant uniquement ceux qui sont cadres. Une implémentation possible en java est la suivante :</p><pre class="brush: java; title: ; notranslate">
public static List&lt;Employee&gt; managers(List&lt;Employee&gt; employees) {
  List&lt;Employee&gt; result = new ArrayList&lt;Employee&gt;();
  for (Employee e : employees)
    if (e.isManager) result.add(e);
  return result;
}
</pre><p>En Ruby, la même fonction serait codée de la sorte :</p><pre class="brush: ruby; title: ; notranslate">
def managers(employees)
  return employees.select {|e| e.isManager}
end
</pre><p>La méthode <code>select</code> est définie dans la classe Collection de Ruby. Elle prend en paramètre un bloc de code &#8211; la fameuse closure &#8211; , défini entre accolades. Si le bloc de code prend des arguments, ces derniers sont  déclarés entre deux barres verticales (ce sont les variables &laquo;&nbsp;libres&nbsp;&raquo;, dont la portée est définie par le contexte). La méthode <code>select</code> encapsule l&#8217;algorithmique : itération sur la collection, exécution du bloc de code pour chaque élément et construction d&#8217;une sous-liste contenant les éléments pour lesquels le bloc de code s&#8217;évalue à true.</p><p>Il existe bien sûr en Java un mécanisme assez similaire, autorisé par l&#8217;usage de classes anonymes imbriquées (Anonymous Inner Class, ou AIC).<br
/> Supposons que la classe <code>List</code> possède, symétriquement à sa contre-partie Ruby, une méthode <code>select</code>, prenant en paramètre une interface définie comme suit :</p><pre class="brush: java; title: ; notranslate">
interface Filter&lt;T&gt;(){
  public boolean accept(T e);
}
</pre><p>Alors le code java pourrait s&#8217;écrire comme suit :</p><pre class="brush: java; title: ; notranslate">
public static List&lt;Employee&gt; managers(List&lt;Employee&gt; employees) {
  return employees.select(
    new Filter&lt;Employee&gt; {
      public boolean accept(Employee e){
        return e.isManager();
      }
    }
  );
}
</pre><p>Les AIC sont l&#8217;avatar traditionnel des closures en java. Les API du JDK en font largement usage (pensez aux interfaces <code>Runnable</code>, <code>Comparable</code>, <code>Callable</code> ou <code>TimerTask</code>, qui fournissent des closures aux classes <code>Thread</code> ou <code>Executor</code>, ou encore permettent de configurer les collections). Les Design Patterns callbacks, factories, predicates ou stategies sont des candidats naturels à ce type de construction. Spring, en particulier dans son framework de templates, les exploite à très bon escient pour masquer le caractère fastidieux de certaines API, JDBC en particulier.</p><p>Pour autant, la programmation par closures, très répandue chez les rubyistes, est quasiment inexistante chez les programmeurs java. Le listing ci-dessus fournit une première explication : la syntaxe des AIC, verbeuse à souhait, est propre à décourager les meilleures intentions. Ensuite, le support des AIC dans Java comme mécanisme de closures souffre de sévères limitations : une fois instanciée, une AIC est un objet à part entière, doté d&#8217;une portée qui lui est propre, et partiellement aveugle au contexte qui l&#8217;a créé. En conséquence, les variables ou méthodes sont résolues dans le portée de ce nouvel objet.</p><p>Examinons, pour illustrer ces quelques lignes de Ruby :</p><pre class="brush: ruby; title: ; notranslate">
i = 1;
1.upto(100) { |num| i *= num; }
puts i;
</pre><p>Ce code permet d&#8217;afficher le factoriel de 100. La variable <code>i</code> est définie en dehors de la closure et modifiée dans son corps. Le code java équivalent ne compilerait pas (à supposer qu&#8217;une API similaire soit disponible). En effet, pour qu&#8217;une variable externe soit accédée dans le corps d&#8217;une AIC, elle doit être déclarée <code><em>final</em></code> (la raison sous-jacente est que la variable est copiée dans le contexte de l&#8217;AIC). Elle ne peut donc être modifiée. Cela ne pose pas de difficulté si la variable est d&#8217;un type <em>mutable</em> (comme une liste ou un wrapper), mais peut se révéler problématique s&#8217;il s&#8217;agit d&#8217;un type <em>immutable</em> ou d&#8217;un <em>value type</em> (en particulier les String et les types primaires).</p><p>Voici un exemple type des contorsions nécessaires en java pour contourner cette contrainte :</p><pre class="brush: java; title: ; notranslate">
final int[] numCompares = new int[1];
Arrays.sort(a, new Comparator&lt;Integer&gt;() {
  public int compare(Integer i1, Integer i2) {
    numCompares[0]++;
    return i1.compareTo(i2);
  }
});
System.out.println(numCompares[0]);
</pre><p>C&#8217;est sur ce constat primordial que la proposition <a
href="http://docs.google.com/View?docid=k73_1ggr36h">CICE</a> a vu le jour. Son objet n&#8217;est pas d&#8217;altérer le langage java mais de rendre plus concise la syntaxe de création des AIC (en fait, un sous-ensemble de ces dernières, appelées <em>single-abstract-method-types</em> ou SAM, qui sont en substance des interfaces ne comprenant qu&#8217;une unique méthode).</p><p>Avec la syntaxe proposée par CICE, notre exemple initial serait réécrit de la sorte :</p><pre class="brush: java; title: ; notranslate">
public static List&lt;Employee&gt; managers(List&lt;Employee&gt; employees) {
  return employees.select(
    Filter&lt;Employee&gt; { return element.isManager();}
  );
}
</pre><p>Cette syntaxe dite concise est complétée par une altération des règles d&#8217;accès aux variables locales du bloc appelant (en particulier, celles déclarées explicitement publiques peuvent être assignées dans le corps de l&#8217;AIC).</p><p>Cette approche a bien sûr le mérite de la simplicité puisqu&#8217;ellle n&#8217;introduit aucun nouveau concept et ne nécessite pas la réécriture des API existantes ; elle pourrait de surcroît probablement être implémentée à l&#8217;aide d&#8217;une modification mineure du compilateur.</p><p>Pour certains, cependant, l&#8217;approche CICE ne fait qu&#8217;effleurer le sujet et ne propose qu&#8217;une mise à disposition minimaliste des closures en Java.</p><p>En effet, d&#8217;une façon générale, les AIC rompent le contexte d&#8217;exécution du code appelant et ne permettent pas de conserver la sémantique d&#8217;un nombre important de structures syntaxiques (celles que Neal Gafter appelle &laquo;&nbsp;lexically scoped language constructs&nbsp;&raquo;) :</p><ul><li>noms des variables</li><li>noms des méthodes</li><li>noms des types</li><li>signification de <code>this</code></li><li>noms des labels</li><li>référent d&#8217;une instruction <code>break</code> sans label</li><li>référent d&#8217;une instruction <code>continue</code> sans label</li><li><code>checked exceptions</code> déclarées ou interceptées</li><li>référent d&#8217;une instruction <code>return</code></li><li>et quelques autres plus exotiques (état d&#8217;assignation des variables, <code>reachability</code>, …)</li></ul><p>La proposition BGGA est une extension du langage java permettant la mise en oeuvre des closures sans rupture de transparence. La syntaxe proposée par BGGA est loin d&#8217;être triviale, ce qui lui vaut de nombreuses critiques – ses contempteurs sont au demeurant souvent les partisans de CICE.</p><p>Sans entrer dans le détail (qui peut être consulté sur le site <a
href="http://www.javac.info/">http://www.javac.info/</a>), on retiendra les caractéristiques suivantes :</p><ul><li>BGGA définit une syntaxe permettant de déclarer des closures littérales ressemblant à ça :<pre class="brush: cpp; title: ; notranslate">
{int x, int y &gt; x+y}
</pre></li><li>BGGA définit également le concept des <em>function type</em>, dans lequel une fonction possède une liste d&#8217;arguments, un type de retour et une clause <em>throws</em> ; on peut instancier un <em>function type</em> à l&#8217;aide d&#8217;une closure littérale compatible</li><li>la transparence lexicale est intégralement garantie, tant pour l&#8217;association de variables que pour la résolution de noms ou les structures de contrôle (<code><em>break</em></code>, <code><em>continue</em></code>, <code><em>return</em></code>) – certaines closures peuvent cependant être marquées <em>restricted</em> et se comporter de façon identiques aux AIC</li><li>BGGA propose une grammaire simplifiée permettant d&#8217;exploiter les closures selon une syntaxe très proche de celle des structures de contrôle natives du langage – avec une telle syntaxe, la modification du langage pour introduire la seconde forme de boucle <code><em>for </em></code>aurait été superflue</li></ul><p>Avec BGGA, l&#8217;algorithme suivant</p><pre class="brush: java; title: ; notranslate">
lock.lock();
try {
  ++counter;
}
finally {
  lock.unlock();
}
</pre><p>deviendrait</p><pre class="brush: java; title: ; notranslate">
withLock(lock, {=&gt;
  ++counter;
});
</pre><p>dans la forme canonique et, dans la forme simplifiée :</p><pre class="brush: java; title: ; notranslate">
withLock(lock) {
  ++counter;
}
</pre><p>Notre exemple initial pourrait être codé de la sorte (pour peu que l&#8217;API de Collection java se dote d&#8217;une méthode <code>select </code>appropriée) :</p><pre class="brush: java; title: ; notranslate">
public static List&lt;Employee&gt; managers(List&lt;Employee&gt; employees) {
  return employees.select({Employee e =&gt; e.isManager()});
}
</pre><p>Comme évoqué plus haut, la médaille a un revers. Si côté client l&#8217;utilisation des closures BGGA semble relativement simple, la syntaxe risque de considérablement complexifier les API du JDK ou des frameworks désireux d&#8217;en tirer parti. Pour se donner une idée, voici le code de la fonction withLock utilisée plus haut :</p><pre class="brush: java; title: ; notranslate">
public static &lt;T,throws E extends Exception&gt;
T withLock(Lock lock, {=&gt;T throws E} block) throws E {
  lock.lock();
  try {
    return block.invoke();
  } finally {
    lock.unlock();
  }
}
</pre><p>A l&#8217;instar des génériques, qui ont rendu presqu&#8217;illisible au commun le code source de certaines classes du JDK, une telle évolution syntaxique risque de dresser une barrière supplémentaire à l&#8217;apprentissage du langage java, et creuser encore davantage le fossé entre l&#8217;utilisateur d&#8217;API (<em>Joe Java</em>, comme disent certains) et le concepteur d&#8217;API. Le jeu en vaut-il la chandelle ?</p><p>Références (toutes en anglais) :<br
/> [1] <a
href="http://www.javac.info/">La proposition BGGA</a>, présentée par Neal Gafter aux <a
href="http://video.google.com/videoplay?docid=4051253555018153503">Google TechTalks</a><br
/> [2] <a
href="http://docs.google.com/View?docid=k73_1ggr36h">L&#8217;approche CICE</a><br
/> [3] <a
href="http://crazybob.org/2006/10/java-closure-spectrum.html">Un très intéressant échange</a> sur le site de Crazy Bob, partisan de CICE<br
/> [4] Deux articles parus sur developerWorks, le <a
href="http://www-128.ibm.com/developerworks/java/library/j-cb01097.html">premier</a> sur les closures en général, et le <a
href="http://www-128.ibm.com/developerworks/java/library/j-jtp04247.html">second</a> plus spécifiquement sur le débat BGGA vs CICE.<br
/> [5] Un<a
href="http://fishbowl.pastiche.org/2003/05/16/closures_and_java_a_tutorial"> article plus ancien</a>, sur l&#8217;approche traditionnelle des closures en java</ul> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/05/10/des-closures-en-java/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>Codez comme des filles !</title><link>http://blog.xebia.fr/2007/04/11/codez-comme-des-filles/</link> <comments>http://blog.xebia.fr/2007/04/11/codez-comme-des-filles/#comments</comments> <pubDate>Wed, 11 Apr 2007 08:11:36 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[développement]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/04/11/codez-comme-des-filles/</guid> <description><![CDATA[Vous avez sûrement déjà , au moins une fois, en parcourant les sources d&#8217;un logiciel open source été impressionné par la qualité formelle du code : nommage efficace et pertinent, choix judicieux des paquets et de leur hiérarchie, émergence des concepts au travers de la structure, javadoc riche et dénuée de fautes d&#8217;orthographe&#8230; même si [...]]]></description> <content:encoded><![CDATA[<p>Vous avez sûrement déjà , au moins une fois, en parcourant les sources d&#8217;un logiciel open source été impressionné par la qualité formelle du code : nommage efficace et pertinent, choix judicieux des paquets et de leur hiérarchie, émergence des concepts au travers de la structure, javadoc riche et dénuée de fautes d&#8217;orthographe&#8230; même si j&#8217;embellis un peu le tableau pour les besoins du propos, on oublierait pour un peu qu&#8217;il s&#8217;agit du même language que celui utilisé pour développer ce logiciel de gestion aux sources cryptiques dont vous avez hérité la maintenance. En fait, le code source de certains projets open source évoque fortement les fiches bristol que les filles confectionnaient au lycée pour simplifier leurs révisions, vous vous souvenez ? Ces précieuses fiches dont, pour tout dire, vous vous moquiez un peu, mais qui rendaient limpides les cours du semestre précédent quand vous même n&#8217;arriviez plus à  relire vos propres notes. Jamais vu un garçon faire des fiches bristol bariolées. C&#8217;est un truc génétique, je crois, une séquence codante dans la branche manquante du chromosome Y, qui interdit aux mâles l&#8217;usage de l&#8217;encre turquoise et celle de la règle pour souligner les titres.</p><p>La coloration syntaxique et le formattage automatique des sources proposés par les IDE modernes permettent bien sûr, à  peu de frais, de donner au code java l&#8217;apparence formelle des fiches bristol (ce qui, au passage, devrait les réhabiliter définitivement et couvrir de honte rétrospectives les anciens moqueurs). Mais ce travail d&#8217;enluminure textuelle n&#8217;est que rarement suffisant pour masquer la faiblesse des choix de nommage ou l&#8217;insuffisance des commentaires &#8211; quand ce n&#8217;est pas l&#8217;indigence des concepts architecturaux. Pire : il les met en exergue.</p><p>Laissé à lui-même, le développeur mâle standard tend à  se laisser aller à  une négligence peccamineuse, proche dans le principe de la façon dont il prenait ses notes au lycée, et qui transforme rapidement le code source le mieux intentionné en jachère sémantique &#8211; et en cauchemar esthétique. Etant moi même l&#8217;auteur de certaines des lignes de codes les plus vilaines jamais produites dans l&#8217;hémisphère nord (il m&#8217;arrive de faire du Perl), je m&#8217;interroge : pourquoi les développeurs open source (du moins certains) échappent-il à la malédiction ?</p><p>La raison en est probablement très simple : lorsque l&#8217;on développe du code open source, on s&#8217;expose à ce que les sources soient consultées par un nombre indéterminé de pairs à  l&#8217;oeil expert, dont le jugement critique fera ou défera le succès du projet. Alors on tente de produire le plus beau code possible. On renomme 6 fois cette variable. On élague par refactoring. On épure l&#8217;architecture. On formatte la javadoc, un espace ici, un saut de ligne là , et là  une liste à  puces&#8230; Bref, on code comme une fille. C&#8217;est une bête question d&#8217;orgueil, la soif ancestrale de reconnaissance, le besoin de séduire.</p><p>Il resterait, bien sûr, à  tenter de trouver une définition un tant soit peu opérationnelle de ce qu&#8217;est du <em>beau code</em> ; je ne m&#8217;y essaierai pas : les philosophes s&#8217;étripent (symboliquement, bien sûr, ce sont des gens d&#8217;une extrême mesure) depuis des siècles pour définir le <a
href="http://fr.wikipedia.org/wiki/Beau">Beau</a>, et les programmeurs leur ont, à  leur modeste échelle, emboité le pas [1]. Ce qui est sûr, c&#8217;est que la plupart des développeurs ont un jugement très sûr et savent reconnaître le beau code quand ils viennent à  le croiser (ils utilisent le plus souvent le qualificatif d&#8217;<em>élégant</em> pour le désigner). Il arrive même à  certains d&#8217;en produire&#8230; Et s&#8217;il est une vertu que chacun s&#8217;accorde à  trouver au <em>beau</em> code, c&#8217;est qu&#8217;il est facile à  comprendre, à  maintenir et à  utiliser. Des caractéristiques constitutives d&#8217;un logiciel de qualité.</p><p>Certaines pratiques clés de l&#8217;eXtreme Programming, en particulier le <em>pair programming</em> ou les revues de code systématiques ont pour vocation de stimuler en permanence l&#8217;orgueil esthétique des programmeurs en soumettant leur production au regard critique de leurs pairs. Ce n&#8217;est pas pour plomber la productivit des codeurs. C&#8217;est pour qu&#8217;ils produisent du beau code. C&#8217;est pour qu&#8217;ils codent comme des filles !</p><hr
/>[1] Pour d&#8217;autres considérations sur la féminité du code, consultez l&#8217;excellent post de Kathy Sierra <span
class="nobr"><a
rel="nofollow" href="http://headrush.typepad.com/creating_passionate_users/2006/03/code_like_a_gir.html">Coding like a Girl [en]</a></span>.</p><p></p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/04/11/codez-comme-des-filles/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>JOT Première partie : Contextualisation des logs avec log4j</title><link>http://blog.xebia.fr/2007/03/05/jot-premiere-partie-contextualisation-des-logs-avec-log4j/</link> <comments>http://blog.xebia.fr/2007/03/05/jot-premiere-partie-contextualisation-des-logs-avec-log4j/#comments</comments> <pubDate>Mon, 05 Mar 2007 13:05:01 +0000</pubDate> <dc:creator>Guillaume Bodet</dc:creator> <category><![CDATA[Exploitation]]></category> <category><![CDATA[Java / JEE]]></category> <category><![CDATA[JOT]]></category> <category><![CDATA[log]]></category> <category><![CDATA[log4j]]></category> <guid
isPermaLink="false">http://blog.xebia.fr/2007/03/05/jot-premiere-partie-contextualisation-des-logs-avec-log4j/</guid> <description><![CDATA[Ce billet est le premier d&#8217;une série décrivant les principes et composants du &#171;&#160;Java Operations Toolkit&#160;&#187;. JOT est un projet encore embryonnaire (je le publierai bientôt sous license Open Source, et sous un autre nom, JOT étant déjà pris&#8230; Si certains parmi vous ont une idée&#8230;). Son objectif est d&#8217;offrir aux applications java un ensemble [...]]]></description> <content:encoded><![CDATA[<p>Ce billet est le premier d&#8217;une série décrivant les principes et composants du &laquo;&nbsp;Java Operations Toolkit&nbsp;&raquo;. JOT est un projet encore embryonnaire (je le publierai bientôt sous license Open Source, et sous un autre nom, JOT étant déjà pris&#8230; Si certains parmi vous ont une idée&#8230;). Son objectif est d&#8217;offrir aux applications java un ensemble d&#8217;utilitaires, d&#8217;API et de bonne pratiques visant à en faciliter l&#8217;exploitation.</p><p>Comme son titre le suggère, ce premier billet concerne la journalisation, connue également sous son sobriquet anglo-saxon de &laquo;&nbsp;log&nbsp;&raquo;.<br
/> Depuis plusieurs années maintenant, l&#8217;utilisation d&#8217;un framework dédié pour gérer les logs s&#8217;est généralisée. Log4j a ouvert la voie, suivi par framework java.util.logging à partir du JDK 1.4, qui adopte une architecture très similaire à celle de log4j, tout en proposant une nomenclature moins intuitive (du moins pour ceux qui pensent que &laquo;&nbsp;DEBUG&nbsp;&raquo; désigne un niveau de journalisation plus évident que &laquo;&nbsp;FINEST&nbsp;&raquo;). Citons également les meta-frameworks Commons Logging et SLF4J, qui offrent une couche d&#8217;adaptation au dessus des différents frameworks pour en unifier l&#8217;usage.</p><p>L&#8217;objet ici n&#8217;est pas de comparer ces différentes solutions : elles sont toutes très proches et offrent toutes les fonctionnalités attendues d&#8217;un utilitaire de logging:</p><ul><li>une API simple et intuitive, style log.debug(message) ou log.info(message)</li><li>une configuration externalisée permettant d&#8217;activer ou de désactiver certaines traces sans intervention sur les sources ou les binaires</li><li>la possibilité de configurer des flux de sortie divers pour les messages (console, fichiers avec rotation, sockets, base de données, JMS, syslog, NTEventLog, etc.), avec une granularité très fine</li><li>la possibilité de configurer le format des messages</li></ul><p>On ne peut que se féliciter de l&#8217;adoption massive de ces frameworks, en particulier du plus illustre d&#8217;entre eux, log4j. Cette adoption a pourtant bien souvent un revers: disposer de ces fonctionnalités a exempté les architectes et développeurs d&#8217;une réflexion réelle sur l&#8217;usage des logs. La politique de journalisation se réduit fréquemment à cette simple directive : &laquo;&nbsp;Utiliser log4j&nbsp;&raquo;, et le code est en conséquence saupoudré plus ou moins densément (selon l&#8217;humeur ou la sensibilité du développeur) d&#8217;instructions du style</p><pre class="brush: java; title: ; notranslate">
Logger log = Logger.getLogger(this.getClass());
	[...]
	log.debug(&quot;Avant call gloubiboulga casimir.isHeureux()=&quot; + casimir.isHeureux());
	casimir.gloubiboulga();
	log.debug(&quot;Après call gloubiboulga casimir.isHeureux()=&quot; + casimir.isHeureux());
	[...]
	catch (Exception ex){
	    log.error(&quot;Une erreur s'est produite&quot;, ex);
	    throw new RealBadThingHappenedException(ex);
	}
	[...]
</pre><p>Plusieurs problèmes dans cette approche:</p><ul><li>le logger utilisé porte le nom de la classe. Il doit être configuré comme tel (y compris avec les mécanisme d&#8217;héritage). Les noms de classe (et de package) n&#8217;ont pas vraiment de sens pour les équipes d&#8217;exploitation, ce qui limite souvent leur autonomie sur la configuration des traces.</li><li>les messages de debug manquent de consistance, et n&#8217;ont de véritable intérêt que pour le développeur au moment de la mise au point de la classe concernée (ce qui, notons-le, n&#8217;est pas critique; par nature, les messages de déboguage ne sont pas destinés aux exploitants).</li><li>si plusieurs threads exécutent simultanément la méthode, les traces seront entrelacées et il sera difficile de rétablir le séquencement des opérations</li><li>le message d&#8217;erreur est laconique et la pile d&#8217;appel, pour utile qu&#8217;elle soit, n&#8217;est interprétable que par l&#8217;ingénierie.</li><li>il n&#8217;y a pas de trace intermédiaire entre DEBUG et ERROR, ce qui limite la capacité de diagnostic en exploitation</li><li>l&#8217;utilisation des API de log tel quel peut poser des problèmes de performance (cf <a
href="http://blog.xebia.com/2007/02/18/ejapp-top-10-countdown-10-excessive-logging/">ce billet</a>)</li></ul><p>Nous nous pencherons aujourd&#8217;hui sur le problème de la corrélation: dans un environnement multithreadé et distribué, comment relier entre eux les messages relatifs à une même interaction?</p><h4>Corréler les logs</h4><p>Dans un environnement multi-threadé, et a fortiori dans un environnement distribué, il est difficile, sinon impossible, de corréler l&#8217;ensemble des traces issues d&#8217;un même traitement ou d&#8217;une même interaction (que l&#8217;on nommera désormais transaction pour plus de clareté). La solution proposée par log4j pour adresser ce problème consiste à placer dans chaque message un identifiant de corrélation unique pour chaque transaction. On trouvera une description de ce principe dans &laquo;&nbsp;Patterns for Logging Diagnostic Messages&nbsp;&raquo;(1).<br
/> Log4j supporte nativement cette contextualisation, aux travers des classes org.apache.log4j.NDC et org.apache.log4j.MDC (ce n&#8217;est pas le cas de java.util.logging; l&#8217;extension de java.util.logging pour supporter les NDC serait néanmoins très simple).<br
/> Pour implémenter ce mécanisme, il suffit donc d&#8217;intercepter le point d&#8217;entrée du système et de fixer l&#8217;identifiant de correlation dans le MDC (ou le NDC).<br
/> Le cas le plus simple est celui d&#8217;une application web, pour laquelle cette interception se fait au moyen d&#8217;un filtre:</p><pre class="brush: java; title: ; notranslate">
public class Log4jMDCServletFilter implements Filter {
	public void doFilter(ServletRequest request,
						 ServletResponse response,
						 FilterChain chain)
					throws IOException, ServletException {
		try {
			if (MDC.get(&quot;CorrelationID&quot;) == null)
				MDC.put(&quot;CorrelationID&quot;, JOTUtils.generateCorrelationID());
			chain.doFilter(request, response);
		}
		finally {
			MDC.remove(&quot;CorrelationID&quot;);
		}
	}
...
}
</pre><p>Il suffit ensuite d&#8217;utiliser le pattern (cf. org.apache.log4j.PatternLayout) suivant pour disposer systématiquement dans les messages d&#8217;un identifiant de correlation :</p><pre class="brush: plain; title: ; notranslate">
%d{ISO8601} [%t] %-5p %c %X{CorrelationID} - %m\n
</pre><p>Il est bien sûr possible de fournir un contexte plus riche (par exemple le nom de l&#8217;utilisateur, le use case, le service, etc.), et ce mécanisme peut servir de base à un filtrage, permettant d&#8217;augmenter le niveau de trace uniquement pour un sous-ensemble de clients ou de contextes.<br
/> Le composant NDC (pour Nested Diagnostic Context) permet quant à lui de gérer une pile de contextes imbriqués.</p><p>Néanmoins, MDC et NDC s&#8217;appuie sur des variables ThreadLocal, limitées donc à l&#8217;espace mémoire de la JVM. Les choses se compliquent donc singulièrement lorsque les interactions sont distribuées et que l&#8217;on souhaite corréler les traces aux travers de plusieurs JVMs.</p><p>Dans un contexte distribué, l&#8217;identifiant de correlation doit être propagé aux différents composants traversés. Il n&#8217;existe malheureusement pas de moyen universel de réaliser cette propagation : elle dépend du protocole utilisé pour réaliser les invocations distantes. Le plus souvent, cependant, la distribution se fera au moyen de RMI/IIOP.<br
/> Le protocole IIOP bénéficie d&#8217;une technologie standard d&#8217;interception: les PortableInterceptors CORBA. Voici donc un moyen de réaliser la propagation transaparente de l&#8217;identifiant de corrélation sur IIOP.</p><p>Premier élément, un intercepteur client chargé d&#8217;enrichir le flux IIOP d&#8217;un contexte spécifique portant l&#8217;identifiant de corrélation:</p><pre class="brush: java; title: ; notranslate">
...
public class CORBAClientInterceptor
	extends org.omg.CORBA.LocalObject
	implements ClientRequestInterceptor {
	private org.omg.PortableInterceptor.ORBInitInfo info;
	private int t_slot;
	private static final long serialVersionUID = -6768740178708556025L;
	public CORBAClientInterceptor(ORBInitInfo info, int t_slot) {
		this.info = info;
		this.t_slot = t_slot;
	}
	public String name() {
		return &quot;JOT Log correlation id propagation - Client Interceptor&quot;;
	}
	public void send_request(ClientRequestInfo ri) throws ForwardRequest {
		org.omg.CORBA.Any any = null;
		try {
			any = ri.get_slot(t_slot);
		}
		catch (org.omg.PortableInterceptor.InvalidSlot is) {
			throw new org.omg.CORBA.INTERNAL(&quot;JOTClientInterceptor : Invalid slot : &quot; + is.getMessage());
		}
		if ( ( any.type().kind().value() == org.omg.CORBA.TCKind._tk_null ) ||
		     ( any.type().kind().value() == org.omg.CORBA.TCKind._tk_void ) )
			return;
		org.omg.IOP.ServiceContext serviceCtx = new org.omg.IOP.ServiceContext();
		serviceCtx.context_id = 995;
		try {
			serviceCtx.context_data = ((String)MDC.get(&quot;CorrelationID&quot;)).getBytes(&quot;UTF-8&quot;);
		} catch (UnsupportedEncodingException e) {
			throw new org.omg.CORBA.INTERNAL(&quot;JOTClientInterceptor : UTF-8 Not Supported : &quot; + e.getMessage());
		}
		ri.add_request_service_context(serviceCtx, true);
	}
...
}
</pre><p>Il faut ensuite un intercepteur symétrique, côté serveur, chargé de décoder l&#8217;identifiant de corrélation et de le placer dans le NDC log4j:</p><pre class="brush: java; title: ; notranslate">
...
public class CORBAServerInterceptor extends LocalObject implements
		ServerRequestInterceptor {
	private static final long serialVersionUID = -5574812890862607150L;
	private org.omg.PortableInterceptor.ORBInitInfo info;
	private int t_slot;
	public CORBAServerInterceptor(ORBInitInfo info, int t_slot) {
		this.info = info;
		this.t_slot = t_slot;
	}
	public String name() {
		return &quot;JOT Log correlation id propagation - Server Interceptor&quot;;
	}
	public void receive_request_service_contexts(ServerRequestInfo ri)
			throws ForwardRequest {
		org.omg.IOP.ServiceContext serviceCtx = null;
		try
		{
			serviceCtx = ri.get_request_service_context(995);
		}
		catch (org.omg.CORBA.BAD_PARAM bp){
			//Le client n'a pas fourni de contexte, on en génère un
			MDC.put(&quot;CorrelationID&quot;, JOTUtils.generateTID());
			return;
		}
		try {
			MDC.put(&quot;CorrelationID&quot;, new String(serviceCtx.context_data, &quot;UTF-8&quot;));
		} catch (UnsupportedEncodingException e) {
			throw new org.omg.CORBA.INTERNAL(&quot;JOTServerInterceptor : UTF-8 Not Supported : &quot; + e.getMessage());
		}
	}
...
}
</pre><p>Et voici la classe d&#8217;initialisation qui permet d&#8217;enregistrer les intercepteurs:</p><pre class="brush: java; title: ; notranslate">
...
public class CORBAInitializer extends org.omg.CORBA.LocalObject implements
		ORBInitializer {
	/**
	 * Log correlation slot id
	 */
	private int t_slot;
	/**
	 * Pre initialization
	 */
	public void pre_init(org.omg.PortableInterceptor.ORBInitInfo info) {
		t_slot = info.allocate_slot_id();
		CORBAClientInterceptor clientInterceptor = new CORBAClientInterceptor(
				info, t_slot);
		try {
			info.add_client_request_interceptor(clientInterceptor);
			// info.add_server_request_interceptor(serverInterceptor);
		} catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName dn) {
			String msg = &quot;Error in initializer: Duplicate name when adding the interceptor : &quot;
					+ dn.getMessage();
			throw new org.omg.CORBA.INTERNAL(msg);
		}
	}
	public void post_init(ORBInitInfo info) {
	}
}
</pre><p>L&#8217;implémentation de ce mécanisme pour d&#8217;autres protocoles dépend bien sût des capacités de ce protocole. Si le protocole est HTTP, il est assez simple d&#8217;ajouter les entêtes adéquates dans les requêtes. Pour d&#8217;autres protocoles, les choses peuvent s&#8217;avérer plus difficile, voire impossible pour des protocoles propriétaires.</p><p>Dans le prochain billet, nous chercherons à centraliser la configuration des catégories et à en simplifier l&#8217;usage.</p><p>Références<br
/> (1) &laquo;&nbsp;Patterns for Logging Diagnostic Messages&nbsp;&raquo; dans &laquo;&nbsp;Pattern Languages of Program Design 3&#8243;, édité par R. Martin, D. Riehle, et F. Buschmann (Addison-Wesley, 1997).</p> ]]></content:encoded> <wfw:commentRss>http://blog.xebia.fr/2007/03/05/jot-premiere-partie-contextualisation-des-logs-avec-log4j/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
