Astuces Applications Communauté
10 min de lecture 146 vues

Ecrire du code propre et maintenable

darwin_nathan

Darwin Nathan

@darwin_nathan

Ecrire du code propre et maintenable

Introduction

L'écriture d'un code propre et maintenable est une compétence essentielle pour tout développeur. Un bon code n’est pas seulement celui qui fonctionne, mais celui qui est facile à lire, facile à comprendre, et facile à maintenir. Un code bien organisé réduit les bugs, facilite l'ajout de nouvelles fonctionnalités, et permet à d'autres développeurs (ou à vous-même dans quelques mois) de s'y retrouver rapidement.

Dans cet article, nous explorerons les principes fondamentaux et les bonnes pratiques pour écrire du code propre et maintenable, tout en évitant les "code smells" (mauvaises pratiques de codage). Voici des stratégies qui vous aideront à améliorer la qualité de votre code et à sensibiliser à l'importance d'un code bien structuré.


1. Suivre les Principes SOLID

Les principes SOLID sont un ensemble de cinq règles destinées à guider la conception d’un code propre et modulaire :

  • S : Single Responsibility Principle Une classe ou une fonction doit avoir une seule responsabilité. Cela réduit la complexité et facilite la maintenance.

  • O : Open/Closed Principle Les entités de votre code (classes, fonctions, etc.) doivent être ouvertes à l'extension mais fermées à la modification. Cela signifie que vous devez pouvoir ajouter de nouvelles fonctionnalités sans modifier les existantes.

  • L : Liskov Substitution Principle Les objets d’une classe dérivée doivent pouvoir remplacer les objets de la classe de base sans affecter la logique du programme.

  • I : Interface Segregation Principle Préférez plusieurs interfaces spécifiques à une grande interface générique. Cela permet de garder des contrats clairs et de limiter les dépendances inutiles.

  • D : Dependency Inversion Principle Les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. Utilisez des abstractions pour découpler vos classes.

Comment faire ?

  • Single Responsibility Principle (SRP) : Quand vous écrivez une classe ou une fonction, posez-vous cette question : "Cette entité fait-elle une seule chose ?". Si une classe fait plus d'une chose (ex. valider des données et gérer une base de données), divisez-la en plusieurs classes.
  • Open/Closed Principle (OCP) : Utilisez l’héritage ou des interfaces pour étendre une classe sans la modifier. Par exemple, au lieu de modifier directement une méthode existante, créez une nouvelle méthode qui la surcharge.
  • Liskov Substitution Principle (LSP) : Créez des sous-classes qui peuvent être utilisées à la place de la classe parente sans modifier le comportement attendu. Si vous devez vérifier le type d'une sous-classe pour un comportement spécifique, vous violez probablement ce principe.
  • Interface Segregation Principle (ISP) : Divisez les interfaces larges en interfaces plus petites et spécifiques. Assurez-vous que les classes n'implémentent que les méthodes dont elles ont besoin.
  • Dependency Inversion Principle (DIP) : Inversez les dépendances en utilisant des abstractions. Injectez des dépendances (classes ou services) dans vos classes plutôt que de les instancier directement.

Exemple

// Mauvais exemple
class Report {
public function generatePDF() {
// Génère un PDF
}
}
 
// Bon exemple : Respecter le principe de responsabilité unique (SRP)
class PDFReport {
public function generate() {
// Génère un PDF
}
}

2. Nommer les Variables et Fonctions de Manière Explicite

Les noms sont importants. Un bon nom doit être clair et explicite. Évitez les abréviations et les noms vagues.

Bonnes pratiques :

  • Utilisez des noms de variables qui décrivent leur rôle : Mauvais : a, b, x1 Bon : totalAmount, userEmail, isVerified

  • Les fonctions doivent indiquer l'action qu'elles accomplissent : Mauvais : mail() Bon : calculateTotalAmount(), sendEmailToUser()

Comment faire ?

  • Variables explicites : Choisissez des noms descriptifs qui représentent ce que fait la variable. Par exemple, au lieu de x ou y, utilisez totalPrice ou userCount.
  • Fonctions explicites : Les fonctions doivent refléter leur action. Par exemple, remplacez doWork() par calculateInvoiceTotal(). Le nom doit indiquer ce que la fonction fait, pas comment elle le fait.
  • Évitez les abréviations : À moins qu'une abréviation soit très courante (comme id pour identifier), préférez toujours des noms complets comme userEmail plutôt que usrEml.

Exemple

// Mauvais
function calc(x, y) {
return x + y;
}
 
// Bon
function calculateTotalPrice(price, discount) {
return price - discount;
}

3. Ecrire des Fonctions Courtes et Simples

Une fonction ne doit faire qu’une seule chose, et elle doit le faire bien. Si une fonction dépasse les 20-30 lignes, il est probablement temps de la diviser. Des fonctions courtes et ciblées sont plus faciles à lire, à comprendre, et à tester.

Comment Faire?

  • Une seule tâche par fonction : Si une fonction fait plusieurs choses (par exemple, elle valide une commande et envoie un email), divisez-la en plusieurs fonctions plus petites.
  • Longueur de fonction : Si une fonction dépasse 30 lignes, c'est un bon indicateur qu'elle doit être divisée. Essayez de créer des fonctions qui tiennent sur une seule page sans qu'il soit nécessaire de scroller.
  • Refactorisez les fonctions complexes : Lorsque vous voyez des blocs de code répétitifs ou une logique difficile à suivre, divisez ce code en plusieurs fonctions. Utilisez des noms de fonctions explicites pour clarifier le rôle de chaque sous-partie.

Exemple

// Mauvais exemple : Fonction trop complexe
function processOrder($order) {
// Validation de la commande
// Calcul des frais de port
// Mise à jour du stock
// Envoi d’un email de confirmation
}
 
// Bon exemple : Diviser en fonctions plus petites
function validateOrder($order) { /* ... */ }
function calculateShipping($order) { /* ... */ }
function updateStock($order) { /* ... */ }
function sendOrderConfirmation($order) { /* ... */ }

4. Limiter les Commentaires et Privilégier un Code Auto-explicatif

Si vous devez commenter votre code pour qu’il soit compréhensible, c’est peut-être un signe que votre code n’est pas assez clair. Un bon code se documente lui-même à travers des noms explicites, des structures claires et une organisation logique.

Cependant, utilisez des commentaires pour expliquer pourquoi quelque chose a été fait de manière spécifique, pas comment cela fonctionne.

Comment faire ?

  • Écrire du code lisible : Choisissez des noms de variables et de fonctions explicites afin qu'il soit clair de comprendre ce que fait le code sans commentaires supplémentaires.
  • Commentaires uniquement pour expliquer le pourquoi : N’utilisez des commentaires que pour des décisions complexes ou non évidentes. Par exemple, expliquez pourquoi vous avez choisi un certain algorithme ou design pattern si c'est pertinent.
  • Supprimer les commentaires inutiles : Si le code est explicite, évitez les commentaires superflus qui expliquent l’évidence. Un commentaire du type // Incrémente le compteur est inutile si la ligne counter++ est suffisamment claire.

Exemple :

// Mauvais
// Incrémente le compteur
$counter = $counter + 1;
 
// Bon
$counter++;

5. Respecter les Standards de Code et Style Guides

Chaque langage de programmation a des conventions de style qui dictent la manière dont le code doit être formaté. Utilisez des outils comme ESLint, PHP-CS-Fixer ou Prettier pour s'assurer que votre code respecte les standards du langage.

Comment faire ?

  • Utiliser des outils d’analyse statique : Utilisez des outils comme ESLint (pour JavaScript), PHP-CS-Fixer (pour PHP), ou Prettier pour formater automatiquement votre code selon les normes du langage.
  • Choisir un style guide et s’y tenir : Adoptez un guide de style reconnu, comme PSR-12 pour PHP ou Airbnb Style Guide pour JavaScript. Cela garantit une cohérence dans la structure de votre code.
  • Utiliser les linters : Configurez un linter dans votre environnement de développement pour détecter les erreurs de formatage ou de style avant même de commettre le code.

Exemples de règles :

  • Indentation cohérente : Utilisez toujours la même indentation (2 ou 4 espaces).
  • Nommer les constantes en MAJUSCULES : const MAX_USERS = 10;
  • Limiter la longueur des lignes : Évitez les lignes de code trop longues (max 80-100 caractères).

6. Éviter les "Code Smells"

Les code smells sont des signes avant-coureurs de problèmes dans le code. Voici quelques exemples courants:

  • Dépendances circulaires : Lorsque deux classes dépendent l'une de l'autre. Cela rend difficile la compréhension du flux du programme.
  • Longues chaînes de conditions : Si vous avez trop de if/else, utilisez des switch ou des stratégies de design pattern pour simplifier le code.
  • Données globales : Les variables globales augmentent le couplage et rendent le code difficile à tester.

Comment faire ?

  • Repérer les dépendances circulaires : Si deux classes dépendent l'une de l'autre, réfléchissez à comment les découpler en introduisant une interface ou un service intermédiaire.
  • Simplifier les chaînes de conditions : Remplacez les longues chaînes de if/else par des switch ou utilisez des design patterns comme la Stratégie ou le State Pattern pour gérer différents comportements de manière plus claire.
  • Réduire l’utilisation des variables globales : Si vous utilisez des variables globales pour stocker des données partagées, envisagez d'utiliser des objets ou des services pour encapsuler ces données.

Exemple :

// Mauvais exemple : trop de paramètres
function calculateDiscountedPrice($unitPrice, $discountRate, $quantity, $taxRate, $shippingCost) {
// Code complexe et peu lisible
return ($unitPrice * (1 - $discountRate) * $quantity) + ($taxRate * $unitPrice) + $shippingCost;
}
 
// Bon exemple
function calculateDiscountedPrice($unitPrice, $discountRate) {
return $unitPrice * (1 - $discountRate);
}

7. Tests Automatisés

Le test est un pilier de la maintenabilité du code. Utilisez des outils comme PHPUnit (pour PHP), Jest (pour JavaScript), ou Pest pour écrire des tests unitaires, fonctionnels et d'intégration. Les tests garantissent que votre code fonctionne comme prévu, même après des modifications.

Comment faire ?

  • Écrire des tests unitaires : Utilisez des frameworks de tests comme PHPUnit ou Jest pour écrire des tests qui vérifient chaque unité de votre code. Commencez par des tests pour les fonctions critiques et les composants de base.
  • Utiliser des mocks pour isoler les dépendances : Lors du test de fonctions qui dépendent d'autres services (comme une base de données ou une API), utilisez des mocks pour simuler ces dépendances et isoler la logique à tester.
  • Écrire des tests d'intégration et des tests fonctionnels : Une fois que vous avez des tests unitaires solides, ajoutez des tests d'intégration pour vérifier que vos composants fonctionnent ensemble, puis des tests fonctionnels pour simuler des interactions utilisateur complètes.

Bonnes pratiques de tests :

  • Testez une seule fonctionnalité à la fois.
  • Utilisez des mocks pour simuler les dépendances.
  • Écrivez des tests clairs et bien nommés : testUserCreation() est plus explicite que test1().

8. Rendre le Code Extensible mais pas Complexe

Un code maintenable doit pouvoir évoluer sans être totalement réécrit. Cependant, n’ajoutez pas de fonctionnalités inutiles pour anticiper des besoins futurs ("YAGNI" - You Aren't Gonna Need It). Concentrez-vous sur les fonctionnalités actuelles tout en laissant de la place pour l’extension.

Comment faire ?

  • Créer un fichier README complet : Dans chaque projet, rédigez un fichier README.md qui explique à quoi sert le projet, comment l'installer, comment l'utiliser et où trouver de la documentation supplémentaire.
  • Utiliser des commentaires de documentation : Si vous utilisez PHP, employez PHPDoc pour documenter les classes et méthodes. Dans JavaScript, vous pouvez utiliser JSDoc. Ces commentaires détaillent les paramètres, les types de retour, et les exceptions levées par une fonction.
  • Maintenir une documentation à jour : Mettez à jour la documentation à chaque changement majeur du code, et supprimez les informations obsolètes. La documentation doit être aussi bien un guide pour les utilisateurs que pour les futurs développeurs du projet.

Exemple :

// Mauvais : Trop d'anticipation
class ReportGenerator {
public function generateReport($type = 'pdf', $template = 'default') {
// Génère un rapport avec plusieurs types et templates à l'avance
}
}
 
// Bon : Code simple et extensible plus tard
class ReportGenerator {
public function generatePDFReport() {
// Génère un PDF maintenant, ajoutez d'autres types plus tard
}
}

9. Documenter le Code

Bien qu’un bon code se documente lui-même, il est aussi essentiel de documenter les composants, classes et modules à un niveau plus global. Une bonne documentation aide les nouveaux développeurs à comprendre l’architecture du projet et facilite la collaboration.

Exemple de documentation :

  • README : Décrivez le but du projet, comment l’installer, et comment l’utiliser.
  • Commentaires de classe : Utilisez des annotations comme PHPDoc ou JSDoc pour décrire les méthodes et paramètres.

Conclusion

Un code propre et maintenable ne se fait pas en un jour, mais en suivant ces pratiques, vous vous assurez de produire un code de qualité qui sera facile à comprendre, à tester, et à améliorer. En tant que développeur, adoptez une approche proactive : toujours chercher à améliorer et à optimiser la lisibilité et la structure de votre code. Cela vous fera gagner du temps à long terme et rendra vos projets bien plus solides.


Cet article propose un ensemble de règles et de principes qui devraient guider tout développeur dans la production de code de haute qualité. En intégrant ces pratiques dans vos projets, vous ferez de votre code un atout précieux pour les années à venir.

darwin_nathan

Darwin Nathan

@darwin_nathan

Je suis un jeune developpeur passione par les technologies innovantes

Vous aimez cet article ? Faite le savoir en partageant