Cohérence de code : idée en or ou pétard mouillé ?


L'idée du siècle ?

Récemment, j'ai commencé à m'intéresser à des outils permettant d'automatiser le respect des standards d'écriture de code.

Le principe est simple : on les décrit dans un fichier de configuration (type d'indentation, position des accolades, casse…) et l'outil va automatiquement corriger les fichiers qui ne les respectent pas à la sauvegarde.

Je suis immédiatement tombé amoureux de l'idée. C'est tellement compliqué d'avoir du code cohérent à 100%, surtout en équipe, qu'un petit coup de pouce n'est pas de refus.

D'autant plus que la cohérence de code, c'est quand même la base du code propre, le niveau zéro du professionnalisme. Bob Martin, l'auteur du livre Clean Code, disait lui-même :

On veut montrer [aux lecteurs] que des professionnels se sont mis au travail.
Robert C. Martin, Clean Code (2008).

Rien à redire, le débat est clos… Mais pas pour moi.

Une idée pourtant si bonne sur le papier peut vite avoir un impact désastreux sur une codebase.

Parce que la plupart du temps, les personnes qui mettent en place ces standards le font de manière arbitraire et biaisée, sans penser aux effets secondaires, qui sont pourtant assez nombreux :

  • Productivité de l'équipe à la baisse.
  • Des désaccords en permanence parmi les développeurs.
  • Une dette technique qui peut exploser quand les standards choisis ne sont pas aussi bons qu'ils en avaient l'air.
… Alors là il va me falloir des arguments.

Ne vous inquiétez pas, j'en ai.

Mais le but de cet article n'est pas de descendre la cohérence de code, mais de rééquilibrer le débat en essayant comprendre si c'est vraiment important pour votre projet (et pas juste un gadget), et si oui, quelles précautions prendre pour ne pas se planter.


Standards de code

Vous le savez aussi bien que moi, il y a quarante mille manières d'écrire la même chose en programmation.

Il n'y a pas besoin d'avoir des programmes complexes pour le voir. Prenez un truc aussi con qu'une déclaration de variable :

string helloWorld = "Hello World!";

var helloWorld = "Hello World!";

string hello_world;
helloWorld = "Hello World!";

// Ne jamais faire ça
object HelloWorld = "Hello World!";

Tout est tellement personnalisable qu'avec plusieurs personnes et des mois de travail, c'est quasiment impossible que tout soit écrit de la même manière sans s'accorder.

C'est là qu'entrent en jeu les standards de code, des règles décrivant comment le code doit être écrit dans une codebase. Par exemple :

  1. Les déclarations de variables locales doivent être faites avec le mot clef var quand l'initialisation est immédiate.
  2. Les noms des variables locales doivent être écrits en camelCase.
  3. La déclaration et l'initialisation d'une variable locale doivent être faites sur la même ligne quand l'initialisation est immédiate.

3 règles simples, mais qui donnent une ligne directrice suffisante pour qu'à peu près toutes les déclarations soient écrites de la même manière.

var helloWorld = "Hello World!";

On appelle l'ensemble des standards une charte de développeur, la cohérence de code étant le fait de respecter cette charte où que l'on soit dans la codebase.

Bref, un concept simple comparé à ce dont je parle d'habitude, mais qui suffit à diviser la communauté des développeurs… comme d'habitude.


Avantage de la cohérence

La première chose à comprendre est que le compilateur/interpréteur se fout royalement de la cohérence. Nada, que pouic, il s'en tape.

Même si l'optimisation rentre parfois en jeu, les standards sont surtout cosmétiques, et destinés au confort des programmeurs. Ils ne doivent pas être mis dans le même panier que l'architecture de l'application qui est infiniment plus importante.


Meilleure lisibilité

En termes de lisibilité, le nommage des modules est la priorité numéro 1. La cohérence n'est que secondaire, mais peut parfois faire la différence.

La raison vient de l'adaptation de notre cerveau à une certaine manière d'écrire. Si soudeinement je comence a faires plein de faute dans mon articles, vous allez avoir plus de mal à lire.

Ça reste compréhensible, mais le fait de devoir réadapter notre cerveau créer une baisse de performances cognitives.

C'est pareil pour le code, si les standards sont complètement différents d'un fichier l'autre, il faudra un petit temps d'adaptation pour pouvoir le lire de manière fluide.

Et plus les standards s'écartent de ce que l'on a l'habitude de voir, plus c'est frappant.

➔ Ne profitez pas de cet argument pour imposer des standards trop stricts non plus. Du code lisible reste du code lisible, même s'il est écrit un poil différemment.


Argument d'autorité

Les développeurs aiment la bagarre, et peu d'entre nous loupent une occasion de débattre technique, quitte parfois à empiéter sur quelque chose d'un peu plus important : le travail à faire.

Suivre une charte permet de couper court aux débats inutiles, et de s'assurer qu'un développeur ne va pas en faire qu'à sa tête, car ce sont les règles, et les règles sont les règles.

➔ Ne les interrompez pas TOUS non plus, certaines personnes peuvent avoir de bons arguments qui risquent de remettre la charte en question. Écoutez-les !


Revues de code plus ciblées

Les revues de code sont primordiales pour déceler les bugs et sources de dette technique (problèmes architecturaux, duplication…), et de les corriger avant même de passer en phase de tests… en théorie.

En pratique, elles tournent rapidement en revue de style, où l’on ne fait qu'embellir le code des autres sans rien apporter de concret.

Or lorsque le code est propre en permanence, il n'y a plus rien à embellir, ce qui donne plus d'espace pour se concentrer sur les vrais problèmes.


Encadrement des moins consciencieux

Malheureusement, certains développeurs n'ont absolument aucune conscience professionnelle, et ne prennent même pas la peine de s'assurer que ce qu'ils écrivent est cohérent avec ce qu'ils ont écrit il y a dix minutes.

La cohérence permet d'encadrer les personnes qui sortent facilement des sentiers battus, la source numéro un d'une codebase bordélique.

➔ C'est plus ou moins un faux argument, car un développeur qui n'est pas capable d'être cohérent dans ce qu'il écrit lui-même n'aura certainement pas la conscience de respecter les bonnes pratiques bien plus importantes, comme l'architecture ou le nommage.


Inconvénients de la cohérence

On pourrait se dire qu'avec concept aussi simple, on peut clôturer le débat tout de suite. Mais, j'ai quelques tours dans mon sac.


Adaptation compliquée

C'est le revers du premier avantage. Si une charte va totalement à l'encontre des habitudes d'un développeur, son adaptation va être assez difficile, en particulier si elle diverge totalement de son style personnel.

J'ai évoqué la raison au-dessus, mais il y en a une seconde : c'est démotivant de travailler sur du code qu'on n'aime pas.

J'en ai fait les frais il n'y a pas longtemps sur un projet en VB.NET, un langage pas loin du C# dans la structure, mais dont la syntaxe me répugnait tellement que lire mon propre code me demandait un effort beaucoup trop important pour ce que s'est. Je ne m'y suis jamais fait.

public static string Join(string delimiter, string[] values)
{
    if (values == null || delimiter == null)
        throw new ArgumentNullException("Parameters can not be null.");

    if (values.Length == 0)
        return "";

    string res = "";
    int i = 1;

    foreach (string value in values)
    {
        res += value;

        if (i == values.Length)
            continue;

        res += delimiter;    
        i++;
    }
    
    return res;
}
Une fonction pour joindre des chaines de caractères en C#
Public Shared Function Join(ByVal delimiter As String, ByVal values As String()) As String
    If values Is Nothing OrElse delimiter Is Nothing Then Throw New ArgumentNullException("Parameters can not be null.")

    If values.Length = 0 Then Return ""

    Dim res As String = ""
    Dim i As Integer = 1

    For Each value As String In values
        res += value

        If i = values.Length Then Continue For
        
        res += delimiter
        i += 1
    Next

    Return res
End Function
Exactement la même en VB.NET... Il faut aimer.

Cas particulier

C'est le revers du second avantage. Certaines situations particulières peuvent générer des débats houleux, typiquement quand un développeur choisit consciemment de ne pas respecter la charte, mais pour une raison justifiée.

Rien de grave à priori, mais en général, une exception en soulève une autre, puis une autre, et encore une autre, et la charte finie aux oubliettes.

Mais d'un autre côté, c'est dommage de se priver d'une solution potentiellement meilleure de celle imposée, donc…

➔ Soyez flexible et n'ayez pas peur de remettre la charte en question si un standard est trop strict, ou si une nouvelle solution s'avère plus bénéfique.

➔ Ayez la main sur la configuration de l'outil d'automatisation pour lui dire d'ignorer ces cas particuliers.


Perte de temps sur l'esthétique

Chaque seconde qu'un développeur passe à rendre son code cohérent est une seconde à laquelle il ne pense pas aux exigences, parfois pour des bénéfices si minces qu'ils ne justifient pas le temps investi.

➔ Automatiser l'application des standards leur permet d'écrire le code à leur façon, et avoir l'outil qui remet tout au propre après-coup.

➔ Veillez aussi à ne pas être ridiculement strict sur les standards choisis, et laisser le développeur respirer. Qui en a quelque chose à foutre qu'il ait utilisé des tabs au lieu d'espaces ?


Mauvais standards

Tous les standards ne sont pas bons à prendre, et le jour où l’on s'en rend compte, c'est déjà trop tard.

Pourtant, choisir des mauvais standards est assez fréquent, je ne me souviens pas d'un programme où tous mes standards jouaient en ma faveur.

Beaucoup de raisons peuvent être à l'origine de cela : mauvaise connaissance du langage, avis biaisé concernant certaines façons de faire (var *hum* *hum*), et la pire de toutes, des standards horribles déjà présents à votre arrivée sur la codebase.

➔ Mettre en place des standards est un travail sérieux, qui nécessite de la réflexion et des recherches. Trop souvent, je me suis basé sur mes préférences, et je m'en suis bouffé les doigts.

➔ Consultez des personnes qui ont de la bouteille avec le langage, ils sauront vous aiguiller.

➔ Soyez flexible. Si une codebase applique encore des standards qui la rongent de jour en jour, il n'y a pas de cohérence de code qui tienne. On retrousse ses manches et l’on se met au travail !


Moins d'ouverture

À force de suivre une charte, on s'ouvre moins à la nouveauté. On se conforte dans les règles sans aller chercher mieux ailleurs.

C'est facile de tomber dans ce vice, surtout sur une vieille codebase où changer un standard tout en préservant la cohérence demande un travail monstrueux, et souvent injustifié.

➔ Soyez flexible, une fois de plus. Écoutez les membres de l'équipe qui proposent de modifier la charte. Tant qu'il y a un vrai bénéfice et que l'équipe est d'accord, banco !


Maintenance de la documentation

Une charte de développeurs, ce n'est pas juste 3 mots échangés dans un couloir, ça nécessite de maintenir une documentation plus ou moins copieuse, ainsi que la configuration des outils d'automatisation.

Encore du sale boulot qui va finir entre les mains du stagiaire, comme d'habitude.


Verdict ?

Comme quoi, quand on cherche des arguments contre la cohérence de code, on en trouve. Mais, au final, ils peuvent être tous plus ou moins mitigés.

Donc si j'arrive à minimiser tous les inconvénients, c'est forcément un bon deal, non ?

Pas forcément, pour une raison très simple : la cohérence ne résout pas toujours un vrai problème.

Certes, elle permet d'améliorer la lisibilité, limiter les débats inutiles, améliorer les revues de code et limiter les dégâts des développeurs incompétents.

Mais si votre équipe ne souffre pas de ces problèmes, à quoi bon ? En imposant des standards, vous risquez surtout de tomber dans les travers que j'ai cités, tout ça pour n’en tirer aucun bénéfice.

N'oubliez pas cela : les bons développeurs écriront toujours du code élégant et lisible, peu importe leur style.

En revanche, si votre équipe souffre de ces problèmes, alors oui, la cohérence a un vrai avantage.

Et comment je peux savoir ça ?

Ouvrez un fichier, s'il ressemble plus à une soupe de lettre qu'à un fichier source, il y a un souci. Si vous avez envie d'étrangler vos collègues lors des revues de code, pareil.

Se rendre compte du problème n'est pas difficile, mais une fois ça fait, il faut agir immédiatement. Et agir ne veut pas dire pondre une charte de nulle part et démerdez-vous, non.

Je ne vais pas trop en dire, car, SPOILER, c'est le sujet d'un prochain article, mais il y a quelques conseils qui me semblent essentiels pour ne pas faire n'importe quoi :


S'adapter aux développeurs de l'équipe

Souvenez-vous, vous ne faites pas ça pour les performances, la sécurité ou l'architecture, mais pour le confort des programmeurs. C'est probablement la bonne pratique la plus ouverte au débat qui existe.

Souvent, je vois des entreprises qui essayent d'imposer leurs règles à toutes leurs équipes, ou alors les forcer à respecter les standards officiels du langage, mais c'est une erreur. Ils doivent toujours être choisis par ceux qui sont sur le terrain : les développeurs de l'équipe et personne d'autre.


Toujours automatiser (ou alerter)

Ce n'est pas juste un bonus sympa en complément d'une charte de développeurs, c'est obligatoire !

Personne ne peut assurer une cohérence à 100% tout seul, et ceux qui essayent voient leur productivité diminuer pour des bénéfices vraiment négligeables.

Donc n'ayez pas peur de faire un maximum de recherche sur le sujet, car d'expérience, je peux vous dire qu'il vaut mieux n'avoir aucun standard que de mettre le couteau sous la gorge de son équipe.


Être flexible

Je ne le répèterais jamais assez, une charte n'est pas une plaque des 10 commandements. Si l’on se rend compte qu'un standard cause plus de dommages que de bénéfice, il faut le dégager vite fait bien fait.

Attention ! Ça ne veut pas dire de changer la charte sur un coup de tête, mais d'écouter les personnes qui font des propositions justifiées, de peser le pour et le contre et de prendre une décision.


Du coup ?

Ça dépend. Je sais que c'est un peu ringard comme verdict, mais c'est la vérité.

J'ai vu des codebases (et des développeurs) tellement bordéliques que j'ai immédiatement proposé l'idée à peine arrivé dans le projet, et d'autres où je n'ai pas moufté, de peur de passer pour un pinailleur.

Le but de cet article était surtout d'apporter un regard critique sur le sujet, car lors de mes recherches, j'ai remarqué que la plupart des gens ont des positions ridiculement extrêmes.

Je naviguais de : « Sans cohérence, t'es bon pour réécrire ton programme tous les 2 ans »

À : « La cohérence tue l'âme créative des développeurs »

Voilà… Avoir une opinion, c'est top, mais avoir une opinion ET l'esprit ouvert, c'est encore mieux.

Merci d'avoir lu cet article jusqu'au bout, pensez à le partager pour apporter votre soutien au blog 💙 et suivez-moi sur Twitter @ITExpert pour être tenu au courant de mes prochains articles.

Et pour les fanas de code blanc comme neige, voici quelques autres articles :

Quant à moi, je vous laisse, il faut que j'aille butiner quelques fleurs pour ne pas me faire engueuler par ma reine.

À bientôt pour un nouvel article sur le blog des développeurs ultra-efficaces. Tchao !