Considérez uniquement l’interface
La programmation orientée objet nous permet de construire des systèmes flexibles et évolutifs, mais cela nécessite une conception attentive. Si nous ne prenons pas soin de garder notre conception flexible, l’ajout de nouvelles fonctionnalités peut entraîner des problèmes avec le code existant. Par exemple, imaginons que vous ayez un chat qui ne peut manger que des saucisses. Si vous voulez étendre le régime alimentaire du chat pour inclure d’autres types de nourriture, cela provoquerait potentiellement des problèmes, car la classe chat n’a été conçu pour manger uniquement des saucisses.
Mauvais code
Bon code
Vous pouvez déterminer si une conception est suffisamment flexible, si vous pouvez facilement l’étendre sans briser aucun code existant. Vérifions la véracité de cette affirmation en observant un autre exemple de chat. Un chat capable de manger n’importe quelle nourriture est plus flexible qu’un chat qui ne peut manger que des saucisses. Vous pouvez toujours nourrir le premier chat avec des saucisses, car elles font partie de la catégorie « nourriture en général » ; cependant, vous pouvez diversifier le menu de ce chat avec tout autre type de nourriture.
Lorsque vous souhaitez que deux classes collaborent accidentellement, vous commencez potentiellement par rendre l’une d’elles dépendante de l’autre. Cependant, il existe une autre méthode, plus flexible, pour instaurer une collaboration entre les objets :
- Déterminez précisément ce dont un objet a besoin de l’autre : quelles méthodes exécute-t-il ?
- Décrivez ces méthodes dans une nouvelle interface ou une classe abstraite.
- Faites en sorte que la classe qui est une dépendance implémente cette interface.
- Faites maintenant dépendre la deuxième classe de cette interface plutôt que de la classe concrète. Vous pouvez toujours la faire fonctionner avec les objets de la classe originale, mais la connexion est désormais beaucoup plus flexible.
L’application de ces principes garantit que le code est bien structuré, facile à maintenir et évolutif. C’est une partie essentielle de la programmation orientée objet, car elle facilite la réutilisation du code et rend les systèmes plus robustes face aux changements. De plus, elle favorise l’encapsulation et le découplage, deux éléments clés pour la création de systèmes logiciels solides dans le temps.
Réduire le couplage
Examinons un autre exemple illustrant que travailler avec des objets via des interfaces peut être plus avantageux que de dépendre de leurs classes concrètes. Imaginez que vous créez un simulateur d’entreprise de développement logiciel. Vous avez différentes classes qui représentent divers types d’employés. Au début, la classe Entreprise est étroitement liée aux classes concrètes des employés. Cependant, malgré la différence dans leurs implémentations, nous pouvons généraliser diverses méthodes liées au travail, puis extraire une interface commune pour toutes les classes d’employés. Après cela, nous pouvons appliquer le polymorphisme au sein de la classe Entreprise, traitant divers objets employés via l’interface Employé.
Avant, couplage fort
Après, couplage plus faible
Malgré tout, la classe Entreprise reste trop liée aux classes d’employés (voir le code du constructeur). C’est problématique, car si nous introduisons de nouveaux types d’entreprises qui travaillent avec d’autres types d’employés, nous devrons réécrire la majeure partie de la classe Entreprise au lieu de réutiliser ce code. Pour résoudre ce problème, nous pourrions déclarer la méthode d’obtention des employés comme abstraite. Chaque entreprise concrète implémentera différemment cette méthode, créant uniquement les employés dont elle a besoin.
Après ce changement, la classe Entreprise est devenue indépendante des diverses classes d’employés. Vous pouvez désormais étendre cette classe et introduire de nouveaux types d’entreprises et d’employés tout en réutilisant une partie de la classe entreprise de base. L’extension de la classe entreprise de base ne casse aucun code existant qui repose déjà sur celle-ci.
Après, couplage idéal
À la suite de cette modification, il est peu probable que vous constatiez un avantage direct. En effet, le code s’est complexifié par rapport à sa version précédente. Toutefois, si vous estimez que cela peut constituer une base solide pour l’ajout de fonctionnalités ultérieures, ou que d’autres utilisateurs de votre code pourraient souhaiter le faire évoluer à partir de ce point ; alors, pensez à mettre en œuvre ce genre de modification.