Avez-vous déjà essayé de comprendre du code source complexe et vous êtes retrouvé perdu dans un dédale de variables et de fonctions qui semblent écrites dans une langue inconnue ? Si tel est le cas, vous savez à quel point un code illisible peut être frustrant. Heureusement, il existe une solution : le clean code, une pratique de code qui peut aider les développeurs à écrire un code clair, simple et facile à comprendre. Dans cet article, nous allons vous expliquer ce qu’est le clean code, pourquoi il est important et comment vous pouvez l’appliquer à votre propre développement de logiciel. Que vous soyez un développeur chevronné ou simplement curieux de savoir comment fonctionne le code, cet article est pour vous ! 

Mais c’est quoi, le clean code ? 

Le clean code est une pratique de développement logiciel qui vise à produire du code lisible et maintenable. Il s’agit d’une approche axée sur la qualité qui encourage les développeurs à adopter des conventions de codage cohérentes et à se concentrer sur la clarté, la simplicité et la robustesse du code. 

En quoi est-ce important ? 

Le clean code permet de produire un logiciel de qualité supérieure. En écrivant du code clair, les développeurs peuvent simplifier leur travail et accélérer le processus de développement. De plus, le code propre est plus facile à tester, à déboguer et à améliorer au fil du temps, ce qui permet de garantir une meilleure qualité et une plus grande évolutivité du logiciel. En fin de compte, le clean code favorise une meilleure collaboration entre les développeurs et garantit la pérennité d’un projet. 

Les fondements du code propre : les cinq piliers du succès 

La philosophie du clean code peut-être résumée aux piliers suivants :  

1 – La lisibilité

Le code doit être facile à lire et à comprendre pour les autres développeurs. Pour améliorer la lisibilité, vous pouvez utiliser des noms de variables clairs et compréhensibles, éviter les abréviations et les acronymes obscurs, ajouter des commentaires si nécessaire et organiser votre code avec des espaces et une indentation claire. 

var x=10;y=20;if(x>y){console.log("x est plus grand que y");} 

Dans cet exemple, le code est mal formaté, difficile à lire et à comprendre. Les variables sont mal nommées et les blocs de code ne sont pas suffisamment bien formés pour apparaître au premier coup d’œil. 

const ageUtilisateur = 10; 
const ageMinimum = 18; 
 
if (ageUtilisateur < ageMinimum) { 
  console.log("Vous devez avoir au moins 18 ans pour accéder à ce contenu"); 
} 

Ici en revanche, le code est aisément lisible, avec des variables bien nommées et des blocs de code définis. Il est ainsi plus facile à comprendre pour les autres développeurs et à maintenir à l’avenir. 

2 – La simplicité

Chaque bloc de code doit être simple et élégant, sans fioritures inutiles. Pour simplifier votre code, vous pouvez utiliser des structures de contrôle de flux simples, éviter les structures de données complexes et les algorithmes compliqués et supprimer les variables inutiles. 

var x = 10; 
var y = 20; 
var result = 0; 
for (var i = 0; i < x; i++) { 
  result += y; 
} 
console.log(result); 

Dans cet exemple de mauvaise pratique, le code est plus complexe qu’il ne devrait l’être. Les variables sont mal nommées, les structures de contrôle de flux et les boucles sont utilisées inutilement pour effectuer une simple opération mathématique. 

const nombreRepetitions = 10; 
const nombreAjouts = 20; 
 
const resultat = nombreRepetitions * nombreAjouts; 
console.log(resultat); 

Dans cet exemple de bonne pratique, le code est simplifié en utilisant des variables clairement nommées et en évitant les boucles et les structures de contrôle de flux. Le code est plus facile à comprendre et à maintenir. De plus, le calcul est effectué en une seule ligne de code, ce qui le rend plus efficace. 

3 – La modularité

Le code doit être organisé en modules clairement définis, ayant des responsabilités précises. Pour rendre votre code plus modulaire, vous pouvez diviser votre code en petites fonctions réutilisables, utiliser des variables globales avec parcimonie et éviter les effets de bord (lorsqu’une fonction modifie une variable qui n’est pas passée en paramètre). 

var utilisateurs = []; 
 
function ajouterUtilisateur(nom, age) { 
  utilisateurs.push({nom: nom, age: age}); 
} 
 
function trouverUtilisateur(nom) { 
  for (var i = 0; i < utilisateurs.length; i++) { 
    if (utilisateurs[i].nom === nom) { 
      return utilisateurs[i]; 
    } 
  } 
} 
 
function supprimerUtilisateur(nom) { 
  for (var i = 0; i < utilisateurs.length; i++) { 
    if (utilisateurs[i].nom === nom) { 
      utilisateurs.splice(i, 1) ; 
      break;
    } 
  } 
} 

Dans cet exemple, toutes les fonctions manipulent une variable globale utilisateurs, ce qui rend le code difficile à comprendre et à modifier. 

class GestionUtilisateurs { 
  constructor() { 
    this.utilisateurs = []; 
  } 
 
  ajouterUtilisateur(nom, age) { 
    this.utilisateurs.push({nom: nom, age: age}); 
  } 
 
  trouverUtilisateur(nom) { 
    for (var i = 0; i < this.utilisateurs.length; i++) { 
      if (this.utilisateurs[i].nom === nom) { 
        return this.utilisateurs[i]; 
      } 
    } 
  } 
 
  supprimerUtilisateur(nom) { 
    for (var i = 0; i < this.utilisateurs.length; i++) { 
      if (this.utilisateurs[i].nom === nom) { 
        this.utilisateurs.splice(i, 1); 
        break; 
      } 
    } 
  } 
} 
 
const gestionUtilisateurs = new GestionUtilisateurs(); 
gestionUtilisateurs.ajouterUtilisateur("Jean", 30); 
const utilisateur = gestionUtilisateurs.trouverUtilisateur("Jean"); 
gestionUtilisateurs.supprimerUtilisateur("Jean"); 

Ici, nous avons défini une classe GestionUtilisateurs qui encapsule toutes les fonctions de gestion des utilisateurs. Les fonctions sont des méthodes de la classe, ce qui rend leur relation avec la classe plus explicite. Nous avons également utilisé le mot-clé this pour faire référence aux propriétés et méthodes de l’objet instancié à partir de la classe. L’utilisation d’une classe offre une abstraction plus élevée du code et facilite la réutilisation du code. La classe peut être facilement instanciée plusieurs fois, ce qui permet de gérer plusieurs listes d’utilisateurs indépendantes. 

4 – L‘évolutivité

Le code doit être conçu pour être facilement modifiable et extensible au fil du temps. Pour rendre votre code plus évolutif, vous pouvez prévoir des extensions futures, utiliser des structures de données et des algorithmes flexibles et isoler les parties du code qui sont susceptibles de changer. 

function calculerPrixTotal(articles) { 
  let total = 0; 
  for (let i = 0; i < articles.length; i++) { 
    total += articles[i].prix; 
  } 
  return total; 
} 

Dans cet exemple, la fonction calculerPrixTotal prend un tableau d’objets d’articles et calcule le prix total en additionnant le prix de chaque article. Bien que cette fonction fonctionne correctement pour le moment, elle n’est pas évolutive car elle ne prend pas en compte les futurs changements de spécifications. Par exemple, si vous souhaitez ajouter une remise ou un code promotionnel à la commande, vous devrez modifier cette fonction existante, ce qui peut entraîner des erreurs ou des bogues. 

class Commande { 
  constructor() { 
    this.articles = []; 
    this.remise = 0; 
  } 
  
  ajouterArticle(article) { 
    this.articles.push(article); 
  } 
  
  calculerPrixTotal() { 
    let total = 0; 
    for (let i = 0; i < this.articles.length; i++) { 
      total += this.articles[i].prix; 
    } 
  
    return total - this.remise; 
  } 
  
  appliquerRemise(codePromo) { 
    // logique de vérification du code promo 
    // si code valide, assigner la remise appropriée 
    this.remise = calculerRemise(codePromo, this.articles); 
  } 
} 
 
function calculerRemise(codePromo, articles) { 
 // logique de calcul de remise 
  return remise; 
} 

Ici, nous utilisons plutôt une classe Commande pour encapsuler la logique de commande, ce qui rend le code plus évolutif. La classe contient des méthodes pour ajouter des articles à la commande, calculer le prix total de la commande et appliquer une remise. La logique de calcul de remise a été extraite dans une fonction séparée, ce qui rend la classe Commande plus cohérente et facile à comprendre. Si nous voulons ajouter une nouvelle fonctionnalité à la commande, comme l’application d’une taxe de vente, nous pouvons simplement ajouter une nouvelle méthode à la classe Commande sans avoir à modifier la logique existante. Cela rend le code plus évolutif et plus facile à maintenir à long terme. 

5 – La robustesse

Le code doit être résistant aux erreurs et aux pannes et capable de gérer les situations imprévues de manière élégante. Pour cela, il est important de prévoir les cas d’erreurs et de les gérer de manière adéquate, de valider les entrées de l’utilisateur et de gérer les exceptions de manière appropriée. Un code robuste est capable de faire face à des situations imprévues sans plantage et de fournir des informations d’erreur claires et précises pour aider les utilisateurs à comprendre les problèmes rencontrés. 

function division(a, b) { 
  return a / b; 
} 

Dans cet exemple, si la variable b est égale à zéro, une erreur de division par zéro se produira. Cette erreur peut causer des plantages imprévus et des comportements indésirables du programme. 

function division(a, b) { 
  if (b === 0) { 
    throw new Error('Division par zéro impossible'); 
  } 
  return a / b; 
} 

Dans cet exemple, nous avons ajouté une vérification pour éviter la division par zéro. Si la valeur de b est égale à zéro, nous levons une exception avec un message clair pour informer l’utilisateur du problème. Ainsi, le programme ne plante pas et l’utilisateur est informé du problème. 

Le Clean Code, c’est donc penser à long terme

La qualité du code est une préoccupation constante pour tout développeur soucieux de produire des logiciels de qualité. Le clean code fournit des principes et pratiques qui permettent d’écrire du code clair, simple, lisible et facilement évolutif. En respectant ces principes, les développeurs peuvent créer des programmes durables, efficaces et évolutifs et ainsi contribuer à l’amélioration globale de la qualité du code dans leur entreprise ou leur communauté de développement.

En somme, le clean code est un moyen de travailler plus intelligemment et de créer des logiciels de qualité supérieure pour répondre aux besoins des utilisateurs finaux. L’adoption de ses pratiques est essentielle pour tout développeur qui souhaite améliorer sa productivité, son efficacité et son impact dans le domaine de la programmation.

Vous souhaitez en savoir plus ? Contactez notre équipe de développeurs à la Factory !

Rédigé par Daniel Azevedo, Manager et Lead Developer à la Factory 

Articles recents