![]() | Par Jules Le 20 March 2020 | ![]() |
Après la responsabilité unique et l’ouverture / fermeture vient le principe de la substitution de Liskov, ou LSP. Le LSP trouve ses origines dans une conférence donnée par Barbara Liskov en 1987, il sera ensuite clarifié dans un papier co-écrit par Liskov et Jeannette Wing en 1994 et sobrement intitulé Behavioral Notation of Subtyping.
Dans Behavioral Notation of Subtyping, le LSP est défini de la manière suivante :
Conditions sur les sous-types : Soit 𝝓(x) une propriété des objets x de type T. Alors 𝝓(y) doit être vrai pour les objets y de type S, avec S un sous-type de T.
Pompeux n’est-ce pas ? Mais on y retrouve déjà quelque chose d’intéressant : si une classe parente a certains attributs, ses sous-types doivent avoir les mêmes sous-attributs.
Et on en revient toujours à Robert C. Martin, qui pousse la définition un peu plus loin en disant que, concrètement, on devrait pouvoir utiliser une classe dérivée à la place de la classe parente indifféremment.
Tel qu’énoncé par Martin, le LSP se rapproche de la notion de programmation par contrat que l’on peut retrouver chez Meyer dans « Design by Contract » (1986). Finalement, le LSP peut être résumé par les 2 points suivants :
Je sens que je vous ai perdus avec ces termes barbares. Si, si, pas la peine de nier ! En réalité ce sont des termes complexes pour exprime quelque chose de simple, voyez par vous-mêmes.
Une pré-condition est une condition attachée à une fonction et que l’on vérifie au début de l’exécution de la fonction, par exemple le type des variables passées en paramètre. Dire qu’elle est covariante signifie qu’elle est au maximum aussi restrictive que celle du parent, sinon moins.
Une post-condition est une condition attachée à une fonction et que l’on vérifie à la fin de l’exécution de la fonction, par exemple la valeur de retour de la fonction. Dire qu’elle est contravariante signfie qu’elle est au moins aussi restrictive que celle du parent, sinon plus.
Jetez donc un coup d’œil au code suivant, tiré de MadeWithLove.com.
Supposons que ChatSiamois est un dérivé de Chat, qui lui-même est un dérivé de Animal. Nous avons ici un exemple de covariance de la pré-condition dans la classe RefugeMixte. En effet, Animal est moins restrictif que Chat, puisque ça pourrait être un Chat, mais aussi un Scarabé, pourquoi pas, après tout.
A partir de là, on peut remplacer RefugeChat (si c’était une classe, certes) par RefugeMixte sans problème, car un Chat sera toujours un Animal, donc pas d’erreur.
La classe ChatSiamois, quant à elle, viole le LSP car sa pré-condition (ChatSiamois) est plus restrictive que celle de son parent (Chat). Si on remplaçait RefugeChat par RefugeSiamois alors qu’on essayait d’utiliser le refuge avec un MaineCoon, on obtiendrait une erreur, alors qu’il s’agit bel et bien d’un chat.
Ici, c’est l’inverse. La post-condition de adopterChat dans RefugeSiamois est plus restrictive que celle dans RefugeChat, car il s’agit d’un ChatSiamois qui est un type de Chat bien précis. On peut donc remplacer RefugeChat par RefugeSiamois, pas de risque d’erreur, c’est contravariant.
Par contre, RefugeMixte permet d’adopter n’importe quel animal, donc si on l’emploie en lieu et place de RefugeChat, il pourrait renvoyer Scarabé, ce qui n’est pas compatible avec les fonctions qui pourraient nécessiter le type chat dans la suite du code.
Un enfant doit accepter des paramètres au moins aussi larges que ceux de ses parents. Un enfant doit retourner un objet à minima aussi précis que celui de ses parents.
Et surtout, ne manquez pas le prochain article de la série sur la séparation des interfaces !
Sources
>https://medium.com/@severinperez/maintainable-code-and-the-open-closed-principle-b088c737262
>https://code.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle--net-36600
>https://madewithlove.com/liskov-substitution-principle-explained/
Top de la semaine
Au hasard
Suivez-nous !
Articles récents
Commentaires
Suivez-nous !
Contactez-nous : contact@shadow-tech.fr
Partenariats : partnership@shadow-tech.fr
© Jules Rommens, tous droits réservés. Consulter les mentions légales.