it-swarm-eu.dev

Warum ist OOP schwierig?

Als ich anfing, eine objektorientierte Sprache (Java) zu verwenden, ging ich so ziemlich auf "Cool" und fing an zu programmieren. Ich habe bis vor kurzem noch nie wirklich darüber nachgedacht, nachdem ich viele Fragen zu OOP gelesen hatte. Der allgemeine Eindruck, den ich bekomme, ist, dass die Leute damit kämpfen. Da ich es mir nicht so schwer gemacht habe und nicht sagen würde, dass ich ein Genie bin, denke ich, dass ich etwas verpasst oder missverstanden haben muss.

Warum ist OOP schwer zu verstehen? Ist schwer zu verstehen?

93
gablin

Ich persönlich fand die Mechanik von OOP ziemlich leicht zu verstehen. Das Schwierige für mich war das "Warum". Als ich zum ersten Mal damit in Berührung kam, schien es mir eine Lösung auf der Suche nach einem Problem zu sein. Hier sind einige Gründe, warum ich denke, dass es den meisten Menschen schwer fällt:

  1. IMHO Lehre OO von Anfang an ist eine schreckliche Idee. Prozedurale Codierung ist keine "schlechte Angewohnheit" und für einige Jobs das richtige Werkzeug. Einzelne Methoden in einem OO -Programm sehen sowieso ziemlich prozedural aus. Darüber hinaus scheint OO dem Schüler nicht sehr nützlich zu sein, bevor er die prozedurale Programmierung so gut lernt, dass ihre Grenzen sichtbar werden.

  2. Bevor Sie OO wirklich verstehen können, müssen Sie die Grundlagen von Datenstrukturen und Funktionen für späte Bindung/höhere Ordnung kennen. Es ist schwierig, den Polymorphismus (der im Grunde genommen einen Zeiger auf Daten und eine Reihe von Funktionen umgibt, die mit den Daten arbeiten) zu verstehen, wenn Sie nicht einmal die Konzepte der Strukturierung von Daten verstehen, anstatt nur Grundelemente zu verwenden und Funktionen höherer Ordnung weiterzugeben. Zeiger auf Funktionen.

  3. Entwurfsmuster sollten als etwas Grundlegendes für OO gelehrt werden, nicht als etwas Fortgeschritteneres. Entwurfsmuster helfen Ihnen, den Wald durch die Bäume zu sehen, und geben relativ konkrete Beispiele dafür, wo OO echte Probleme vereinfachen kann, und Sie werden sie sowieso irgendwann lernen wollen. Sobald Sie wirklich OO erhalten, werden die meisten Designmuster im Nachhinein offensichtlich.

120
dsimcha

Ich denke, es gibt einige Faktoren, die noch nicht erwähnt wurden.

Zumindest in "reinem OOP" (z. B. Smalltalk), wo alles ein Objekt ist, müssen Sie Ihren Geist in eine ziemlich unnatürliche Konfiguration verwandeln, um an eine Zahl zu denken (für nur ein Beispiel) ) als intelligentes Objekt statt nur als Wert - da in Wirklichkeit 21 (zum Beispiel) wirklich ist nur ein Wert. Dies wird besonders problematisch, wenn Ihnen einerseits gesagt wird, dass ein großer Vorteil von OOP darin besteht, die Realität genauer zu modellieren, aber Sie beginnen damit, dass Sie eine sehr LSD-inspirierte Sichtweise einnehmen selbst der grundlegendsten und offensichtlichsten Teile der Realität.

Zweitens folgt die Vererbung in OOP auch nicht sehr genau den mentalen Modellen der meisten Menschen. Für die meisten Menschen hat die Klassifizierung von Dingen am spezifischsten nicht irgendwo in der Nähe der absoluten Regeln notwendig, um eine funktionierende Klassenhierarchie zu erstellen. Insbesondere das Erstellen eines class D das von einem anderen erbt class B bedeutet, dass Objekte von class D absolut, positiv teilen alle die Eigenschaften von class B. class D kann neue und unterschiedliche Eigenschaften hinzufügen, aber alle die Eigenschaften von class B muss intakt bleiben.

Im Gegensatz dazu folgen Menschen, wenn sie Dinge mental klassifizieren, normalerweise einem viel lockeren Modell. Wenn zum Beispiel eine Person Regeln für eine Objektklasse erstellt, ist es ziemlich typisch, dass fast jede Regel verletzt werden kann, solange genügend andere Regeln befolgt werden. Selbst die wenigen Regeln, die nicht wirklich gebrochen werden können, können sowieso fast immer ein bisschen "gedehnt" werden.

Betrachten Sie zum Beispiel "Auto" als Klasse. Es ist ziemlich leicht zu erkennen, dass die große Mehrheit dessen, was die meisten Leute als "Autos" betrachten, vier Räder hat. Die meisten Menschen haben jedoch (zumindest ein Bild von) ein Auto mit nur drei Rädern gesehen. Einige von uns im richtigen Alter erinnern sich auch an ein oder zwei Rennwagen aus den frühen 80ern (oder so) mit sechs Rädern - und so weiter. Dies lässt uns grundsätzlich drei Möglichkeiten:

  1. Behaupten Sie nichts darüber, wie viele Räder ein Auto hat - aber dies führt tendenziell zu der impliziten Annahme, dass es immer 4 sein wird, und zu einem Code, der wahrscheinlich für eine andere Zahl kaputt geht.
  2. Stellen Sie sicher, dass alle Autos vier Räder haben, und klassifizieren Sie diese anderen als "keine Autos", obwohl wir wissen, dass sie es wirklich sind.
  3. Entwerfen Sie die Klasse so, dass die Anzahl der Räder für alle Fälle variiert werden kann, auch wenn die Wahrscheinlichkeit groß ist, dass diese Funktion niemals benötigt, verwendet oder ordnungsgemäß getestet wird.

Das Unterrichten über OOP] konzentriert sich oft auf den Aufbau riesiger Taxonomien - z. B. Teile einer riesigen Hierarchie allen bekannten Lebens auf der Erde oder etwas in dieser Reihenfolge. Dies wirft zwei Probleme auf: In erster Linie führt dies dazu, dass sich viele Menschen auf riesige Mengen an Informationen konzentrieren, die für die vorliegende Frage völlig irrelevant sind. Irgendwann sah ich eine ziemlich lange Diskussion darüber, wie Hunderassen modelliert werden sollen und ob (zum Beispiel) " Zwergpudel "sollte von" Pudel in voller Größe "erben oder umgekehrt, oder ob es eine abstrakte Basisklasse" Pudel "geben sollte, von der" Pudel in voller Größe "und" Zwergpudel "beide erben. Was sie alle schienen zu ignorieren war, dass der Antrag sich mit der Verfolgung von Lizenzen für Hunde befassen sollte, und für den vorliegenden Zweck war es völlig ausreichend, ein einzelnes Feld mit dem Namen "Rasse" (oder etwas in dieser Reihenfolge) ohne Modellierung der Beziehung zu haben überhaupt zwischen Rassen.

Zweitens, und fast wichtig, führt dies dazu, dass Sie sich auf die Eigenschaften der Elemente konzentrieren, anstatt sich auf die Eigenschaften zu konzentrieren, die für die jeweilige Aufgabe wichtig sind. Es führt dazu, Dinge so zu modellieren, wie sie sind, wobei (meistens) das einfachste Modell erstellt wird, das unsere Anforderungen erfüllt, und die Abstraktion verwendet wird, um die Unterklassen notwendig anzupassen, um sie anzupassen Abstraktion, die wir gebaut haben.

Abschließend möchte ich noch einmal sagen: Wir folgen langsam dem gleichen Weg, den Datenbanken im Laufe der Jahre eingeschlagen haben. Frühe Datenbanken folgten dem hierarchischen Modell. Abgesehen davon, dass Sie sich ausschließlich auf Daten konzentrieren, handelt es sich um eine Einzelvererbung. Für kurze Zeit folgten einige Datenbanken dem Netzwerkmodell - im Wesentlichen identisch mit Mehrfachvererbung (und aus diesem Blickwinkel unterscheiden sich mehrere Schnittstellen nicht genug von mehreren Basisklassen, um sie zu bemerken oder sich darum zu kümmern).

Vor langer Zeit konvergierten Datenbanken jedoch weitgehend auf dem relationalen Modell (und obwohl es sich nicht um SQL handelt, sind auf dieser Abstraktionsebene auch die aktuellen "NoSQL" -Datenbanken relational). Die Vorteile des relationalen Modells sind hinreichend bekannt, so dass ich sie hier nicht wiederholen werde. Ich möchte nur darauf hinweisen, dass das nächste Analogon des relationalen Modells, das wir bei der Programmierung haben, die generische Programmierung ist (und es tut uns leid, aber trotz des Namens Java Generika zum Beispiel sind nicht wirklich qualifiziert) obwohl sie ein winziger Schritt in die richtige Richtung sind).

57
Jerry Coffin

OOP erfordert die Fähigkeit, abstrakt zu denken; Ein Geschenk/Fluch, das nur wenige Menschen, selbst professionelle Programmierer, wirklich haben.

26
John Kraft

Jedes Paradigma erfordert für die meisten Menschen einen gewissen Push "over the Edge", um es zu erfassen. Per Definition ist es eine neue Denkweise und erfordert daher ein gewisses Maß an Loslassen alter Begriffe und ein gewisses Maß an Verständnis dafür, warum die neuen Begriffe nützlich sind.

Ich denke, ein großes Problem ist, dass die Methoden zum Unterrichten von Computerprogrammierung im Allgemeinen ziemlich schlecht sind. OOP ist jetzt so häufig, dass es nicht mehr so ​​auffällt, aber Sie sehen es immer noch häufig in der funktionalen Programmierung:

  • wichtige Konzepte sind hinter ungeraden Namen verborgen (FP: Was ist eine Monade? OOP: Warum nennen sie sie manchmal Funktionen und manchmal Methoden?)

  • seltsame Konzepte werden in Metaphern erklärt, anstatt in Bezug darauf, was sie tatsächlich tun oder warum Sie sie verwenden würden oder warum irgendjemand jemals daran gedacht hat, sie zu verwenden (FP: Eine Monade ist ein Raumanzug, sie fasst Code zusammen. OOP: An Objekt ist wie eine Ente, es kann Lärm machen, laufen und von Animal erben)

  • die guten Sachen variieren von Person zu Person, daher ist nicht ganz klar, was der Wendepunkt für einen Schüler sein wird, und oft kann sich der Lehrer nicht einmal daran erinnern. (FP: Oh, mit Monaden können Sie etwas im Typ selbst verstecken und weitermachen, ohne jedes Mal explizit aufschreiben zu müssen, was passiert. OOP: Oh, mit Objekten können Sie die Funktionen für eine Art von Daten mit diesen Daten behalten.)

Das Schlimmste ist, dass einige Leute, wie die Frage zeigt, sofort verstehen werden, warum das Konzept gut ist, andere nicht. Es kommt wirklich darauf an, was der Wendepunkt ist. Für mich war es der Schlüssel zu verstehen, dass Objekte Daten und Methoden für diese Daten speichern. Danach passte alles andere nur noch als natürliche Erweiterung. Dann hatte ich später Sprünge wie die Erkenntnis, dass ein Methodenaufruf von einem Objekt einem statischen Aufruf mit diesem Objekt als erstem Parameter sehr ähnlich ist.

Die kleinen Sprünge später helfen, das Verständnis zu verfeinern, aber es ist der erste, der eine Person aus "OOP macht keinen Sinn, warum machen die Leute das?" zu "OOP ist das Beste, warum machen die Leute etwas anderes?"

21
CodexArcanum

Ich denke, Sie können die grundlegende Schwierigkeit folgendermaßen zusammenfassen:

// 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);

Sicher, die Leute können sich daran gewöhnen, "links" als 270 abzubilden, und ja, "Car.Turn" statt "Turn the Car" zu sagen, ist kein so großer Sprung. ABER, um mit diesen Objekten gut umzugehen und sie zu erstellen, müssen Sie die Art und Weise umkehren, wie Sie normalerweise denken.

Anstatt ein Objekt zu manipulieren, weisen wir das Objekt an, die Dinge tatsächlich selbst zu tun. Es mag sich nicht mehr schwierig anfühlen, aber einem Fenster zu sagen, es solle sich öffnen, klingt seltsam. Menschen, die an diese Denkweise nicht gewöhnt sind, müssen immer wieder mit dieser Seltsamkeit kämpfen, bis sie schließlich irgendwie natürlich wird.

21
John Fisher

Weil die grundlegende Erklärung von OOP) sehr, sehr wenig damit zu tun hat, wie es im Feld verwendet wird. Die meisten Programme zum Unterrichten versuchen, ein physikalisches Modell zu verwenden, wie "Denken Sie an ein Auto als ein Objekt und Räder als Objekte und die Türen und die Übertragung ... ", aber außerhalb einiger dunkler Fälle von Simulationsprogrammierung werden Objekte viel häufiger verwendet, um nicht-physikalische Konzepte darzustellen oder Indirektion einzuführen. Der Effekt ist dass es die Leute dazu bringt, es intuitiv falsch zu verstehen.

Das Lehren aus Entwurfsmustern ist eine viel bessere Möglichkeit, OOP zu beschreiben, da es Programmierern zeigt, wie einige tatsächliche Modellierungsprobleme effektiv mit Objekten angegriffen werden können, anstatt sie abstrakt zu beschreiben.

15
Dan Monego

Ich bin mit Dsimchas Antwort größtenteils nicht einverstanden:

  1. Unterrichten OO von Anfang an ist an sich keine schlechte Idee, ebenso wenig wie das Unterrichten von prozeduralen Sprachen. Wichtig ist, dass wir den Menschen beibringen, klaren, präzisen und zusammenhängenden Code zu schreiben, unabhängig von OO oder prozedural.

  2. Einzelne Methoden in guten OO Programmen neigen dazu, überhaupt nicht prozedural zu sein. Dies wird mit der Entwicklung von OO Sprachen) immer wahrer (lesen Sie C # weil außer C++ ist das die einzige andere OO Sprache, die ich kenne) und ihre Syntax, die von Tag zu Tag komplexer wird (Lambdas, LINQ zu Objekten usw.). Die einzige Ähnlichkeit zwischen OO Methoden und Verfahren in prozeduralen Sprachen sind die linearen Eigenschaften der einzelnen Methoden, von denen ich bezweifle, dass sie sich bald ändern würden.

  3. Sie können eine prozedurale Sprache auch nicht beherrschen, ohne die Datenstrukturen zu verstehen. Das Zeigerkonzept ist für prozedurale Sprachen ebenso wichtig wie für OO Sprachen. Wenn Sie beispielsweise Parameter als Referenz übergeben, was in prozeduralen Sprachen durchaus üblich ist, müssen Sie Zeiger so gut verstehen, wie es erforderlich ist lerne eine beliebige OO Sprache).

  4. Ich denke nicht, dass Entwurfsmuster früh in OO Programmierung überhaupt unterrichtet werden sollten, weil sie für OO Programmierung überhaupt nicht grundlegend sind. Man kann definitiv Seien Sie ein guter OO Programmierer, ohne etwas über Designmuster zu wissen. Tatsächlich kann eine Person sogar bekannte Designmuster verwenden, ohne zu wissen, dass sie als solche mit Eigennamen dokumentiert sind und dass Bücher es sind Grundsätzlich sollten Designprinzipien wie Single Responsibility, Open Close und Interface Segregation vermittelt werden. Leider sind viele Leute, die sich selbst als OO Programmierer heutzutage betrachten), entweder nicht damit vertraut Grundlegendes Konzept oder einfach ignorieren. Deshalb haben wir so viel Müll OO Code da draußen. Erst nach einem gründlichen Verständnis dieser und anderer Prinzipien sollten Entwurfsmuster eingeführt werden.

Um die Frage des Originalplakats zu beantworten: Ja, OO ist ein schwieriger zu verstehendes Konzept als die prozedurale Programmierung. Dies liegt daran, dass wir nicht in Eigenschaften und Methoden realer Objekte denken. Zum Beispiel menschlich Das Gehirn denkt nicht ohne weiteres an "TurnOn" als eine Methode des Fernsehens, sondern sieht es als eine Funktion des menschlichen Einschaltens des Fernsehens. In ähnlicher Weise ist Polymorphismus ein Fremdwort für ein menschliches Gehirn, das im Allgemeinen jedes reale Objekt nur von einem sieht. " Gesicht ". Vererbung wieder ist nicht natürlich für unser Gehirn. Nur weil ich ein Entwickler bin, heißt das nicht, dass mein Sohn einer sein würde. Im Allgemeinen muss das menschliche Gehirn trainiert werden, um OO während) zu lernen prozedurale Sprachen sind natürlicher.

13

Ich denke, viele Programmierer haben zunächst Schwierigkeiten mit dem Design und der Planung im Voraus. Selbst wenn jemand das gesamte Design für Sie erledigt, ist es dennoch möglich, sich von OOP Prinzipien) zu lösen. Wenn ich einen Haufen Spaghetti-Code nehme und ihn in eine Klasse lege, ist das wirklich OOP? Jemand, der OOP nicht versteht), kann immer noch in Java programmieren. Verwechseln Sie auch nicht die Schwierigkeiten beim Verstehen mit der Nichtbereitschaft, einer bestimmten Methode zu folgen oder nicht damit einverstanden zu sein.

6
JeffO

Sie sollten Objekte nie? Nun, kaum jemals. (ACM-Mitgliedschaft erforderlich) von Mordechai Ben-Ari lesen, der vorschlägt, dass OOP so schwierig ist, weil es kein Paradigma ist Das ist eigentlich natürlich, um irgendetwas zu modellieren. (Obwohl ich Vorbehalte gegen den Artikel habe, weil nicht klar ist, welche Kriterien ein Programm seiner Meinung nach erfüllen muss, um zu sagen, dass es im Gegensatz zum Paradigma OOP) geschrieben ist ein prozedurales Paradigma unter Verwendung einer OO Sprache.)

5
Ken Bloom

Objektorientierte Programmierung an sich ist nicht schwer.

Das Schwierige ist, es gut zu machen. Wo soll der Schnitt zwischen Code eingefügt werden, damit Sie Dinge einfach in das gemeinsame Basisobjekt verschieben und später erweitern können? So machen Sie Ihren Code für andere nutzbar (Klassen erweitern, Proxys einschließen, Methode überschreiben), ohne dazu durch die Rahmen zu springen.

Das ist der schwierige Teil, und wenn es richtig gemacht wird, kann es sehr elegant sein, und wenn es schlecht gemacht wird, kann es sehr ungeschickt sein. Meine persönliche Erfahrung ist, dass es viel Übung erfordert, in all den Situationen gewesen zu sein, in denen Sie sich wünschen würden, dass Sie es anders gemacht haben, um es gut genug zu machen diesmal Zeit.

5
user1249

Ich hatte GW-Basic und Turbo Pascal ein gutes Stück programmiert, bevor ich in OO eingeführt wurde, also hat es anfangs meinen Kopf reingelegt.

Keine Ahnung, ob dies mit anderen passiert, aber für mich war es so: Mein Denkprozess über das Programmieren war rein prozedural. Wie in: "so und so passiert, dann passiert so und so weiter" usw. Ich habe die Variablen und Daten nie als etwas anderes als flüchtige Akteure im Programmfluss angesehen. Programmierung war "der Fluss der Aktionen".

Ich nehme an, was nicht leicht zu verstehen war (so dumm das jetzt für mich aussieht), war die Idee, dass die Daten/Variablen tatsächlich wirklich wichtig sind , in einem tieferen Sinne als nur flüchtige Akteure im Programm "Flow" zu sein. Oder anders ausgedrückt: Ich habe immer wieder versucht, es über das zu verstehen, was passiert , anstatt über das, was ist , das ist der eigentliche Schlüssel, um es zu erfassen.

4
Bobby Tables

Ich habe mir gerade ein Video von Richard Feynman angesehen, in dem es darum ging, wie Menschen beim Denken tatsächlich völlig andere Methoden im Kopf haben - ich meine ganz andere.

Wenn ich auf hoher Ebene entwerfe, visualisiere ich Objekte, sehe sie, sehe ihre Schnittstellen und sehe, welche Pfade Informationen durchlaufen müssen.

Ich habe auch Probleme, mich an Details zu erinnern, und fand, dass OO eine großartige organisatorische Hilfe ist - viel einfacher zu findende Funktionen als das Durchsuchen einer lose organisierten Liste von Unterprogrammen.

Für mich war OO ein großer Vorteil, aber wenn Sie nicht auf die gleiche Weise visualisieren oder keine Architektur auf hoher Ebene erstellen, ist dies wahrscheinlich sinnlos und ärgerlich.

4
Bill K

Ich denke nicht, dass es schwer zu verstehen ist, aber es kann sein, dass viele der abfragenden Programmierer neu im Konzept sind und aus prozeduralen Sprachen stammen.

Nach dem, was ich gesehen/gelesen habe, suchen viele Leute (zumindest in Foren) nach einem "Ergebnis" von OOP. Wenn Sie ein prozeduraler Programmierer sind, der nicht zurückgeht und seinen Code nicht erweitert, kann es wahrscheinlich schwierig sein, die Vorteile zu verstehen.

Es gibt auch viele schlechte OOP da draußen, wenn Leute das lesen/sehen, dann ist es leicht zu erkennen, warum sie es schwierig finden könnten.

IMO müssen Sie warten, bis es "klickt" oder von jemandem mit echtem Wissen unterrichtet wird. Ich glaube nicht, dass Sie sich beeilen können.

3
DBlackborough

Ich denke, der Grund OOP ist für viele schwierig, weil die Tools es nicht wirklich erleichtern.

Computersprachen sind heute eine Abstraktion dessen, was im Computer vor sich geht.

OOP ist eine abstrahierte Art, Abstraktionen darzustellen.

Wir verwenden also eine Abstraktion, um Abstraktionen mit einer Abstraktion zu erstellen. Hinzu kommt, dass das, was wir abstrahieren, normalerweise sehr komplexe physische/soziale Interaktionen sind und kein Wunder.

3
ElGringoGrande

Ich habe tatsächlich einen Blog namens "Kämpfe in der objektorientierten Programmierung", der aus einigen meiner Schwierigkeiten mit dem Lernen entstanden ist. Ich denke, es war besonders schwierig für mich zu verstehen, weil ich so viel Zeit mit prozeduraler Programmierung verbracht habe, und es fiel mir schwer, mich auf die Idee einzulassen, dass ein Objekt durch eine Sammlung von Attributen und Verhaltensweisen dargestellt werden könnte (ich war es gewohnt) einfach eine Sammlung von Variablen und Methoden).

Es gibt auch viele Konzepte, die eine Sprache objektorientiert machen - Vererbung, Schnittstellen, Polymorphismus, Komposition usw. Es gibt wirklich viel über die Theorie zu lernen, bevor Sie tatsächlich effektiv und objektorientiert Code schreiben können Während bei der prozeduralen Programmierung lediglich die Speicherzuweisung für Variablen und Einstiegspunktaufrufe für andere Methoden verstanden werden müssen.

2
Tim Claason

Motivation. Es ist schwieriger, etwas zu lernen, wenn Sie nicht verstehen, warum und auch wenn Sie nicht sehen können, was Sie getan haben und herausfinden, ob Sie es richtig gemacht haben oder nicht.

Was benötigt wird, sind kleine Projekte, die OO) verwenden, um nützliche Dinge zu tun. Ich würde vorschlagen, ein Buch über Entwurfsmuster durchzusehen und eines zu finden, das offensichtlich nützlich ist und gut mit OO funktioniert. (I. Ich habe Strategy verwendet, als ich es einmal ausprobiert habe. Etwas wie Fliegengewicht oder Singleton wäre eine schlechte Wahl, da es sich um Möglichkeiten handelt, Objekte im Allgemeinen zu verwenden und keine Objekte zu verwenden, um etwas zu erreichen.)

2
David Thornley