Duplication de code, refactoring et YAGNI

En développement logiciel, la duplication de code est un problème courant que l'on résout classiquement lors d'une étape de refactorisation. Pour cela, encore faut-il identifier une duplication comme telle et accepter le coût de la refactorisation. En l'occurrence supprimer une duplication peut faire apparaître une abstraction que l'on jugera éventuellement, en se référant au principe YAGNI (You Aren't Gonna Need It), inutile.

La séquence "Right Angles" du jeu Soft(ware)Ball permet de se confronter à ce dilemme.

Cette séquence consiste à faire circuler un ballon en passant par les points A, B, C, D, E et F de l'aire de jeu dessinée ci-dessous.

rightangles1.png


La difficulté réside dans la découverte progressive de ce parcours. Lors de la première étape, on ne connaît l'existence que des points A et B et le trajet du ballon se limite à aller du point A au point B. Lors de la deuxième étape, on découvre le point C, puis le point D apparaît dans la troisième étape, etc.

Lors de la première étape, la majorité des équipes[1] va au plus simple : un composant, appelons-le Nathan est positionné sur le point A et un autre composant, Emma, est positionné sur le point B.
Nathan est programmé avec la règle : "Quand je reçois la balle, je l'envoie à Emma". Cela coûte 2 points et c'est le mieux que l'on puisse faire pour remplir le contrat.
Emma n'a pas besoin d'être programmée car elle attrape implicitement la balle que Nathan lui envoie.

rightangles3.png


Lors de la 2ème étape, le point C apparaît et, là encore, la majorité des équipes va au plus simple. On rajoute un composant "Lucas" sur le point C et on programme Emma avec la règle "Quand je reçois la balle, je l'envoie à Lucas" qui coûte 2 points supplémentaires.

rightangles4.png


On peut continuer cette approche "facile" jusqu'au bout[2] et aboutir à la programmation suivante pour un coût total de 12 points :

  • Nathan : "Quand je reçois la balle, je l'envoie à Emma"
  • Emma : "Quand je reçois la balle, je l'envoie à Lucas"
  • Lucas : "Quand je reçois la balle, je l'envoie à Lola"
  • Lola : "Quand je reçois la balle, je l'envoie à Enzo"
  • Enzo : "Quand je reçois la balle, je l'envoie à Chloé"
  • Chloé : "Quand je reçois la balle, je l'envoie à Nathan"


rightangles5.png

La plupart des équipes, toutefois, choisissent, à un moment donné de refactoriser le code pour supprimer une duplication en introduisant un programme "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche" ou "Quand je reçois la balle, je l'envoie au composant qui est situé à ma droite". Chacune d'entre elles coûte 3 points mais elles sont réutilisables sans aucun coût supplémentaire.

Par exemple, lors de la quatrième étape, on voit facilement[3] que Emma et Lola font exactement la même chose. Une équipe qui déciderait de refactoriser à ce moment là terminerait avec la programmation suivante pour un coût total de 9 points :

  • Nathan : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche" (avec auparavant "Quand je reçois la balle, je l'envoie à Emma" utilisé jusqu'à la 5ème étape)
  • Emma : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche" (avec auparavant "Quand je reçois la balle, je l'envoie à Lucas" utilisé jusqu'à la 3ème étape)
  • Lucas : "Quand je reçois la balle, je l'envoie à Lola"
  • Lola : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
  • Enzo : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
  • Chloé : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"

Le meilleur score possible permet de terminer avec seulement un coût total de 5 points. Pour cela, il faut commencer le refactoring dès la 2ème étape (alors qu'on ne sait même pas s'il va être utile...)

  • Etape 1 :
    • Nathan : "Quand je reçois la balle, je l'envoie à Emma" (2 points)
  • Etape 2 :
    • Nathan : "Quand je reçois la balle, je l'envoie à Emma"
    • Emma : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche" (3 points)
  • Etape 3 :
    • On déplace Nathan au point C, Emma au point D, Lola au point B et Lucas au point A (et positionné perpendiculairement à (AB)) ce qui nous permet de réutiliser l'ensemble des programmes déjà disponibles
    • Lucas : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Lola : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Nathan : "Quand je reçois la balle, je l'envoie à Emma"
    • Emma : rien
  • ...
  • Etape 6 :
    • Lucas : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Lola : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Nathan : "Quand je reçois la balle, je l'envoie à Emma"
    • Emma : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Enzo : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"
    • Chloé : "Quand je reçois la balle, je l'envoie au composant qui est situé à ma gauche"

rightangles6.png
J'ai pu observer des équipes utilisant toutes entre 8 et 12 points pour arriver au bout de cette séquence.
A chaque fois, la question de la refactorisation s'est rapidement posée et les réponses ont été variées : choix de code factorisé en passant à une approche plus générique ou attente de ce qui viendra après.
A chaque fois, ces choix ont été collectifs avec des intentions opposées exprimées au sein de l'équipe.
Cela montre que la notion de code dupliqué n'a pas une définition unique pour tout le monde, surtout si la suppression de la duplication induit un coût non négligeable.

Pour ceux qui voudraient tenter l'expérience, cette séquence peut se jouer en environ une heure (20 minutes de présentation+30 minutes de jeu+10 minutes de debriefing). Le matériel (présentation du jeu, cartes, feuille de score) est disponible sur le site Soft(ware)Ball. C'est d'ailleurs une bonne façon de découvrir le jeu avant d'attaquer des séquences plus difficiles.

Notes

[1] J'ai fait jouer cette séquence lors des Agile Tour Montpellier, Agile Tour Bordeaux, Agile Grenoble.

[2] une équipe l'a fait

[3] ce fut le cas pour toutes les équipes qui ont joué cette séquence