Blog 3 min de lecture

POO contre généricité : les approches « est un » et « a un »

Share this article
POO contre généricité : les approches « est un » et « a un »

Comme le souligne Bjarne Stroustrup, « le C++ est un langage multi-paradigmes ». Il prend en charge de nombreux styles de programmation différents, ou paradigmes, et la programmation orientée objet n'en est qu'un parmi d'autres. Parmi les autres figurent la programmation structurée et la programmation générique.

Comme l'explique Thomas Becker dans cet intéressant article, il existe une tension entre la programmation générique et la POO. Voici l'opinion d'Alexander Stepanov, une figure éminente du C++, sur la POO, citée dans cet article :

Let us start with a little trivia quiz. Who said the following things about object-oriented programming?

"I find OOP technically unsound."

"I find OOP philosophically unsound."

"I find OOP methodologically wrong."

"I have yet to see an interesting piece of code that comes from these OO people."

"I think that object orientedness is almost as much of a hoax as artificial intelligence."

All the quotes above are from an interview with Alexander Stepanov, the inventor of the STL and elder statesman of generic programming.

To have a concrete idea about the generics flexibility, let’s compare the implementation of a class calculating a tax in OOP and generic programming.

Explorons une différence majeure entre les deux approches, qui pourrait expliquer l'opinion d'Alexander Stepanov sur l'approche POO. Pour l'illustrer, prenons l'exemple d'un calculateur de taxes basique.

generics1

CTaxCalculator ne collabore qu'avec des classes dérivées de ICalculator. Nous devons hériter de ICalculator et redéfinir certaines méthodes virtuelles pour implémenter notre algorithme.

En revanche, voici un exemple de TaxCalculator générique :

generics2

La classe CGenericTaxCalculator n'est pas limitée à un type de classe spécifique ; elle peut fonctionner avec n'importe quel type capable de calculer la taxe, quelle que soit la hiérarchie de classes de ce type.

L'approche POO est davantage une «approche orientée est» : l'héritage est surutilisé, et dans presque tout le code POO, chaque classe A collabore avec une autre classe B si B est une sorte d'une autre classe, abstraite ou non.

En revanche, avec l'approche générique, une classe A collabore avec B si B possède certaines méthodes et certains champs spécifiques — pas besoin d'hériter d'une classe particulière.

Cela rend la programmation générique plus naturelle et plus flexible : elle permet au développeur d'adopter une «approche orientée a». La POO est plus rigide en raison du fort couplage généré par l'héritage, qui oblige le développeur à suivre une «approche orientée est».

Réfléchissez-y : l'«approche orientée a» est la plus naturelle. En effet, dans le monde réel, je collabore avec une personne qui possède des compétences spécifiques, peu importe qu'elle soit issue d'une famille particulière.

La flexibilité de la programmation générique peut en faire un choix privilégié pour la conception C++ moderne, comme le souligne Andrei Alexandrescu :

Modern C++ Design defines and systematically uses des composants génériques. - highly flexible design artifacts that are mixable and matchable to obtain rich behaviors with a small, orthogonal body of code.

Trois points de sa déclaration sont particulièrement intéressants :

  • Modern C++ Design définit et utilise systématiquement des composants génériques..
  • Une conception hautement flexible.
  • Obtenir des comportements riches avec un corps de code petit et orthogonal.

Pour résumer, la programmation générique est plus naturelle et plus flexible que l'approche POO, et elle offre plus d'options pour écrire du code efficace.

Share this article