Affichage des articles dont le libellé est refactoring. Afficher tous les articles
Affichage des articles dont le libellé est refactoring. Afficher tous les articles

jeudi 29 octobre 2015

Refactoring, you're doing it wrong (en)

Some developers consider that refactoring is a huge chunk of work that needs to freeze the repository during a week. A week when every features are broken and rebuilt. Afterwards, another week is needed to merge the new features, once pushing on the central repo is authorized again. That’s so wrong, so costly!

It reminds me a talk by Joshua Kerievsky in which he explains more or less that I would try to remain the shortest time possible in the red while refactoring. With this principle, he keeps the ability to deploy continuously while refactoring the whole system. It’s been revelation for me. I like to feel I can deploy whenever I want, even if I don’t have the need to do so. In fact, I do not want to be in a situation where I block the repository, where I prevent my team mates to commit, where I’m sure I will spend painful hours to merge others changes one by one without feeling safe about it.

The ideas:

  • Refactor in small steps. Consider that you will continuously refactor the application and not perform a big bang refactoring once in a while. Think boy scout rule.
  • Consider refactoring only if you have a decent code coverage on the part you want. If you don’t, start with writing a test harness. At least system tests that will experience the code from the UI and check the outputs or the database. If you want to do refactoring that matters, you have to be damn sure that your are not slaughtering the application.
  • Use your IDE. You have to know every features that lies in the Refactoring menu and use them rather than manual editing. Tooling won’t take any risk and they will ask you if they’re not sure of what they’re doing.
  • Consider the “I build a huge amount of code that will work in parallel of the current system that I’ll branch when it’s ready” only when you have no simpler solution left.

Timebox your refactoring session. I promise you that you can do significant improvement within 30 minutes. Tell yourself that delivery is tomorrow, or in 1 hour or in 30 minutes. It will keep you motivated

(this post is a translation of an older one)

mardi 8 juillet 2014

Refactoring, you're doing it wrong

Ce qui m'énerve avec le refactoring, c'est que certains considèrent que c'est un gros chantier, qu'il faut bloquer la base de code pendant une semaine pendant laquelle on aura cassé toutes les fonctionnalités existantes puis passer une seconde semaine à fusionner toutes les modifs. C'est raide !

Je me rappelle une conf de Joshua Kerievsky dans laquelle il expliquait en gros, si je me rappelle bien, qu'il cherchait à rester le moins longtemps possible dans le rouge lorsqu'il faisait du refactoring. En effet, cela lui permettait de garder la possibilité de faire du déploiement en continu malgré le souhait de refactoriser tout le système. Ç'a été une révélation pour moi. J'aime bien me dire que je suis en condition de déploiement continu, même si c'est loin d'être vrai. Je ne veux pas me mettre dans une situation ou je bloque le répo, ou j'empèche les gens de commiter, où je dois passer un long moment pénible à fusionner les modifications des collègues.

Les idées :

  • Y aller par petites touches. Considérer que le refactoring est quelque chose de constant sur un projet et pas un déploiement big bang auquel on va s'astreindre tous les 36 du mois.
  • Le refactoring se fait s'il y a une couverture de test qu'on estime suffisante. Franchement, rédigez au moins des tests système qui contrôlent que vous n'êtes pas en train de tout défoncer. Si vous n'en n'avez pas un minimum, codez en ou tant pis, laissez le code comme il est.
  • Utiliser les outils de votre IDE. Même un truc tout pourri comme VS2008 possède des fonctionnalités permettant de renommer des éléments, extraire des méthodes, des interfaces. Utilisez les parce qu'ils ne prennent pas de risque. Il vous garantissent dans la plupart de cas l'absence d'erreur.
  • N'envisager l'approche « je refais une grosse merde qui tourne en parallèle du code existant et je la branche quand c'est prêt » que quand vous ne pouvez pas faire plus simple.

Timeboxez vos sessions de refactoring. Je vous promets que vous pouvez faire des trucs sympas en 30 minutes et en faire profiter les collègues. Dites-vous que la livraison c'est demain, dans 1 heure, dans 30 minutes... Motivant, non ?

samedi 17 novembre 2012

Legacy remains legacy




Le code legacy, vous savez tous ce que c'est. Vous arrivez sur un projet, vous
regardez le code et vous faites une grimace.
Je suis sur un projet un peu comme ça. Toutefois, comme je suis joueur, je me
dis : "chouette, il y a pleins d'opportunités d'amélioration, on va bien se marrer !".
Alors sur mes premières interventions, j'ai essayé discrètement de remettre
le code à ma sauce, factoriser un peu tout ça pour faciliter la maintenance.
C'est alors qu'arrive une demande d'évolution nous proposant de réaliser un
tout nouveau module de l'application. C'était le début de l'été, on était à
l'aise... il y avait 2 packages PLSQL à coder. J'ai dit à mon stagiaire d'en
coder un et j'ai gardé le second.

J'ai réutilisé la structure du code existant -c'est une exigence du client-
tout en tentant de l'améliorer : en réduisant la redondance, en essayant de
faire un maximum de fonctions pour que cela reste lisible.
J'ai également écrit les 2 shells de lancement, en poussant les fonctions
communes aux deux scripts dans un troisième fichier. Ça marchait bien,
j'étais vraiment content du boulot qu'on avait effectué et j'étais persuadé
que le client allait être satisfait.

Après l'été, le module entre en VABF. Premiers griefs : qu'est-ce que vous avez
fait dans ce shell ? On y comprend rien, il y a des fonctions partout. En plus
vous avez mis les fonctions communes dans un troisième fichier ! C'est trop en
rupture avec l'existant, ce serait pas mal que vous nous relivriez, après avoir
recopié les fonctions communes dans chacun des deux scripts pour ne pas sourcer
de script externe. Au passage, une remarque en off : c'est pas si mal de factoriser, mais il
faudrait le faire pour toute l'application. Ben voyons, gratos, c'est bien
ça ?

Soupir, respiration, je modifie, je relivre et je me dis que c'est bon...

Peu de temps après seconde remarque : le code du package PLSQL que j'avais
rédigé n'est lui non plus pas conforme. Le style de codage est trop en rupture,
ce qui rend le code non maintenable (sic). Pluies d'anomalies, KPI en berne,
palabre avec le client. On refait le tout.
Il y avait une vraie ano fonctionnelle relativement minime, j'ai quand même
réécrit tout mon code... et ravalé ma fierté.

Essayons de comprendre le client. Celui-ci n'avait pas de TMA depuis plusieurs moi
et a dû prendre en charge évolutions et corrections sans équipe de développeurs
SQL chevronnés. Ceci nécessite de son point de vue :

  • que le style de codage soit uniforme et que tous les modules suivent strictement le même modèle ;

  • que le code soit abondamment (sur)commenté ;

  • que les fonctions un peu compliquées soient évitées. Quand ce n'est pas possible, elles sont très abondamment commentées.


  • En plus, mon code n'était pas cohérent avec celui de mon stagiaire... code qui au
    passage est considéré comme meilleur que le mien (Nassim, si tu nous lis ;-)) !
    Bref, une bonne douche froide et un suppo d'humilité pour moi. Je me remets en
    question, j'hésite à démarrer une thérapie... Je me rappelle d'un passage du
    livre Pragmatic Programmer, celui qui parle du good enough software... et de boiled frog.

    En théorie, les anomalies du client devraient être liées à des tests
    fonctionnels. Le comportement de l'application n'était pas celui attendu. Dans
    mon cas, c'était effectivement le cas, mais je l'ai découvert moi-même par la
    suite. La vraie ano que j'ai eu est "le code est complètement faux".
    Dans les faits, bah, on retouche le code à la demande pour que le client soit
    satisfait, assuré qu'il a une compréhension globale de ce qui est réalisé et
    accepte la livraison. On promet qu'on ne prendra plus les mêmes libertés par la
    suite. C'est la joie de la sous traitance.

    À titre personnel, c'est un peu dur pour moi car je réfléchis toujours
    au façon d'améliorer un système (c'est mon côté geek... ah pardon, lean), d'aller chercher une
    meilleure maintenabilité pour faciliter l'évolutivité (c'est une belle phrase
    ça, ça ferait un bon tweet). Par  exemple, j'imaginais mettre en place un framework pour la
    partie PHP. Une telle idée me fait gentiment sourire aujourd'hui.
    Au final, la situation s'améliore pour moi : à l'heure actuelle je ne code
    quasiment plus pour cette application.
    Dernier mot sur l'histoire de la boiled frog pour ceux qui n'ont pas lu le livre.

    Si vous voulez cuire une grenouille en la plongeant dans une casserole d'eau
    bouillante, celle-ci sautera systématiquement hors de la casserole. Si
    toutefois, vous la mettez dans une casserole d'eau froide que vous portez à
    ébullition, la grenouille restera dans la casserole car elle ne comprend pas
    qu'elle est en train de se faire ébouillanter vivante !

    Si vous bossez avec un client (une MOE) et que vous voulez organiser une évolution en
    rupture dans un système, rappelez vous que vos solutions ne seront jamais
    les bonnes tant que votre client ne se les ait pas appropriées. Faites en sorte
    que vos propositions d'évolution deviennent celles de votre client, que ce soit
    lui qui les porte. À vous d'être suffisamment malin... tout en restant
    honnête à 100%, cela va se soi.



    mercredi 14 mars 2012

    Mikado Method

    J'ai lu ça et là pas mal de choses sur la Mikado Method ces derniers temps. J'ai pu profiter de longues heures de vol pour dévorer le bouquin (je vous ai dit que je possédais un Kindle ?)

    Il s'agit d'une méthode pour faire du refactoring dans du code legacy. On peut la voir comme une amélioration ou une industrialisation au draft refactoring proposé par Michael Feathers dans Working Effectively With Legacy Code (pas de lien, j'ai déjà fait une pub gratos pour Amazon plus haut).

    Vous avez tous joué aux mikados. On a plein de bâtonnets en foutoir et il faut les récupérer un par un sans faire bouger les autres. L'objectif est de récupérer celui avec la spirale bleue appelé... le mikado ! Celui-ci fait gagner plein de points et assure au joueur qui s'en empare de remporter la victoire. Si on fait bouger un autre bâtonnet, on passe son tour et on est frustrer d'avoir à attendre pour recommencer.

    Si on reprend cette analogie, le refactoring proposé par la mikado method s'apparente à jouer au mikado comme un gros bourrin : en essayant de choper le mikado dès le début du jeu ! On ne sait jamais, si cela fonctionne, on aura gagné un paquet de temps et d'énergie...

    Voilà comment ce déroule le processus :

    1. Vous vous fixez votre objectif. Cela peut être d'ajouter une fonctionnalité, ou de diminuer le couplage entre plusieurs composants, etc. Il s'agit de l'objectif final. Il vous semble difficile à remplir directement. Sinon, ce n'est pas drôle.
    2. Vous essayez d'attendre l'objectif directement, réalisant les actions à mener sans vous soucier du reste du code.
    3. Normalement, dans tout bon système legacy (c'est à dire existant depuis plus de deux jours en moyenne...), votre projet ne doit plus compiler car vous avez des erreurs de compilation sur énormément de classes. Cette situation dégage un objectif secondaire : vous devez régler ces problèmes avant de remplir votre objectif principal. Vous le notez.
    4. C'est le plus important et le plus douloureux : vous faites un revert des modifications pour rendre le système à nouveau fonctionnel.
    5. Vous tentez d'atteindre les objectifs secondaires avant l'objectif initial. Si cela ne fonctionne pas, vous dégagez de nouveaux objectifs, faites un rollback et recommencez.
    6. Itérez jusqu'à la mort ou jusqu'à avoir rempli l'objectif principal (ou les deux, comme dirait mon chef).

    J'ai trouvé ça plutôt intéressant et vous incite à lire le livre. Un point fort je trouve est que les auteurs proposent d'accompagner les différentes étapes par la mise en place d'un diagramme montrant les différents objectifs à remplir et les liens entre eux. Ceci permet de faciliter la communication dans l'équipe et de voir l'avancement dans la réalisation de l'objectif initial.

    Je suis arrivé sur un nouveau projet legacy (il a plus de 2 jours), et j'imagine déjà des cas dans lesquels je pourrai utiliser cette Mikado Method !