J'ai récemment écrit un article pour présenter le concept de «DRY Programming», que je vous invite à lire si ce n'est pas déjà fait.

En substance, un code «DRY» évite toute sorte de répétition de code en regroupant les morceaux de codes similaires dans des abstractions (classes, fonctions, ...)

Les inconvénients du DRY

En théorie, il est difficile d'avancer que le "Don't Repeat Yourself" est un principe erroné, car la répétition naïve de code est rarement quelque chose de souhaitable dans un projet.

Néanmoins, l'abstraction à outrance, ou simplement la mauvaise abstraction, coûte plus cher que la répétition du code.

C'est notamment ce qu'avance Sandi Metz dans son article "The Wrong Abstration".

Une mauvaise abstraction peut induire (dans le désordre) :

  • De la complexité accidentelle
  • Des fonctions/méthodes trop lourdes ou incompréhensible
  • Du code maintenu uniquement pour soutenir les tests, même si une grosse partie n'est plus actuellement utilisée dans le logiciel
  • De l'aversion à la perte quant au risque de la suppression ou modification du-dit code

Et le WET alors ?

Certaines personnes, comme Conlin Durbin, on essayé de donner du sens à l'inverse du DRY en "créant" le principe WET : Write Everything Twice.

L'idée : Pour éviter l'abstraction inutile de code, s'autoriser à ré-écrire deux copies d'un même morceau de code, et commencer à créer une abstraction à partir de la troisième version.

Si l'idée est charmante en théorie, elle conserve le même travers que son antonyme DRY, c'est-à-dire qu'elle est dogmatique et ne laisse pas suffisamment la place à la réflexion.

On ressent dans ces concepts, comme une odeur de "Cargo Cult" : un principe devrait nous aider à réfléchir, pas se substituer à la réflexion.

Le compromis : le AHA Programming

C'est après avoir compris les contraintes des deux approches précédemment évoquées, que Kent C. Dodds est parvenu à introduire un nouveau concept prônant le meilleur des deux mondes : le AHA Programming (précédemment nommé MOIST, en référence à DRY et WET).

AHA signifie "Avoid Hasty Abstraction", soit "Eviter les abstractions hatîves" en Français

Il se base sur le principe décrit précédemment par Sandi Metz :

"prefer duplication over the wrong abstraction"

En se basant sur le fait qu'on ne connait pas quel sera le futur du code que l'on est en train d'écrire, et qu'il est contre-productif d'optimiser l'entièreté du code derrière des abstractions qui devront peut-être complètement changer à cause de mauvaises assomptions, ou de changement de direction pour la logique métier, Kent suit une directive :

"Optimize for change first" ou "D'abord optimiser pour changements"

Qu'est-ce que cela signifie en réalité ?

Comme nous sommes dans l'inconnu face à l'avenir de notre code, Kent favorise la duplication jusqu'à temps que l'on soit sûr et certains que ces morceaux de code peuvent (et doivent) effectivement être rendus abstraits.

Le risque de commencer l'abstraction trop tôt réside notamment dans le fait que pour chaque ligne, ressemblant de près ou de loin à quelque chose que vous avez déjà rendu abstrait, alors vous essayerez de tordre (modifier) l'abstraction pour coller à votre cas d'usage.

Et ceci, jusqu'à ce que votre fonction, censée simplifier le code, devienne en réalité illisible à force de refactor et d'ajouts de "if" à la chaine, pour prendre en compte tous les cas différents.

Exemple

Comme une ligne de code vaut mieux que mille mots, voici un exemple d'un code trop répétitif, la version DRY, et la version AHA :

À noter que ces exemples sont inspirés de la présentation de Kent C. Dodds pour l'évènement React Summit que je vous invite à regarder !

Base

// user-list.js
const name = user.name ? `${user.name.first.slice(0, 1)}. ${user.name.last}` : user.username ? `@ ${user.username}` : 'Anonymous';
console.log(name);
/*
    Possible Results : 
        - J. Doe
        - @jdoe
        - Anonymous
 */

// profile.js
const name = user.username ? `@ ${user.username}` : user.email;
console.log(name);
/*
    Possible Results : 
        - @jdoe
        - jdoe@example.com
 */

// navbar.js
const name = user.name ? `${user.name.first}. ${user.name.last}` : 'Anonymous';
console.log('Hello', name);
/*
    Possible Results : 
        - Hello John Doe
        - Hello Anonymous
 */

DRY


function getName(user, {firstnameInitial, displayEmailByDefault}){
    let name = 'Anonymous';
    if(user.name) {
        let first = user.name.first;
        if(firstnameInitial){
            first = first.slice(0, 1);
        } 
        name = `${first}. ${user.name.last}`;
    } else if(user.username) {
        name = user.username;
    } else if(displayEmailByDefault){
        name = user.email;
    }
    return name;
}

// user-list.js
console.log(getName(user,{firstnameInitial: true}));

// profile.js
console.log(getName(user, {displayEmailByDefault: true}));

// navbar.js
console.log('Hello', getName(user));

AHA


function getFullName(user, firstnameInitial){
    let name = 'Anonymous';
    if(user.name) {
        let first = firstnameInitial ? user.name.first.slice(0, 1) + '.'  : user.name.first;
        name = `${first} ${user.name.last}`;
    }
    return name;
}

function getUsernameOrEmail(user){
    let username = user.username;
    if(!username) {
        username = user.email
    }
    return username;
}

// user-list.js
console.log(getFullname(user, true));

// profile.js
console.log(getUsernameOrEmail(user));

// navbar.js
console.log('Hello', getFullname(user));

Conclusion

Aucun des concepts de DRY ni de WET ne sont à jeter, mais ce qu'il faut éviter à tout pris, c'est l'application dogmatique des principes et l'abstraction trop hâtive, voir inutile.

Les articles les plus populaires du blog

Envie de continuer à lire des articles autour du développement web (entre autres) ? Voici la sélection des articles de mon blog les plus lus par la communauté !

Voir la sélection 🚀

Recevez les articles de la semaine par e-mail pour ne rien manquer !

S'abonner à la newsletter 📧

À propos de l'auteur

Hello, je suis Nicolas Brondin-Bernard, ingénieur web indépendant depuis 2015 passionné par le partage d'expériences et de connaissances.

Aujourd'hui je suis aussi coach pour développeurs web juniors, tu peux me contacter sur nicolas@brondin.com, sur mon site ou devenir membre de ma newsletter pour ne jamais louper le meilleur article de la semaine et être tenu au courant de mes projets !


Photo par Taton Moïse sur Unsplash