Ne tombez pas dans le piège de l’héritage impulsif

Si vous avez tendance à faire des classes filles à tout bout de champ

« Un chient aboie, un chat miaule, et pourtant ce sont des animaux ! ». Si cette phrase vous rappelle un cours ou tutoriel sur la programmation objet, vous êtes au bon endroit.

Il est fréquent d’utiliser ce genre d’exemple afin de servir de support pour une modélisation orientée objet ; je pense notamment à pas mal de tutoriels et/ou exercices sur la POO présents sur la toile. Cependant de mon point de vue ce genre d’exemple est mauvais et je vais essayer de vous expliquer pourquoi.

Prêtons nous au jeu

Avant de critiquer ce modèle, il faut l’essayer pour se rendre compte de ce qui ne va fondamentalement pas avec cette approche.

Supposons un exercice où l’on vous demande de gérer un chenil.

Première étape :

Sont à votre charge des chiens et des chats. Afin de mieux reconnaitre qui est en train de réclamer à manger vous devez également gérer le son produit par ces animaux.

Cet énoncé n’est pas complet mais avec un peu d’imagination on peut facilement se dire qu’un développeur puisse produire ce genre d’architecture :

Modélisation UML

Une classe abstraite Animal et deux classes filles réimplémentant cri() : Chien et Chat

Seconde étape :

Maintenant une nouvelle contrainte arrive : après avoir réalisé les aménagements nécessaires, on veut maintenant proposer aux clients de garder leurs serpents pendant leur absence.

Adaptez votre programme en conséquence.

Avec l’architecture que l’on a choisi il faut rajouer une classe pour pouvoir gérer nos serpents !

Modélisation UML

On doit créer une classe Serpent réimplémentant cri()

Et maintenant supposons que l’on veuille également gérer les singes. Même histoire, il faut rajouter une classe fille.

Le problème

On remarque ici le problème que l’on rencontre avec notre système d’héritage choisi : à chaque fois que l’on veut étendre la portée du programme il faut rajouter du code source. En Python cela n’a pas de très grosses conséquences mais en C++ cela implique une recompilation qui peut prendre plus ou moins de temps.

D’autres exemples que ce chenil virtuel posent les mêmes difficultés, comme un exercice où il faudrait gérer les personnages d’un RPG et ou cela serait fait de la manière suivante :

Modélisation UML

Modélisation du système RPG avec deux classes héritant de Personnage

Cette modélisation va rencontrer les mêmes problèmes que celle de notre chenil si on veut rajouter un paladin avec une compétence écraserAvecMarteau.

Solution alternative

Il serait beaucoup plus intéressant de raisonner de la manière suivante en ce qui concerne le problème du chenil :

Modélisation UML

Une seule classe Animal avec des attributs espèce et cri

On a plus qu’une seule classe et on peut gérer autant de cris et d’animaux que l’on veut.

Pour le cas des personnages de RPG on aurait :

Modélisation UML

Une classe Personnage possédant des objets de type Compétence

On sépare maintenant vraiment les données utiles du code. Si on veut rajouter un nouveau personnage il suffit de le décrire dans un fichier pour ensuite le charger ainsi que ses compétences plutôt que de devoir modifier le code et de le recompiler.

Conclusion

Méfiez vous des exercices de modélisation en programmation orientée objet.

Je ne suis pas un spécialiste dans le domaine mais donner de tels exemples à des débutants peut entrainer des codes sources énormes, pas flexibles, et où les données sont liées au code au lieu d’en être séparées.

Une question ou remarque ? N'hésitez pas à me contacter en envoyant un mail à microjoe, suivi d'un arobase, puis encore microjoe et enfin un « point org ».