SOLID Principles : les 5 règles d’or de l’OOP

Les principes SOLID consistent en cinq pratiques et directives pour un code propre, maintenable et flexible lors de la programmation orientée objet (OOP). L’application et le respect de ces principes permettent de concevoir des logiciels faciles à comprendre sur de longues périodes de développement. De cette manière, il est possible non seulement de produire un meilleur code, mais aussi de mieux entretenir le code existant.

SOLID Principles : qu’est-ce que c’est ?

Au début d’un bon code source, il y a des règles, des paradigmes de programmation et un style de programmation approprié pour un code efficace et propre. C’est précisément ce que font les cinq principes SOLID (SOLID Principles, en anglais), forgés par Robert C. Martin, Bertrand Meyer et Barbara Liskov. En respectant certains principes dans la programmation orientée objet (OOP) avec des langages comme Python ou Java, on écrit non seulement un meilleur code, mais on assure aussi à long terme une maintenance plus efficace du code, une conception durable et flexible du logiciel et une sécurité accrue.

Le terme SOLID désigne d’une part la base de développement solide pour tous ceux qui veulent apprendre à programmer. D’autre part, l’abréviation se compose des premières lettres de chacun des cinq principes :

  • Single Responsibility Principle ou Principe de Responsabilité Unique : une classe ne doit avoir qu’une seule responsabilité (et non une seule tâche) et une seule raison de changer.
  • Open Closed Principle ou Principe d’Ouverture/Fermeture : les classes doivent être ouvertes aux extensions et fermées aux modifications.
  • Liskov Substitution Principle ou Principe de Substitution de Liskov : les sous-classes doivent pouvoir hériter et implémenter toutes les méthodes et propriétés de la superclasse.
  • Interface Segregation Principle ou Principe de Ségrégation des interfaces : les interfaces ne doivent pas contenir plus de méthodes qu’il n’en faut pour les classes qui les implémentent.
  • Dependency Inversion Principle ou Principe d’Inversion de Dépendance : les classes ne doivent pas dépendre d’autres classes, mais d’interfaces ou de classes abstraites.

SOLID Principles : les avantages

Là où il n’y a pas de règles, le chaos s’installe : cela devient évident lorsque l’on programme. Même de petites erreurs, imprécisions et lacunes peuvent, si elles restent « non traitées », rendre à long terme un bon code source totalement inutilisable. Il suffit de peu de choses : des classes complexes qui compliquent l’implémentation ou encore des sous-classes auxquelles il manque certaines propriétés de leurs superclasses. Le respect des principes SOLID permet qu’il y ait le moins possible de réparation de code par refactoring.

Les avantages de l’application des SOLID Principles permettent que le code soit :

  • Clair, propre et beau : les logiciels et les codes sont plus faciles à comprendre, plus compréhensibles, plus efficaces et tout simplement plus beaux.
  • Facile à entretenir : grâce à une structure claire et concise, il est plus facile d’entretenir et de maintenir le code, qu’il soit nouveau ou qu’il ait évolué au fil du temps, même si plusieurs personnes sont impliquées.
  • Adaptable, extensible, réutilisable : grâce à une meilleure lisibilité, à une réduction des complexités et des responsabilités ainsi qu’à une réduction des dépendances entre les classes, le code peut être plus facilement édité, adapté, étendu par des interfaces et réutilisé de manière flexible.
  • Moins sujet aux erreurs : avec un code propre et une structure simple, les modifications apportées à une partie n’ont pas d’impact involontaire sur d’autres domaines ou fonctions.
  • Plus sûr et plus fiable : en réduisant ou en éliminant les points faibles, les incompatibilités ou les erreurs, on améliore la fonctionnalité et la fiabilité des systèmes, et donc la sécurité.

SOLID Principles : les 5 principes en revue

Les principes SOLID comptent parmi les règles d’or d’une bonne programmation et devraient donc être familiers à tous ceux qui s’intéressent à la programmation orientée objet. Découvrez les 5 principes :

SRP : Single Responsibility Principle (Principe de Responsabilité Unique)

La définition originale selon Robert C. Martin dans Agile Software Development: Principles, Patterns and Practices est la suivante :

Citation

« Il ne devrait jamais y avoir plus d’une raison de changer une classe. »

Le SRP stipule qu’une seule responsabilité doit s’appliquer à chaque classe dans l’OOP. Il ne doit donc y avoir qu’une seule raison pour modifier une classe. Contrairement à de fréquents malentendus, cela ne signifie pas qu’une classe ou un module ne doit avoir qu’une seule responsabilité, mais qu’elle ne doit être responsable que de tâches spécifiques qui, si possible, ne se chevauchent pas avec d’autres domaines.

Un chevauchement des responsabilités, par exemple en fournissant des fonctions à différents domaines d’activité, peut avoir des répercussions sur la fonctionnalité de la classe en cas de modification d’un domaine. En raison de plus d’une responsabilité et de trop de dépendances, une modification dans un domaine peut entraîner plusieurs autres modifications ou des erreurs de code.

Le SRP a donc pour objectif de développer des modules cohérents, responsables d’une tâche clairement compréhensible ou d’objets clairement définis. Grâce à une forme clairement structurée avec des dépendances réduites et des implémentations découplées, les modifications et modulations ultérieures sont plus simples, plus rapides et sans complications.

Note

Les classes, également connues sous le nom de types d’objets ou modules, sont l’élément central de la programmation orientée objet (OOP). Elles peuvent être considérées comme des modèles de construction avec des attributs pour créer des objets logiciels réels, similaires à ceux construits dans le monde réel. Les classes sont donc souvent comparées à des plans ou des modèles pour créer des objets, plutôt qu’à des types de fichiers.

OCP : Open Closed Principle (Principe d’Ouverture et de Fermeture)

Selon Bertrand Meyer et Robert C. Martin dans Object Oriented Software Construction, la définition de l’OCP est la suivante :

Citation

« Les entités logicielles (classes, modules, fonctions, etc.) devraient être à la fois ouvertes aux extensions et fermées aux modifications. »

L’OCP veille à ce que vous n’ayez pas à réécrire le cœur d’un logiciel pour mettre en œuvre des modifications. Si des modulations profondes du code sont nécessaires, des risques d’erreurs subtiles et de code smell apparaissent. Un code bien structuré devrait pouvoir être doté d’interfaces permettant d’ajouter des fonctions supplémentaires. Le mot-clé ici est héritage de classe.

Les nouvelles fonctionnalités et extensions peuvent être facilement rattachées à une superclasse sous forme de sous-classes via une interface. De cette manière, il n’est pas nécessaire de « bidouiller » le code déjà écrit et stable. Cela facilite la maintenance et l’entretien des programmes et rend la réutilisation d’éléments de code stables beaucoup plus efficace grâce aux interfaces.

LSP : Liskov Substitution Principle (Principe de Substitution de Liskov)

Selon Barbara H. Liskov et Jeannette M. Wing dans Behavioral Subtyping Using Invariants and Constraints, voici le concept du LSP :

Citation

« Soit q (x) une propriété de l’objet x de type T, alors q (y) devrait s’appliquer à tous les objets de type S, où S est un sous-type de T ».

Ce qui semble énigmatique au premier abord est en fait facile à comprendre : les sous-classes liées ou étendues doivent fonctionner comme leurs superclasses ou classes de base. Cela signifie que chaque sous-classe doit recevoir les propriétés de sa superclasse par le biais de l’héritage. Ces propriétés ne doivent pas subir de modifications dans la sous-classe. Elles doivent être remplaçables par principe ; d’où le principe de substitution. Les superclasses, en revanche, peuvent être modifiées.

L’exemple du rectangle et du carré de Robert C. Martin sert d’illustration. En géométrie, tout carré est un rectangle, en revanche, la réciproque n’est pas vraie : un rectangle n’est pas un carré. Un carré partage la propriété « côtés perpendiculaires » avec la classe supérieure des rectangles, mais présente la propriété supplémentaire « côtés de même longueur ».

Il en va autrement en programmation : l’hypothèse selon laquelle des classes similaires ou apparemment identiques se réfèrent les unes aux autres ou dépendent les unes des autres conduit à des erreurs, des malentendus et un code peu clair. C’est pourquoi, en programmation, la classe « rectangle » n’est pas un carré et la classe « carré » n’est pas un rectangle. Les deux sont « découplés » et implémentés séparément. Sans lien intégré entre les classes, un malentendu ne peut pas conduire à des erreurs interclasses. Cela augmente la sécurité et la stabilité lors de l’échange d’implémentations dans des sous-classes ou des superclasses sans avoir d’impact.

ISP : Interface Segregation Principle (Principe de Séparation des Interfaces)

L’ISP se définit selon Robert C. Martin dans The Interface Segregation Principle de la manière suivante :

Citation

« Les clients ne devraient pas être contraints de dépendre d’interfaces qu’ils n’utilisent pas. »

L’ISP stipule que les utilisateurs ne devraient pas être contraints d’utiliser des interfaces dont ils n’ont pas besoin. En d’autres termes, pour mettre à la disposition des clients les fonctions de certaines classes, de nouvelles interfaces plus petites sont conçues pour répondre à des besoins concrets. Cela permet d’éviter que les interfaces ne deviennent trop grandes et que de fortes dépendances ne se créent entre les classes. L’avantage : un logiciel avec des classes découplées et plusieurs petites interfaces adaptées à des exigences concrètes est plus facile à entretenir.

DIP : Dependency Inversion Principle (Principe d’Inversion des Dépendances)

Selon Robert C. Martin dans The Dependency Inversion Principle, le cinquième et dernier des principes SOLID s’énonce comme suit :

Citation

« A. Les modules de haut niveau ne devraient pas dépendre des modules de bas niveau. Les deux devraient dépendre d’abstractions. B. Les abstractions ne devraient pas dépendre des détails. Les détails devraient dépendre des abstractions. »

Le DIP veille à ce que les fonctions et dépendances concrètes dans les niveaux de code source reposent sur des interfaces abstraites et non les unes sur les autres. En clair : les architectures logicielles peuvent être grossièrement divisées en niveaux d’utilisateurs supérieurs et en niveaux abstraits inférieurs ou plus profonds. D’un point de vue purement logique, on peut supposer que la base abstraite détermine le comportement des niveaux supérieurs. Le DIP y voit toutefois un risque d’erreur, car il en résulte une dépendance des niveaux supérieurs vis-à-vis des niveaux inférieurs.

Au lieu de coupler les niveaux supérieurs aux niveaux inférieurs, les classes des niveaux supérieurs et inférieurs devraient dépendre d’interfaces abstraites intermédiaires. Les interfaces récupèrent les fonctionnalités nécessaires aux niveaux supérieurs et les mettent à disposition des niveaux inférieurs. Cela permet d’éviter une hiérarchie « bottom-to-top » (du bas vers le haut) de dépendances qui, avec le temps, peut entraîner des erreurs dans le code. Cela facilite la réutilisation des modules et permet d’apporter des modifications aux classes inférieures sans affecter les niveaux supérieurs.

Hébergement Web
Hébergement Web flexible, performant et sûr
  • Certificat SSL et protection DDoS
  • Sauvegarde et restauration des données
  • Assistance 24/7 et conseiller personnel

Que se passe-t-il en cas de non-respect des SOLID Principles ?

Un code beau et facile à lire, qui facilite autant que possible la maintenance, devrait être l’objectif de tout développement de logiciel. Mais si des directives comme les principes SOLID sont oubliées, le code vieillit très mal en raison de points faibles, de redondances, d’erreurs accumulées et de trop nombreuses dépendances. Dans le pire des cas, le code devient inutilisable avec le temps. Cela constitue un problème majeur, notamment dans le développement agile de logiciels, où de nombreuses personnes travaillent généralement sur un code complexe.

Parmi les conséquences d’un code malpropre ou d’une mauvaise maintenance du code, on peut citer :

  • Code smell : les points faibles historiques dus à un code malpropre, connus sous le nom de code smell ou « code qui sent mauvais », entraînent des erreurs de fonctionnement et des programmes incompatibles.
  • Code rouge : s’il n’est pas entretenu ou réparé par refactoring ou par un code review coûteux, le code peut « pourrir » et perdre complètement sa fonctionnalité. Un autre terme pour un code illisible et confus est le code spaghetti.
  • Les failles de sécurité : un code malpropre peut avoir pour conséquence des pannes, une maintenance compliquée ou des incompatibilités, mais aussi des failles de sécurité qui offrent aux logiciels malveillants la possibilité de créer des exploits ainsi que des attaques zero-day.

SOLID Principles : d’où viennent-ils ?

L’origine des SOLID Principles réside dans plusieurs principes introduits pour la première fois par Robert C. Martin (« Uncle Bob »), l’un des initiateurs de la programmation agile, dans son essai « Design Principles and Design Patterns » en 2000. Le groupe d’où sont issus les cinq principes SOLID a été cofondé par Robert C. Martin, Bertrand Meyer et Barbara Liskov. L’acronyme, facile à retenir et composé des cinq premières lettres des principes, a été répandu par Michael Feathers.

Y a-t-il d’autres principes de programmation similaires ?

Dans le développement de logiciels, les principes représentent des lignes directrices et des recommandations d’action générales ou très concrètes, à l’instar des principes SOLID, qui offrent un ensemble de principes pour le paradigme de la programmation orientée objet. D’autres principes de programmation pour Clean Code sont par exemple :

  • Le principe DRY (Don’t repeat yourself), « ne vous répétez pas », pour les fonctions à représentation unique et univoque.
  • Le principe KISS (Keep it simple, stupid), « simplifiez, idiot », pour un code aussi simple que possible.
Cet article vous a-t-il été utile ?
Page top