Du code temporaire qui devient définitif

Publié par Éric Le Merdy
Cette réflexion vient d'un retour qu'on m'a fait sur un programme écrit pour un client. La consultante fonctionnelle qui connaît bien les tables relationnelles de son produit me demande les logs des requêtes SQL éxécutées par mon programme. 

Le problème

Le log transmis, elle observe une curiosité du type : select * from table where table.col1 = 'x' (…) and table.col1 = 'x' (…)
La requête est valide mais cela m'intrigue aussi. Comment en arrive-t-on à écrire un tel ordre et comment éviter que cela ne se reproduise ?
La bonne nouvelle c'est que grâce à la gestion de configuration, la tracabilité est assurée. La modification incriminée est apparue entre le 30/07/2007 14:00 (version 1.2) et le 01/08/2007 11:55 (version 1.3) :

v1.2
select * from table2 where /* table.col1 = 'x' and*/ (...) and table2.col1 = 'x' (...)
remplacement de table2 par table
select * from table where /* table.col1 = 'x' and*/ (...) and table.col1 = 'x' (...)
v1.3 : suppression du commentaite
select * from table where table.col1 = 'x' and (...) and table.col1 = 'x' (...)

Remonter aux origines

C’était l’époque où il y avait une incertitude sur la table source. J’ai donc introduit un commentaire dans la requête SQL sur la première condition (pour me souvenir qu’il serait probable qu'à terme, on filtrerait sur cette table source) avant de rajouter une autre condition que je considérais comme non définitive sur la table2… Après précision du nom de la table à requêter, j'ai supprimé le commentaire sur ma condition 1 sans relire la requête en entier après l’effacement de ces commentaires dans le SQL. Voilà pourquoi il existe aujourd’hui les deux conditions dans la même requête.

Leçons à retenir

  • La gestion de configuration permet de tracer très efficacement les modifications dans le code. Je n’aurais donc pas du mettre la condition en commentaire mais bel et bien l’effacer ! Seulement un commentaire dans le code est plus « visible » qu’une historisation de version. Or, le problème avait vocation à être résolu un jour. Dans ce cas, le commentaire n’agit pas comme une mémoire mais comme un marqueur de problème à résoudre. Et lorsqu’on agit mécaniquement (remplacement en masse), que les tests unitaires passent et que le programme se comporte correctement après résolution, on peut introduire ce genre de bizarerie !
    Typer son commentaire (de type TODO dans eclipse par exemple) est donc préférable car cela permet de :
    • Marquer visuellement dans le code qu’il y a un problème à résoudre
    • Retrouver, le cas échéant, la version historisée à l’aide de l'historisation car ce n'est plus du code en commentaire mais une explication du problème. Si c'est une autre personne qui dépile les tâches TODO, elle saura quoi faire alors que devant un code en commentaire, on ne sait pas quoi faire. Moi, en général, je supprime ce code...
  • Appliquer un principe d'ergonomie : rapprocher visuellement ce qui est lié, car du code est destiné à être relu, c'est donc aussi une représentation graphique ! En effet, pourquoi la seconde condition a-t-elle été placée si loin de la première alors que je savais que la seconde était temporaire et devait disparaître ?
  • Ecrire un commentaire pour se souvenir qu'il faudra changer la condition est du **gaspillage**. Mon programme n'en avait pas besoin pour fonctionner, je devais donc le supprimer. Le refactoring qui allait suivre serait donc plus simple et donc moins soumis à l'erreur.