web-dev-qa-db-fra.com

Pourquoi est OOP difficile?

Quand j'ai commencé à utiliser un langage orienté objet (Java), je suis pratiquement devenu "cool" et j'ai commencé à coder. Je n'y ai jamais vraiment réfléchi jusqu'à récemment, après avoir lu beaucoup de questions sur la POO. L'impression générale que j'ai est que les gens ont du mal avec ça. Puisque je n'y ai pas pensé aussi dur, et je ne dirais pas que je suis un génie, je pense que j'ai dû manquer quelque chose ou l'avoir mal compris.

Pourquoi est OOP difficile à comprendre? Is est-il difficile à comprendre?

93
gablin

J'ai personnellement trouvé la mécanique de OOP assez facile à comprendre. La partie difficile pour moi était le "pourquoi" de celui-ci. Quand j'ai été exposé pour la première fois, cela semblait être une solution à la recherche d'un problème. Voici quelques raisons pour lesquelles je pense que la plupart des gens ont du mal:

  1. IMHO enseigner OO depuis le début est une idée terrible. Le codage procédural n'est pas une "mauvaise habitude" et est le bon outil pour certains travaux. Les méthodes individuelles dans un programme OO ont tendance à être assez procédurales de toute façon. De plus, avant d'apprendre suffisamment bien la programmation procédurale pour que ses limites deviennent visibles, OO ne semble pas très utile à l'étudiant.

  2. Avant de pouvoir vraiment saisir OO, vous devez connaître les bases des structures de données et des fonctions de liaison tardive/d'ordre supérieur. Il est difficile de bloquer le polymorphisme (qui consiste essentiellement à passer un pointeur vers des données et un tas de fonctions qui opèrent sur les données) si vous ne comprenez même pas les concepts de structuration des données au lieu d'utiliser simplement des primitives et de contourner des fonctions d'ordre supérieur/pointeurs vers des fonctions.

  3. Les modèles de conception doivent être enseignés comme quelque chose de fondamental pour l'OO, pas comme quelque chose de plus avancé. Les modèles de conception vous aident à voir la forêt à travers les arbres et donnent des exemples relativement concrets où OO peut simplifier de vrais problèmes, et vous allez vouloir les apprendre éventuellement de toute façon. De plus, une fois que vous obtenez vraiment OO, la plupart des modèles de conception deviennent évidents avec le recul.

120
dsimcha

Je pense qu'il y a quelques facteurs qui n'ont pas encore été mentionnés.

Tout d'abord, au moins en "pure POO" (par exemple, Smalltalk) où tout est un objet, vous devez tordre votre esprit dans une configuration plutôt artificielle pour penser à un nombre (pour un seul exemple) ) en tant qu'objet intelligent au lieu d'une simple valeur - car en réalité, 21 (par exemple) vraiment est juste une valeur. Cela devient particulièrement problématique quand d'un côté on vous dit qu'un gros avantage de OOP modélise la réalité de plus près, mais vous commencez par prendre ce qui ressemble énormément à une vue inspirée du LSD des parties les plus élémentaires et les plus évidentes de la réalité.

Deuxièmement, l'héritage dans OOP ne suit pas de très près les modèles mentaux de la plupart des gens. Pour la plupart des gens, classer les choses le plus précisément pas a n'importe où près des règles absolues nécessaire pour créer une hiérarchie de classes qui fonctionne. En particulier, la création d'un class D qui hérite d'un autre class B signifie que les objets de class D partager absolument, positivement tous les caractéristiques de class B. class D peut ajouter des caractéristiques nouvelles et différentes, mais tous les caractéristiques de class B doit rester intact.

En revanche, lorsque les gens classent les choses mentalement, ils suivent généralement un modèle beaucoup plus souple. Par exemple, si une personne établit des règles sur ce qui constitue une classe d'objets, il est assez typique que presque n'importe quelle règle puisse être violée tant que suffisamment d'autres règles sont suivies. Même les quelques règles qui ne peuvent pas vraiment être enfreintes peuvent presque toujours être "étirées" un peu de toute façon.

Par exemple, considérons "voiture" comme une classe. Il est assez facile de voir que la vaste majorité de ce que la plupart des gens considèrent comme des "voitures" ont quatre roues. Cependant, la plupart des gens ont vu (au moins une photo de) une voiture avec seulement trois roues. Quelques-uns d'entre nous du bon âge se souviennent également d'une voiture de course ou deux du début des années 80 (ou plus) qui avait six roues - et ainsi de suite. Cela nous laisse essentiellement trois choix:

  1. N'affirmez rien sur le nombre de roues d'une voiture - mais cela tend à conduire à l'hypothèse implicite que ce sera toujours 4, et un code qui risque de casser pour un autre numéro.
  2. Affirmez que toutes les voitures ont quatre roues, et classe simplement ces autres comme "pas des voitures", même si nous savons qu'elles le sont vraiment.
  3. Concevez la classe pour permettre une variation du nombre de roues, juste au cas où, même s'il y a de fortes chances que cette capacité ne soit jamais nécessaire, utilisée ou testée correctement.

L'enseignement de OOP se concentre souvent sur la construction d'énormes taxonomies - par exemple, des morceaux de ce qui serait une hiérarchie géante de toute la vie connue sur terre, ou quelque chose dans cet ordre. Cela soulève deux problèmes: d'abord et avant tout, cela tend à amener de nombreuses personnes à se concentrer sur d'énormes quantités d'informations qui ne sont absolument pas pertinentes pour la question à traiter. À un moment donné, j'ai vu une discussion assez longue sur la façon de modéliser les races de chiens, et si (par exemple) " caniche miniature "devrait hériter de" caniche de taille normale ", ou vice versa, ou s'il devrait y avoir une classe de base" caniche "abstraite, avec" caniche pleine taille "et" caniche miniature "héritant de lui. Ce qu'ils semblaient tous ignorer, c'est que l'application était censée traiter du suivi des licences pour les chiens, et pour le but à atteindre, il était tout à fait suffisant d'avoir un seul champ nommé "race" (ou quelque chose dans cet ordre) sans modélisation de la relation entre les races du tout.

Deuxièmement, et ce qui est presque important, cela conduit à se concentrer sur les caractéristiques des articles, au lieu de se concentrer sur les caractéristiques qui sont importantes pour la tâche à accomplir. Cela conduit à modéliser les choses telles qu'elles sont, où (la plupart du temps) ce qui est vraiment nécessaire est de construire le modèle le plus simple qui répondra à nos besoins, et d'utiliser l'abstraction pour s'adapter aux sous-classes nécessaires pour s'adapter à la l'abstraction que nous avons construite.

Enfin, je dirai encore une fois: nous lentement suivons le même chemin emprunté par les bases de données au fil des ans. Les premières bases de données ont suivi le modèle hiérarchique. Outre le fait de se concentrer exclusivement sur les données, il s'agit d'un héritage unique. Pendant un court laps de temps, quelques bases de données ont suivi le modèle de réseau - essentiellement identique à l'héritage multiple (et vues sous cet angle, plusieurs interfaces ne sont pas assez différentes de plusieurs classes de base pour s'en apercevoir ou s'en soucier).

Il y a longtemps, cependant, les bases de données ont largement convergé vers le modèle relationnel (et même si elles ne sont pas SQL, à ce niveau d'abstraction, les bases de données "NoSQL" actuelles sont également relationnelles). Les avantages du modèle relationnel sont suffisamment connus pour que je ne prenne pas la peine de les répéter ici. Je vais juste noter que l'analogue le plus proche du modèle relationnel que nous avons dans la programmation est la programmation générique (et désolé, mais malgré le nom, Java, par exemple, ne sont pas vraiment qualifiés , bien qu’ils constituent un tout petit pas dans la bonne direction).

57
Jerry Coffin

La POO requiert la capacité de penser de façon abstraite; un cadeau/malédiction que peu de gens, même des programmeurs professionnels, ont vraiment.

26
John Kraft

Tout paradigme nécessite une certaine poussée "par-dessus bord" pour saisir, pour la plupart des gens. Par définition, c'est un nouveau mode de pensée et cela nécessite donc un certain abandon des anciennes notions et une certaine compréhension de la raison pour laquelle les nouvelles notions sont utiles.

Je pense qu'une grande partie du problème est que les méthodes utilisées pour enseigner la programmation informatique sont assez pauvres en général. OOP est si courant maintenant qu'il n'est pas aussi visible, mais vous le voyez toujours souvent dans la programmation fonctionnelle:

  • des concepts importants sont cachés derrière des noms impairs (FP: Qu'est-ce qu'une monade? OOP: Pourquoi les appellent-ils parfois des fonctions et des méthodes d'autres fois?)

  • les concepts étranges sont expliqués dans la métaphore plutôt qu'en termes de ce qu'ils font réellement, ou pourquoi vous les utiliseriez, ou pourquoi quelqu'un a jamais pensé à les utiliser (FP: Une monade est une combinaison spatiale, elle enveloppe du code. OOP: An l'objet est comme un canard, il peut faire du bruit, marcher et hériter de l'animal)

  • les bonnes choses varient d'une personne à l'autre, donc ce n'est pas tout à fait clair quel sera le point de basculement pour n'importe quel élève, et souvent l'enseignant ne s'en souvient même pas. (FP: Oh, les monades vous permettent de cacher quelque chose dans le type lui-même et de le poursuivre sans avoir à écrire explicitement ce qui se passe à chaque fois. OOP: Oh, les objets vous permettent de conserver les fonctions d'une sorte de données avec ces données.)

Le pire, c'est que, comme l'indique la question, certaines personnes vont immédiatement comprendre pourquoi le concept est bon, et d'autres non. Cela dépend vraiment du point de basculement. Pour moi, saisir que les objets stockent des données et des méthodes pour ces données était la clé, après quoi tout le reste convenait comme une extension naturelle. Ensuite, j'ai eu des sauts plus tard, comme réaliser qu'un appel de méthode à partir d'un objet est très similaire à un appel statique avec cet objet comme premier paramètre.

Les petits sauts plus tard aident à affiner la compréhension, mais c'est le premier qui prend une personne de "POO n'a pas de sens, pourquoi les gens font-ils cela?" à "OOP est le meilleur, pourquoi les gens font-ils autre chose?"

21
CodexArcanum

Je pense que vous pouvez résumer la difficulté de base de cette façon:

// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.

// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);

Bien sûr, les gens peuvent s'habituer à la cartographie de "gauche" comme 270, et oui, dire "Car.Turn" au lieu de "tourner la voiture" n'est pas un énorme saut. MAIS, pour bien gérer ces objets et les créer, vous devez inverser la façon dont vous pensez normalement.

Au lieu de manipuler un objet, nous disons à l'objet de faire les choses par lui-même. Cela peut ne plus sembler difficile, mais dire à une fenêtre de s'ouvrir semble étrange. Les gens qui ne sont pas habitués à cette façon de penser doivent lutter avec cette bizarrerie encore et encore jusqu'à ce que cela devienne finalement naturel.

21
John Fisher

Parce que l'explication de base de OOP a très, très peu à voir avec la façon dont il est utilisé sur le terrain. La plupart des programmes pour l'enseigner essaient d'utiliser un modèle physique, comme "Pensez à une voiture comme un objet, et les roues comme objets, et les portes, et la transmission ... ", mais en dehors de certains cas obscurs de programmation par simulation, les objets sont beaucoup plus souvent utilisés pour représenter des concepts non physiques ou pour introduire l'indirection. L'effet est qu'il incite les gens à le comprendre intuitivement de la mauvaise façon.

L'enseignement à partir de modèles de conception est une bien meilleure façon de décrire la POO, car il montre aux programmeurs comment certains problèmes de modélisation réels peuvent être efficacement attaqués avec des objets, plutôt que de les décrire dans l'abstrait.

15
Dan Monego

Je suis en désaccord avec la réponse de dsimcha pour la plupart:

  1. Enseigner OO depuis le début n'est pas vraiment une mauvaise idée en soi, ni enseigner les langages procéduraux. Ce qui est important, c'est que nous enseignions aux gens à écrire du code clair, concis et cohérent, indépendamment de OO ou procédural.

  2. Les méthodes individuelles dans les bons programmes OO N'ONT PAS du tout tendance à être procédurales. Cela devient de plus en plus vrai avec l'évolution des langages OO (lire C # car autre que C++ c'est le seul autre OO que je connais) et leur syntaxe qui devient de plus en plus complexe de jour en jour (lambdas, LINQ aux objets, etc.). La seule similitude entre OO dans les langages procéduraux sont la nature linéaire de chacune, qui, je doute, changerait de sitôt.

  3. Vous ne pouvez pas non plus maîtriser un langage procédural sans comprendre les structures de données. Le concept de pointeur est aussi important pour les langages procéduraux que pour les langages OO. Passer des paramètres par référence, par exemple, ce qui est assez courant dans les langages procéduraux, vous oblige à comprendre les pointeurs autant qu'il est nécessaire pour apprendre n'importe quelle langue OO.

  4. Je ne pense pas que les modèles de conception devraient être enseignés tôt dans la programmation OO, car ils ne sont pas fondamentaux pour la programmation OO du tout. On peut certainement être un bon programmeur OO sans rien connaître des modèles de conception. En fait, une personne peut même utiliser des modèles de conception bien connus sans même savoir qu'ils sont documentés comme tels avec des noms propres et que les livres sont écrit à leur sujet. Ce qui devrait être enseigné fondamentalement, ce sont les principes de conception tels que la responsabilité unique, la fermeture ouverte et la ségrégation des interfaces. Malheureusement, beaucoup de gens qui se considèrent OO les programmeurs de nos jours ne sont pas familiers avec concept fondamental ou choisissez simplement de l'ignorer et c'est pourquoi nous avons tellement de déchets OO code là-bas. Ce n'est qu'après une compréhension approfondie de ces principes et d'autres que les modèles de conception doivent être introduits.

Pour répondre à la question de l'affiche originale, oui, OO est un concept plus difficile à comprendre que la programmation procédurale. C'est parce que nous ne pensons pas en termes de propriétés et de méthodes d'objets réels. Par exemple, l'homme le cerveau ne pense pas facilement à "TurnOn" comme une méthode de télévision, mais le voit comme une fonction de l'allumage de la télévision par l'homme. De même, le polymorphisme est un concept étranger à un cerveau humain qui voit généralement chaque objet de la vie réelle par un seul " visage ". L'hérédité n'est pas encore naturelle à notre cerveau. Ce n'est pas parce que je suis un développeur que mon fils en serait un. De manière générale, le cerveau humain doit être formé pour apprendre OO tout en les langages procéduraux lui sont plus naturels.

13
SoftwareRockstar

Je pense que de nombreux programmeurs ont des difficultés avec la conception et la planification initiales pour commencer. Même si quelqu'un fait tout le design pour vous, il est toujours possible de rompre avec les principes OOP. Si je prends un tas de code spaghetti et le jette dans une classe, est-ce vraiment OOP? Quelqu'un qui ne comprend pas OOP peut toujours programmer en Java. Aussi, ne confondez pas la difficulté à comprendre avec le fait de ne pas vouloir suivre une certaine méthodologie ou d'être en désaccord avec elle.

6
JeffO

Vous devriez lire Objets jamais? Eh bien, presque jamais. (adhésion ACM requise) par Mordechai Ben-Ari qui suggère que OOP est si difficile, parce que ce n'est pas un paradigme c'est en fait naturel pour modéliser quoi que ce soit. (Bien que j'ai des réserves à propos de l'article, car il n'est pas clair quels critères il estime qu'un programme doit satisfaire pour dire qu'il est écrit sur le paradigme OOP par opposition à un paradigme procédural utilisant un langage OO.)

5
Ken Bloom

La programmation orientée objet en elle-même n'est pas difficile.

La partie difficile vient de bien le faire. Où placer la coupure entre le code afin que vous puissiez facilement déplacer des éléments vers l'objet de base commun et les étendre plus tard? Comment rendre votre code utilisable par d'autres (étendre les classes, encapsuler des proxys, remplacer la méthode) sans sauter à travers les cerceaux pour le faire.

C'est la partie difficile, et si elle est bien faite, elle peut être très élégante, et si elle est mal faite, elle peut être très maladroite. Mon expérience personnelle est qu'il faut beaucoup de pratique pour avoir été dans toutes les situations où vous SOUHAITEZ le faire différemment, afin de le faire assez bien ce temps.

5
user1249

J'avais fait un peu de programmation GW-Basic et Turbo Pascal avant d'être présenté à OO, donc initialement il [~ # ~] a fait [~ # ~] a fait ma tête.

Je ne sais pas si c'est ce qui arrive aux autres, mais pour moi c'était comme ça: ma réflexion sur la programmation était purement procédurale. Comme dans: "tel ou tel se produit, alors tel ou tel se produit ensuite", etc. Je n'ai jamais considéré les variables et les données comme rien de plus que des acteurs éphémères dans le flux du programme. La programmation était "le flux d'actions".

Je suppose que ce qui n'était pas facile à saisir (aussi stupide que cela me semble maintenant), c'est l'idée que les données/variables comptent vraiment , dans un sens plus profond que le simple fait d’être des acteurs éphémères dans le "déroulement" du programme. Ou pour le dire autrement: j'ai continué à essayer de le comprendre via ce qui se passe , plutôt que via ce que est , qui est la vraie clé pour le saisir.

4
Bobby Tables

Je regardais juste une vidéo de Richard Feynman discutant de la façon dont les gens peuvent avoir des méthodologies complètement différentes dans leur tête en pensant - je veux dire complètement différent.

Lorsque je fais de la conception de haut niveau, il m'arrive de visualiser des objets, je peux les voir, voir leurs interfaces et voir quelles informations les voies doivent traverser.

J'ai également du mal à me souvenir des détails et j'ai trouvé OO pour être une excellente aide organisationnelle - beaucoup plus facile de trouver des fonctionnalités que de parcourir une liste de sous-programmes mal organisée.

Pour moi OO était un grand avantage, mais si vous ne visualisez pas de la même manière ou ne faites pas une architecture de haut niveau, c'est probablement inutile et ennuyeux.

4
Bill K

Je ne pense pas que ce soit difficile à comprendre, mais il se peut que beaucoup de programmeurs interrogés soient nouveaux dans le concept, venant de langages procéduraux.

D'après ce que j'ai vu/lu, beaucoup de gens (dans les forums au moins) recherchent un "résultat" de la POO. Si vous êtes un programmeur procédural qui ne revient pas en arrière et ne modifie pas son code, il peut être difficile de comprendre les avantages.

En outre, il y a beaucoup de mauvais OOP là-bas, si les gens lisent/voient cela, alors il est facile de voir pourquoi ils pourraient trouver cela difficile.

OMI, vous devez attendre jusqu'à ce qu'il "clique" ou être enseigné par quelqu'un avec de vraies connaissances, je ne pense pas que vous puissiez vous précipiter.

3
DBlackborough

Je pense que la raison OOP est difficile pour beaucoup parce que les outils ne le facilitent pas vraiment.

Les langages informatiques d'aujourd'hui sont une abstraction de ce qui se passe dans l'ordinateur.

La POO est une manière abstraite de représenter des abstractions.

Nous utilisons donc une abstraction pour construire des abstractions avec une abstraction. Ajoutez à cela que ce que nous résumons sont généralement des interactions physiques/sociales très complexes et, ce n'est pas étonnant.

3
ElGringoGrande

J'ai en fait un blog intitulé "Luttes dans la programmation orientée objet", qui est né de certaines de mes difficultés à l'apprendre. Je pense que c'était particulièrement difficile pour moi de comprendre parce que j'ai passé tellement de temps à utiliser la programmation procédurale, et j'ai eu du mal à comprendre l'idée qu'un objet pourrait être représenté par une collection d'attributs et de comportements (j'étais habitué à simplement une collection de variables et de méthodes).

De plus, il y a beaucoup de concepts qui rendent un langage orienté objet - héritage, interfaces, polymorphisme, composition, etc. Il y a vraiment beaucoup à apprendre sur la théorie de celui-ci avant de pouvoir réellement écrire du code efficacement manière, alors qu'avec la programmation procédurale, il s'agit simplement de comprendre des choses comme l'allocation de mémoire pour les variables et les appels de point d'entrée à d'autres méthodes.

2
Tim Claason

Motivation. Il est plus difficile d'apprendre quelque chose lorsque vous ne voyez pas pourquoi, et aussi lorsque vous ne pouvez pas regarder ce que vous avez fait et déterminer si vous l'avez fait correctement ou non.

Ce qui est nécessaire, ce sont de petits projets qui utilisent OO pour faire des choses utiles. Je suggère de parcourir un livre sur les modèles de conception et d'en trouver un qui est évidemment utile et qui fonctionne bien avec OO. (I J'ai utilisé Strategy la seule fois où j'ai essayé. Quelque chose comme Flyweight ou Singleton serait un mauvais choix, car ce sont des façons d'utiliser des objets en général, pas d'utiliser des objets pour accomplir quelque chose.)

2
David Thornley