samedi 10 avril 2010

UN BON CODE ...

Dans l'ordre, un bon code
1. passe ses tests avec succès;
2. ne peut être mal utilisé;
3. ne contient pas de redondance;
4. exprime clairement l'intention;
5. est aussi court que possible.

Paraphrase ...
A peu de choses près, les points 1, 3, 4 et 5 sont une citation de
Kent Beck, créateur de l'eXtreme-Programming. Praticien de la programmation par contrat, j'y ai rajouté le point 2. (Qu'est-ce que je ne ferai pas pour citer les travaux de Kent Beck et Bertrand Meyer dans le même billet :o)

... néanmoins utile
J'ai la chance de relire beaucoup de code, de binommer avec de nombreux développeurs et d'enseigner. Dans le cadre de ces activités, cette citation en cinq points m'est très utile. Je m'en sers beaucoup et je la cite souvent. Je dois sûrement passer pour un extrémiste dogmatique et têtu ... (Après tout dans un équipe, il est bon d'atteindre un certain ratio développeur extrémiste / développeur laxiste)

N'empêche qu'il y a beaucoup de sagesse empirique dans cette citation. Entre autre, l'ordre des critères est très important.

1. Tu testeras
Les tests occupent le haut du podium. Un code qui n'est pas testé n'a pas de valeur. C'est du code sans garantie. Toute ligne d'instruction doit être couverte par un test. Cela se vérifie très bien avec les outils d'analyse de la couverture structurelle.

2. Tu détromperas
Un code qui ne peut être mal utilisé est un code détrompé. Il contribue à la gestion préventive des défauts dans l'application. La programmation par contrat est une excellente pratique pour détromper le code. Quitte à parler de programmation par contrat, il serait plus exacte de dire: "Un bon code garantie sa postcondition si sa précondition est garantie par son appelant". Pour en savoir plus sur cette pratique rare mais vraiment efficace, vous pouvez lire un précédant billet sur ce sujet.

3. Tu ne te répèteras pas
La duplication est source de défauts multiples et de reprises multiples. Elle nuit à la clarté des intentions. Admettons que j'"hérite" d'un code non testé. Sans hésitation, je préfère consacrer du temps à le tester qu'à en éliminer les redondances. (En fait, j'éliminerai les redondances dès que les tests passeront :o)

4. Tu seras clair et explicite
Le code est bien plus souvent lu qu'écrit - y compris par son auteur! D'ailleurs, l'écrivain est avant tout son propre lecteur. Autant faciliter la vie de tous ces relecteurs. Comme pour le point précédant, je préfère tester que renommer et découper. (Pareil, je renommerai et découperai dès que les tests passeront :o)

5. Tu seras bref
La brièveté du code arrive en dernier car elle peut entrer en conflit avec les points 1, 3 et 4. Dans un tel cas de figure, la brièveté n'est pas prioritaire.
Pour rendre un code testable, il faut souvent créer des interfaces pour injecter des dépendances à la construction des objets. Cela augmente la taille du code. Le test amène également à découper en petites classes et il y a un talon déclaratif à payer pour cette modularité.
Un code sans duplication peut amener à créer une opération pour 2 lignes dupliquées. Au total, en comptant le surcroit de déclaration, cette pratique peut augmenter le nombre de lignes. D'ailleurs, avez vous remarqué que les exemples de code remanié sont TOUJOURS plus longs que leur code d'origine? (voir Clean Code)
Pour rendre un code plus explicite, nous sommes amené à homogénéiser le niveau d'abstraction dans le code des opérations. Pour cela, nous encapsulons le code de niveau d'abstraction inférieur dans une opération. Là encore, nous payons une taxe pour la déclaration des opérations.

Et le code des tests?
Ce codex en 5 règles s'applique au code, mais aussi aux tests, car les tests sont du code. On peut penser qu'il ne faut pas tester les tests sinon on n'en finit jamais. Pourtant, la pratique du Test Driven Developpment issue de l'eXtreme-Programming intègre par construction le test du test!
En effet, lorsque nous commençons par écrire un test qui échoue, puis nous modifions le code jusqu'à ce que le test passe avec succès, nous vérifions la justesse du test. Ce tte démarche en 2 étapes est le test du test.

Un de plus (violation du critère 3!)
Désolé, ceci était le 1379ème billet visant à définir un bon code. Plusieurs livres y consacrent leurs pages. C'est un peu comme les chaînes de chance/malchance. Lorsqu'on lit un de ces billets, on se doit d'en écrire un à son tour ...

5 commentaires:

  1. Merci de partager ton expérience.
    C'est la première fois quoi que j'entends parler d'un ratio développeur extrémiste / développeur laxiste.
    Je suis curieux de savoir comment tu l'argumentes et quel serait d'après toi le ratio idéal?

    RépondreSupprimer
  2. Avec le recul, je regrette d'avoir utilisé le terme "développeur laxiste". "Laxiste" est bien trop fort et péjoratif ...

    En fait, l'idée est qu'il est bon d'avoir au moins un "développeur extrémiste" dans une équipe. Il tirera la sonnette d'alarme lorsque certaines pratiques (comme les tests) ne seront plus appliqués correctement.

    Ceci déclenchera un discussion dans l'équipe et l'"extrémiste" ne lâchera pas facilement le morceau. Pour l'extrémiste, la flemme, la lassitude ou lâcher sur la qualité pour tenir les délais ne sont pas des arguments recevables pour justifier une baisse de qualité ou de discipline de travail.

    Pour le ratio idéal, je dirai qu'un par équipe me semble nécessaire. S'il s'agit du coach de l'équipe alors tant mieux.

    RépondreSupprimer
  3. Merci d'avoir pris le temps d'éclaircir ton point de vue

    RépondreSupprimer
  4. Bjr Manu,
    Après qqes temps passés à revoir du code/ des projets je pense que ces principes ne sont pas suffisant sur le long terme. Tu peux avoir du code qui localement est 'bien', mais qui cependant globalement n'est pas cohérent/intégré dans l'ensemble que forme le logiciel final, ou l'ensemble de logiciels que fournis une entreprise (les briques logicielles étant souvent partagées).
    Du coup, aujourd'hui je m'interroge si ces critères doivent être mis plus en avant que :
    1) tu seras homogène avec le reste du code
    2) tu revisiteras ton architecture régulièrement
    3) tu refactoriseras régulièrement ton code, ton logiciel, ...
    4) tu n'oublieras pas le déploiement et la configuration de ton application
    5) tu mettras à jours tes libraires 3rd party, ...
    6) .....

    J'ai souvent eu l'impression, que sur le long terme, ... ce qui te coute vraiment cher c'est l'enchevêtrement de tes différentes couches logiciels plus qu'une couche particulièrement.
    (Au pire, si l'architecture de ton logiciel est bonne, tu peux réécrire complètement une brique) alors que si une mauvaise pratique c'est mise en place dans un code mal architecturé, il faudra changer tout ton code ... (suis-je clair ??? pas sur :-) )


    Sinon, je suis tout à fait d'accord avec toi sur le développeur extrémiste ... par contre, suivant la personnalité, attention au risque de mise a l'écart du groupe.

    RépondreSupprimer
  5. Patrice Van de Velde16 avril 2010 à 10:14

    Ces critères peuvent aussi servir de critères d'arrêt pour le refactoring.
    C'est une question qui revient souvent, et c'est la réponse qui me semble la plus juste.
    Elle contient une part de subjectif (par ex chaque idée est exprimée clairement) mais cela me semble normal.

    RépondreSupprimer