mikado method

Abstract

One method to refactor easily and painlessly:

  1. define an objective
  2. experiment (steps to reach the objective)
  3. visualize (e.g. draw circles, arrows, … to reach the objective) in order to track the progress of the changes
  4. cancel (e.g. revert) beccause the expirimentations often generate code with bad quality

D’après une étude du « The Crash Report 2011 – 2012« , le coût de la dette technique est estimé à 3,6 millions de dollars pour une unique application de taille moyenne. Réduire cette dette est une nécessité pour pouvoir maintenir et faire évoluer un système d’information. Les développeurs doivent souvent travailler sur un code non testé, difficile à comprendre et à modifier, c’est ce qu’on appelle un « code legacy ».

Faire évoluer un code legacy est souvent considéré comme un art. L’artisan doit maîtriser des techniques et des outils mais aussi bien s’organiser pour ne pas se décourager face à la complexité de la tâche.

Une pratique importante qui est souvent négligée ; le refactoring du code legacy. Sans cette pratique nécessaire, la dette technique s’accumule et le coût des prochaines évolutions et modifications de notre code augmente. Un bon refactoring se fait en petites étapes (des baby steps). Bien souvent, nous n’avons pas le temps de mener des chantiers de refactoring de grande envergure. Nous allons donc privilégier des petites itérations de refactoring tout en ayant un objectif plus global.

Baby steps j’ai dit ! Ce n’est pas toujours aussi simple…

Généralement, on démarre un refactoring en ayant une bonne idée sur le résultat lorsqu’on aura terminé. Mais entre temps, nous allons rencontrer plusieurs difficultés, plusieurs étapes à franchir avant d’arriver au résultat escompté. Notre refactoring à première vue de petite taille, peut durer plusieurs heures, plusieurs jours, voir plusieurs semaines. Bye bye baby steps !

Pendant ce temps, et au fur et à mesure que l’on découvre les difficultés :

  • notre code est souvent dans un état qui ne compile pas.
  • … donc nous ne pouvons pas faire de commit ?
  • … donc nous devons gérer le merge pour mettre à jour notre version en local avec les modifications de nos camarades ?

Personnellement, j’ai parfois abandonné sans aller au bout de mon refactoring. Mais c’était avant de découvrir la Mikado Method !

Mikado Method

Ola Ellnestam et Daniel Brolund proposent une approche intéressante qu’ils ont nommé “Mikado Method” par référence au jeux Mikado. La méthode a été introduite en 2012, puis formalisée dans un livre du même nom en 2014. Au-delà de décrire théoriquement la méthode, le livre est rempli de cas pratiques et d’application dans différentes situations.

La méthode nous permet de :

  • Visualiser l’objectif de notre modification puis les étapes nécessaires pour l’atteindre.
  • Mener notre modification en baby steps en ayant un code qui compile et potentiellement livrable à tout moment.
  • Avoir un historique propre de commits qui correspondent à toutes les étapes par lesquelles nous sommes passés.

Mikado Method est applicable pour formaliser et structurer toute modification ou évolution d’un code existant. Toutefois, elle est particulièrement efficace pour :

  • Mener un chantier de refactoring de taille importante.
  • Améliorer et faire évoluer l’architecture d’un système.
  • Et de façon générale toute modification ou évolution importante qui nécessite une organisation rigoureuse.

Comment ça marche ?

La méthode propose une démarche basée sur quatre concepts clés :

  1. Définir un objectif L’objectif ou “Mikado goal” doit correspondre à une évolution souhaitée de notre système. Ce dernier doit être clair et bien défini dès le début.

    Exemple : Créer une nouvelle bibliothèque à partir d’un code existant pour que je puisse la réutiliser dans d’autres projets sans créer de duplication.

  2. Expérimentation

    Les expérimentations permettent d’avancer dans notre idée de refactoring tout en testant des hypothèses. Nous allons essayer d’appliquer la première idée logique permettant d’atteindre notre objectif. Souvent, nous allons rencontrer un obstacle. Généralement cet obstacle se manifeste par le fait que le code ne compile plus sans devoir faire des modifications plus en amont. Cet obstacle marque aussi la fin de notre expérimentation.

    Exemple : Afin d’extraire une partie de mon code dans une bibliothèque, je vais dans un premier temps essayer de l’extraire dans un nouveau package/projet. Toutefois, je me rends compte que mon code est fortement couplé et que, pour pouvoir répondre à mon objectif, il va falloir casser plusieurs dépendances dans mon code d’origine. Je viens de rencontrer un obstacle. Je dois modifier en amont avant de pouvoir créer ma nouvelle bibliothèque. J’ai donc invalidé l’hypothèse qui consistait à extraire le code et validé une nouvelle hypothèse : il faut casser les dépendances dans mon code d’origine.

  3. Visualisation

    La Mikado Method propose aussi de visualiser notre objectif et nos expérimentations. Ceci permet d’avoir un support pour suivre notre réflexion mais aussi pour l’expliquer à nos collègues. Cette visualisation se fait en utilisant le Mikado Graph

    La visualisation commence par l’objectif du mikado, tout en bas du graphe, représenté par un double cercle. Puis, l’ajout de chaque expérimentation menée sous forme d’un pré-requis à l’étape précédente. Les flèches indiquent le sens du pré-requis.

    Elle permet donc de suivre l’avancement des changements.

    Exemple :

  4. Annulation

    Pour atteindre notre objectif, plusieurs expérimentations sont souvent nécessaires. Chacune est un pré-requis de l’expérimentation précédente.

    La Mikado Method propose d’annuler nos modifications à chaque fin d’expérimentation avant d’implémenter son pré-requis afin de ne pas laisser le code dans un état non utilisable. Comprenez annulation dans le sens “Revert” à travers votre outil de versionning.

    Ce comportement à première vue extrême est le concept le plus important et le plus efficace de la méthode. En effet, en annulant nos modifications lorsque notre expérimentation n’aboutit pas à un code potentiellement livrable, nous évitons tous les problèmes cités au début de cet article. C’est ce qui va nous permettre réellement de faire des “Baby steps”. Il n’est pas facile de « jeter » un code que l’on viens d’écrire. Pourtant, le garder nous expose au risque de vouloir le réutiliser à tout prix. Le but premier d’une expérimentation est d’avoir un feedback, le code qui en résulte peut-être comparé à un PoC qui ne doit pas partir en production.

    Si je reprends l’exemple précédent : lorsque j’expérimente l’extraction de mon code dans un nouveau package, mon code ne compile pas car il est fortement couplé. Je visualise dans mon graphe une nouvelle expérimentation à mener pour casser les dépendances. Puis j’annule mon extraction de code. J’annule tout ce que j’ai fait et je passe à l’inversion des dépendances.

Démarche

Résumons notre réflexion lors de la mise en application de ces quatre concepts :

  • Je commence par visualiser mon objectif et une première expérimentation
  • J’essaie d’implémenter cette première expérimentation
  • Mon code ne compile pas
  • J’identifie une ou plusieurs nouvelles expérimentations à implémenter au préalable
  • J’annule mes modifications pour ne pas laisser le code dans un état non livrable
  • Je visualise la prochaine expérimentation dans mon Mikado Graph
  • J’essaie d’implémenter une nouvelle expérimentation
  • J’annule (Revert)
  • Et ainsi de suite jusqu’à arriver à la dernière expérimentation qui ne nécessite aucun pré-requis, généralement de petite taille, et qui ne représente aucun risque.
  • Cool ! Je viens d’apporter un changement que je peux commit et potentiellement livrer en prod !

Et après ?

  • Une fois arrivé tout en haut du Mikado Graph, je me base sur ce dernier pour continuer mon refactoring en suivant le chemin de haut en bas.
  • À chaque étape implémentée, je résous un pré-requis à l’étape précédente, je commit et je peux donc avancer jusqu’à atteindre mon objectif.

Le processus (Figure 2.1 – du livre « Mikado Method »)

Pendant toute cette démarche :

  • Mon code est resté tout le temps dans un état potentiellement livrable sans aucun problème d’intégration avec les modifications de mes collègues.
  • Je ne me suis pas éparpillé. Je me suis concentré sur une étape à la fois.
  • J’ai visualisé ma réflexion et mon avancement. Toute personne peut savoir ce qui ce passe et ce qui reste à faire en utilisant le graphe. Mes collègues peuvent aussi l’utiliser pour intervenir sur le refactoring. Travailler à plusieurs sur le même sujet est donc facilité.

Conclusion:

La Mikado Method est une approche intéressante pour mener à bien un chantier de refactoring de grande envergure dans de bonnes conditions. Le Mikado Graph est également un bon moyen de faciliter la communication et la collaboration autour d’un même refactoring au sein d’une équipe. Toutefois, l’annulation des modifications à chaque étape n’est pas une démarche naturelle et il faut un temps d’adaptation pour s’approprier la méthode. Couplée aux bonnes pratiques de refactoring, elle apporte une démarche structurante !

Dans un prochain article, nous verrons un exemple concret d’utilisation de la méthode.

Et vous, avez-vous des méthodes ou des astuces pour mener à bien vos chantiers de refactoring ? N’hésitez pas à les partager en commentaire !

Pour aller plus loin je vous propose la lecture du livre de référence par les inventeurs de la méthode.