une mauvaise compréhension des concepts, quand ce n'est pas une ignorance
Salut,
Je n'ai pas lu toutes les interventions, il y aura donc sans doute des redites...
Je crois, pour ma part, que le problème n'est pas ** forcément ** à chercher au niveau de la POO en elle-même, mais bien au niveau de la mauvaise compréhension des concepts qui la soutiennent.
A commencer sans doute par le concept même de paradigme, dont wikipedia indiquait à l'époque qu'il s'agit
Citation:
de rails dont il est dangereux de s'écarter, car cela occasionne des catastrophes
Le texte ayant changé depuis, j'ai fait cette citation de tête, et peut-être pas repris les termes exacts.
Mais combien de développeurs sont encore intimement persuadés qu'il est dangereux de s'écarter du paradigme qu'ils ont décidé d'utiliser:question: Pire encore : combien de langages fournissent le moyen correct d'intégrer correctement les différents paradigmes :question:
Or, le fait est que certains langages (je pense notamment à C++) nous démontrent tout le contraire, en nous permettant de mélanger allègrement les trois paradigmes pourtant distincts que sont
- le paradigme procédural pur
- le paradigme orienté objets
- le paradigme générique
Juste après la notion de paradigme, j'aurais tendance à citer la notion d'encapsulation parmi celles qui sont -- à tout le moins -- très souvent mal comprises:
Combien de développeur sont, encore à l'heure actuelle, persuadés d'encapsuler parfaitement leurs données en fournissant un code ressemblant à
Code:
1 2 3 4 5 6 7 8 9 10 11 12
| class MaClasse{
public:
/* il faut sans doute d'autres fonctions qui pourraient être nécessaires*/
void setX(int newX){
x = newX;
}
int getX() {
return x;
}
private:
int x;
} |
(avec les adaptations éventuelles au langage utilisé) :question:
Qu'on se le dise : ce code représente beaucoup de choses, mais ce n'est absolument pas un exemple correct d'encapsulation! L'encapsulation devrait nous faire réfléchir à l'interface de nos classes en termes de services rendus de manières à ce que tous les calculs et vérifications nécessaires soient effectués par les différentes fonctions qui seront appelées.
Assez paradoxalement, l'encapsulation n'est même pas un concept limité à la POO : dés que le langage propose certains mécanismes susceptibles d'éviter à l'utilisateur d'un agrégat de donnée (une structure, une classe ou un enregistrement, selon le nom qu'on lui donn) connaitre la manière dont les données sont organisées "en interne", la notion d'encapsulation devient possible.
La structure FILE du langage C en est le parfait exemple : on dispose de "tout ce qu'il faut" pour pouvoir la manipuler à son aise, alors que très peu de gens savent exactement de quelle données elle est composées (pire : sa composition a de fortes chances de varier en fonction du système sur lequel elle est utilisée).
Un accesseur (la fonction getX() ) peut, dans certains cas, correspondre à un service rendu par la classe, mais les mutateur (la fonction setX(int newX)) ne devrait pas exister, car elle oblige l'utilisateur de la classe à effectuer lui-même les différents calculs et vérifications pour déterminer la nouvelle valeur de x. Au risque qu'il se trompe lors du calcul, ou qu'il oublie de vérifier l'une ou l'autre des règles imposées par la classe.
Un exemple correct d'encapsulation serait d'avantage proche de
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Point{
public:
/* il faut sans doute d'autres fonctions qui pourraient être nécessaires*/
void move(int diffX, int diffY){
/* on vérifie que la position à atteindre est "cohérente" et accessible */
x+= diffX;
y+= diffY;
}
int getX(){
return x;
}
int getY(){
return y;
}
private:
int x;
int y;
} |
Le troisième point souvent mal compris -- quand il n'est pas purement et simplement ignoré par de nombreux développeurs -- est d'avantage un principe qu'un concept. Je veux parler du principe de substitution de Liskov.
Combien de développeurs utilisant la POO n'en ont-ils même jamais entendu parler :question: Combien de fois ai-je vu un développeur java ouvrir de grands yeux lorsque je lui en parlais :question: Combien de développeurs java n'ont pas conscience d'utiliser le même principe lorsqu'ils décide d'extends une classe ou qu'ils décident d'implement une interface :question:
Pire encore : parmi ceux qui disent le connaitre, combien de développeurs ne le comprennent-ils décidément que très mal :question:
Je me souviens d'une très longue discussion dans la section C++ dans laquelle j'essayais de convaincre des développeurs pourtant chevronnés que ce n'est pas parce que le compilateur accepte quelque chose que le principe en question est respecté; que ce principe devait être respecté avant même que l'on décide de tracer la relation d'héritage dans shéma UML, ou d'écrire la moindre ligne de code.
Le temps a passé depuis, et pourtant, combien de développeurs seraient encore près à me contredire à ce sujet :question:
Enfin, je dois reconnaitre un point comme correct: la POO n'est en aucun cas la panacée. Il y a de nombreux domaines dans lesquels la POO pose plus de problèmes qu'elle n'en résout.
Une approche Data Driven, avec une séparation claire des comportements et des données est souvent bien préférable; et l'immutabilité facilite énormément la tache du développeur pour toute une série d'agrégats de données.
Ce n'est, finalement, pas pour rien que l'on fait, en C++, la distinction entre les types de données qui ont sémantique de valeur et ceux qui ont sémantique d'entité.
Le problème étant -- encore une fois -- que trop de langages orientés objets interdisent au développeur de s'écarter du paradigme en question ;)