Introduction
Vue d'ensemble
La programmation orientée objet ne se résume pas à implémenter des classes et à instancier des objets. Elle repose sur un ensemble de concepts fondamentaux qui permettent de structurer le code, de répartir les responsabilités et de concevoir des logiciels plus faciles à comprendre, à maintenir et à faire évoluer.
La maîtrise de ces concepts constitue également un prérequis important pour comprendre les principes SOLID et les design patterns. Des principes fondamentaux tels que l’encapsulation, l’abstraction, l’héritage, le polymorphisme ou encore l’utilisation des interfaces sont utilisées dans de nombreux principes et modèles de conception. D'autres mécanismes du langage, comme la surcharge, complètent ces concepts et sont utilisées pour la conception de nos classes.
Penser de manière orientée objet
La programmation orientée objet (POO) propose une façon de penser la conception et le développement de logiciels de manière radicalement différente des langages procéduraux. Elle ne consiste pas à penser uniquement « traitements de données », car même s’ils sont importants, ils sont relayés dans un premier temps en arrière-plan. Avant d’implémenter les traitements de données, il est nécessaire de définir les classes que nous allons compléter ou créer, leurs relations (associations et héritages), la manière dont nous les utiliserons tout en tenant compte de leur évolutivité.
Dans le schéma ci-dessous, la personne de gauche reçoit l’expression d’un besoin et l’implémente directement, au risque de créer un « plat de spaghettis » dans lequel l’évolution des traitements de données peut être difficile, et risque de diminuer la robustesse des logiciels avec l’apparition de bugs de régression. La personne de droite pense de manière orientée objet. Dans un premier temps, elle ne pense pas traitement de données, mais diagrammes de classes, conception, structuration du code. Elle peut alors structurer son code dans des classes afin de factoriser des membres communs entre elles (via l’héritage par exemple), décider comment exposer les classes (via les interfaces par exemple), traiter des problématiques de conception connues avec les design patterns (modèles de conception), anticiper les éventuelles évolutions en rendant sa conception extensible, expliquer à ses collègues comment une fonctionnalité a été implémentée via un diagramme de classes, sans avoir à montrer et expliquer les traitements de données, … Bref, concevoir un logiciel en pensant de manière orientée objet a de nombreux avantages.
Qu’est-ce que l’encapsulation ?
Les classes contiennent des membres qui se divisent en deux catégories :
-
L’état : ensemble des champs (attributs) et accesseurs (propriétés)
-
Le comportement : ensemble des constructeurs, du finaliseur, des méthodes et évènements
L’encapsulation consiste à regrouper dans une classe son état et les comportements qui permettent de le manipuler, tout en contrôlant l’accès à ses données internes. L’objectif est d’empêcher qu’un objet puisse être placé dans un état incohérent par du code extérieur à une classe. Par exemple, la classe Donut pourrait avoir les caractéristiques « DiametreExterne », « DiametreInterne », « TypeNappage », … et proposer le service « Napper », …
Qu’est-ce que l’abstraction ?
Le principe de l’abstraction consiste à masquer la complexité. Les classes peuvent proposer des services complexes, sans que le développeur qui manipule un objet ait à connaître le détail de l’implémentation des services. Par exemple, le service « Napper » peut être composé d’un ensemble de tâches à exécuter : positionner le bec de nappage au-dessus du donut, ouvrir le bec, attendre que le nappage coule, fermer le bec, … Ce service est « abstrait » pour le développeur car il n’en connait pas les détails de l’implémentation.
