SOLID est l'acronyme de cinq principes de conception orientée objet introduits par Robert Martin au début des années 2000. Chaque principe répond à un mode de défaillance spécifique de la conception orientée objet – des symptômes que vous reconnaissez dans les bases de code réelles : des classes impossibles à étendre, des modules qui se brisent à des endroits inattendus lorsqu'ils sont modifiés, un code qui ne peut pas être testé de manière isolée. Les principes SOLID ne sont pas des règles à appliquer mécaniquement : ce sont des objectifs permettant d'identifier les problèmes de conception et de guider la refactorisation. Cette leçon couvre chaque principe avec précision, montre la violation avant le correctif et explique les implications architecturales.
La formulation de Martin : « Une classe ne devrait avoir qu'une seule raison de changer. » Le mot « raison » est essentiel : il fait référence à un acteur ou à une partie prenante dont les exigences pourraient conduire à un changement, et non à une règle syntaxique « à méthode unique ». Une classe qui formate les rapports ET les enregistre dans la base de données a deux raisons de changer : l'équipe de reporting (changements de format) et l'équipe opérationnelle (migration de la base de données). Lorsque ces changements se produisent simultanément, ils entrent en conflit. SRP affirme que ces préoccupations appartiennent à des classes distinctes.
Formulation de Bertrand Meyer (1988), reformulée par Martin : « Les entités logicielles doivent être ouvertes à l'extension, mais fermées à la modification ». Une classe est fermée pour modification lorsque son code testé et déployé n'a pas besoin d'être modifié pour s'adapter à un nouveau comportement. Il est ouvert à l'extension lorsqu'un nouveau comportement peut être ajouté en écrivant un nouveau code — une nouvelle sous-classe, une nouvelle implémentation de stratégie, un nouveau décorateur — sans toucher à la classe existante. Le mécanisme le plus courant : dépendre d'abstractions (interfaces) et injecter des implémentations concrètes.
Formulation de Barbara Liskov (1987) : « Si S est un sous-type de T, alors les objets de type T peuvent être remplacés par des objets de type S sans altérer aucune des propriétés souhaitables du programme. » En termes simples : une sous-classe doit honorer le contrat de sa superclasse – pas seulement ses signatures de méthode, mais ses attentes comportementales (préconditions, postconditions, invariants). La violation LSP classique est le problème Carré-Rectangle : Carré étend le rectangle, mais remplacer setWidth pour définir également la hauteur viole le contrat du rectangle selon lequel la largeur et la hauteur sont indépendantes.
Formulation de Martin : « Les clients ne devraient pas être obligés de dépendre d'interfaces qu'ils n'utilisent pas. » Les grosses interfaces - des interfaces avec de nombreuses méthodes indépendantes - obligent les implémenteurs à fournir des implémentations de stub de méthodes dont ils n'ont pas besoin et obligent les clients à importer un type qui comporte des fonctionnalités qu'ils n'utilisent pas. Le FAI dit : préférez de nombreuses petites interfaces spécifiques au client plutôt qu'une grande interface à usage général. La pression de conception exercée par les FAI produit naturellement des interfaces de rôle : des interfaces qui décrivent le rôle joué par un objet (imprimable, enregistrable, auditable) plutôt que le menu complet de tout ce qu'un objet peut faire.
Formulation de Martin : « (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. DIP est le principe qui sous-tend l'architecture Onion, l'architecture hexagonale et l'architecture propre – toutes les architectures abordées dans le chapitre précédent. C’est aussi le principe qui donne du sens à l’injection de dépendances : DI est le mécanisme ; DIP est la raison.