Warum ist OOP schwierig? [geschlossen]


91

Als ich anfing, eine objektorientierte Sprache (Java) zu verwenden, ging ich einfach auf "Cool" und fing an zu programmieren. Ich habe erst kürzlich 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 vorgestellt habe und nicht sagen würde, dass ich ein Genie bin, denke ich, dass ich etwas verpasst oder falsch verstanden haben muss.

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


72
Ich kontere mit: Es ist nicht schwer zu verstehen, nur schwer zu meistern. Das Programmieren als Ganzes ist so.
Steven Evers

2
ähm, ist es nicht? Vielleicht fällt es Programmierern, die nicht programmieren können, schwer, die oops anstelle ihrer Codezeilen zu beschuldigen? Ich weiß es nicht, aber ich habe nie jemanden sagen hören, dass es schwer zu verstehen ist. Allerdings habe ich gesehen, wie ppl gesagt hat, dass funktional seltsam ist, zumal sie den Wert ihrer Variablen nicht ändern können.

5
@ acidzombie42: funktional ist gar nicht komisch. Sie müssen keine Befehlsliste schreiben, um den Inhalt von Variablen zu ändern, die eine Position im RAM darstellen. Variablen stellen Werte dar. Sie ändern keine Werte. 42 bleibt 42, x bleibt x - was immer x ist. Sie schreiben Funktionen, die Ergebnisse aus ihren Parametern zuordnen. Werte sind: Zahlen, Wertelisten, Funktionen von Werten zu Werten, Programme, die Nebenwirkungen hervorrufen, und ein sich daraus ergebender Wert bei der Ausführung und mehr. Auf diese Weise wird das Ergebnis der Hauptfunktion vom Compiler berechnet, dh dem Programm, das ausgeführt werden kann.
Comonad

5
Ich habe kürzlich Haskell gelernt. Je mehr ich über funktionale Programmierung lerne und verstehe, desto schwerer fällt mir OOP. Ich denke, der Hauptgrund dafür ist, dass OOP versucht, die Daten (Objekt / Klasse) zusammen mit der Funktion, die sie bearbeitet (Methode), zu verknüpfen. Dies ist die Ursache des Problems, und viele OOP-Entwurfsmuster wurden entwickelt, um zu vermeiden, dass Daten und Funktionen miteinander verknüpft werden. Beispiel: Das Factory-Muster wird verwendet, um den Konstruktor (der eine Funktion ist) vom tatsächlichen Objekt zu trennen, auf dem er ausgeführt wird.
ming_codes

1
Weil es falsch benannt ist. Es sollte wirklich eine subjektorientierte Programmierung sein, indem das Subjekt die Aktion (Verb) ausführt und das Objekt die Aktion empfängt - John warf den Ball. JohnsBall.throw () ergibt also keinen Sinn.
Chris Cudmore

Antworten:


119

Ich persönlich fand die Mechanik von OOP ziemlich einfach zu begreifen. Das Schwierige für mich war das "Warum". Als ich zum ersten Mal damit in Berührung kam, schien es eine Lösung zu sein, um ein Problem zu suchen. Hier sind ein paar Gründe, warum ich denke, dass die meisten Leute es schwer finden:

  1. Meiner Meinung nach ist es eine schreckliche Idee, OO von Anfang an zu unterrichten. Prozedurale Kodierung ist keine "schlechte Angewohnheit" und für manche Jobs das richtige Werkzeug. Einzelne Methoden in einem OO-Programm sehen sowieso eher prozedural aus. Bevor OO das prozedurale Programmieren so gut lernt, dass seine Grenzen sichtbar werden, erscheint es dem Schüler nicht sehr nützlich.

  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 schwer, Polymorphismus (der im Grunde einen Zeiger auf Daten und eine Reihe von Funktionen, die auf die Daten angewendet werden, umgeht) zu verstehen, wenn Sie nicht einmal die Konzepte der Strukturierung von Daten verstehen, anstatt nur Primitive zu verwenden und Funktionen höherer Ordnung zu übergeben. Zeiger auf Funktionen.

  3. Entwurfsmuster sollten als etwas Grundlegendes für OO gelehrt werden, nicht als etwas Fortgeschritteneres. Entwurfsmuster helfen Ihnen dabei, 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 schließlich sowieso lernen wollen. Darüber hinaus werden die meisten Designmuster im Nachhinein offensichtlich, sobald Sie wirklich OO erhalten.


5
fabelhafte Antwort, vor allem Nummer 1. Natürlich sehen Methoden in OO wie Methoden in einer prozeduralen Sprache aus, aber jetzt sind sie in Objekten enthalten, die auch einen Status haben.
Dan Rosenstark

3
Ich mag besonders Ihre 1. und 3. Punkte. Mein Freund ist gaga für Designmuster, und ich sage ihm immer wieder, dass die meisten von ihnen sehr natürlich vom anfänglichen Problem herrühren, wenn Sie nur gutes OOP verwenden.
CodexArcanum

7
+1 für "Der schwierige Teil für mich war das" Warum "davon". Es erfordert einige Zeit und Mühe, die Grundlagen der Sprache (Kapselung) und der Entwurfsprinzipien sowie der Refactoring-Methoden zu verstehen und anzuwenden, um gemeinsame Lösungen (Entwurfsmuster) zu finden.
Belun

12
Ich stimme Nummer 1 zu, mit dem Vorbehalt, dass Sie OO besser erklären müssen, wenn Sie bereits wissen, wie man prozedural programmiert, als dies beim Lernen der Fall war. Nein, es ist weder nützlich noch informativ, über eine CatKlasse zu sprechen Mammal, die von einem echten Programm erbt , noch ein reales Beispiel zu verwenden, das wir prozedural geschrieben hätten. Wie eine einfache Datenstruktur.
Carson63000

4
-1 Design Patterns sind heute so überbetont. Sie sind sicher wichtig, aber: Erstens sind sie für alle Paradigmen wichtig: funktional, strukturiert sowie OO; und zweitens sind sie nicht Teil des Paradigmas, sondern nur ein praktisches Add-On, das Sie wie viele andere verwenden können. @SoftwareRockstar erklärt dies in seiner / ihrer Antwort.
CesarGon

56

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

Zumindest in "pure OOP" (z. B. Smalltalk), wo alles ein Objekt ist, müssen Sie Ihren Verstand in eine ziemlich unnatürliche Konfiguration verwandeln, um sich eine Zahl (nur für ein Beispiel) als intelligentes Objekt anstatt vorzustellen nur ein Wert - da in der Realität 21(zum Beispiel) wirklich ist nur ein Wert. Dies wird besonders problematisch, wenn Sie einerseits erfahren, dass ein großer Vorteil von OOP darin besteht, die Realität genauer zu modellieren, aber Sie beginnen damit, dass Sie eine sehr ähnliche, von LSD inspirierte Sicht auf die grundlegendsten und offensichtlichsten Teile von OOP haben Wirklichkeit.

Zweitens folgt die Vererbung in OOP auch nicht sehr genau den mentalen Modellen der meisten Menschen. Für die meisten Menschen nicht Dinge , die meisten speziell die Klassifizierung nicht haben überall in der Nähe der absoluten Regeln notwendig , um eine Klassenhierarchie zu erstellen , die funktioniert. Insbesondere bedeutet das Schaffen eines class D, das von einem anderen erbt class B, dass Objekte class Dabsolut alle Eigenschaften von teilen class B. class Dkann neue und andere Eigenschaften hinzufügen, aber alle Eigenschaften von class Bmüssen intakt bleiben.

Im Gegensatz dazu folgen Menschen, wenn sie Dinge mental klassifizieren, in der Regel einem viel lockeren Modell. Wenn eine Person beispielsweise Regeln für eine Objektklasse aufstellt, ist es ziemlich typisch, dass fast jede Regel verletzt werden kann, solange genügend andere Regeln eingehalten werden. Sogar die wenigen Regeln, die nicht wirklich gebrochen werden können, können sowieso fast immer ein wenig "gedehnt" werden.

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

  1. Behaupten Sie nicht, wie viele Räder ein Auto hat - aber dies führt zu der impliziten Annahme, dass es immer 4 sein wird und Code, der wahrscheinlich für eine andere Zahl kaputt geht.
  2. Nehmen Sie an, dass alle Autos vier Räder haben, und klassifizieren Sie diese nur als "Nicht-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, auch wenn die Wahrscheinlichkeit groß ist, dass diese Funktion niemals benötigt, verwendet oder ordnungsgemäß getestet wird.

Das Unterrichten über OOP konzentriert sich oft darauf, riesige Taxonomien aufzubauen - z. B. Teile einer gigantischen Hierarchie von allem bekannten Leben auf der Erde oder etwas in dieser Reihenfolge. Dies wirft zwei Probleme auf: In erster Linie führt es dazu, dass sich viele Menschen auf riesige Informationsmengen konzentrieren, die für die jeweilige Frage völlig irrelevant sind. Irgendwann sah ich eine ziemlich lange Diskussion darüber, wie man Hunderassen modelliert und ob (zum Beispiel) "Zwergpudel" von "Vollpudel" erben sollte oder umgekehrt, oder ob es einen abstrakten Grundpudel geben sollte "Klasse, mit" Pudel in voller Größe "und" Zwergpudel ", die beide davon erben. Was sie alle zu ignorieren schienen, war, dass die Anwendung sich mit dem Verfolgen von Lizenzen für Hunde befassen sollte,

Zweitens, und das ist beinahe wichtig, führt dies dazu, dass Sie sich auf die Eigenschaften der Objekte konzentrieren, anstatt sich auf die Eigenschaften zu konzentrieren, die für die jeweilige Aufgabe wichtig sind. Dies führt dazu, dass die Dinge so modelliert werden, wie sie sind, wo (meistens) wirklich das einfachste Modell erstellt werden muss, das unsere Anforderungen erfüllt, und die Abstraktion verwendet wird, um die erforderlichen Unterklassen an die von uns erstellte Abstraktion anzupassen .

Abschließend möchte ich noch einmal sagen: Wir gehen langsam den gleichen Weg, den Datenbanken im Laufe der Jahre eingeschlagen haben. Frühe Datenbanken folgten dem hierarchischen Modell. Dies ist keine reine Datenvererbung, sondern eine einmalige Vererbung. Für kurze Zeit folgten einige Datenbanken dem Netzwerkmodell - im Wesentlichen identisch mit der Mehrfachvererbung (und unter diesem Gesichtspunkt unterscheiden sich mehrere Schnittstellen nicht genug von mehreren Basisklassen, um dies zu bemerken oder sich darum zu kümmern).

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


Sehr gut erklärt, und vor allem, dass die meisten Probleme mit OOP, die Sie geben, nicht nur Probleme mit Anfängern sind, die es verstehen, sondern eher OOP-Probleme im Allgemeinen, mit denen die meisten OOP-Programmierer das Nachdenken lernen. Ich habe in letzter Zeit mit Spieledesign gearbeitet, bei dem ein Komponentenmodell sehr gut funktioniert, das eher dem Begriff relationaler Modelle als hierarchischer Modelle entspricht.
CodexArcanum

7
Heh, ich habe neulich nur darüber nachgedacht. Wie all das erste Lernmaterial, das ich über OOP las, sich auf Vererbung zu konzentrieren schien, zeigt mir meine Erfahrung immer mehr, dass Vererbung meistens nutzlos, wenn nicht sogar schädlich ist.
rmac

Klingt nach tabellenorientierter Programmierung , obwohl ich zu dem Schluss komme, dass OOP nicht das A und O der Softwareentwicklung ist.
OnesimusUnbound

1
@OnesimusUnbound: Der Unterschied besteht darin, dass generisches Programmieren eine echte, praktische Methode ist, um etwas zu erledigen, während tabellenorientiertes Programmieren meistens ein Wahnsinn über eine Theorie darüber ist, wie etwas funktionieren könnte (lesen Sie die alten Beiträge von TopMind in comp.object und Sie durch Mal sehen, was ich meine - eigentlich sind die Posten vielleicht nicht alle alt (soweit ich weiß, fährt er auch heute noch fort).
Jerry Coffin

3
Deshalb sind Schnittstellen so großartig. Sie nehmen die Vererbungsmodellierung und kehren sie in einen Bredth-First-Ansatz um. Beispielsweise kann beim Hundebeispiel davon ausgegangen werden, dass jeder Hund eine Gattung und bis zu zwei Superarten (eine für jeden Elternteil) für eine bestimmte Rasse hat. Es kann auch eine Listeneigenschaft geben, die Merkmale enthält, aber die mögliche Vielfalt macht es sinnlos, sie in eine bestimmte Struktur zu zerlegen. Es ist besser, eine gründliche Suche durchzuführen, um die Merkmale zu crawlen und ähnliche Rassen basierend auf diesen Ergebnissen zu kombinieren.
Evan Plaice

26

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


35
Alle Programmierungen sind abstrakt.
JeffO

28
@ Jeff O - Ich bin anderer Meinung. Das Programmieren erfordert nur die Fähigkeit, jemandem Schritt für Schritt mitzuteilen, wie etwas zu tun ist. Wenn Sie jemandem sagen können, wie man ein Erdnussbutter-Gelee-Sandwich macht, können Sie Befehle in eine Programmierschnittstelle eingeben. Das ist eine völlig andere Fähigkeit, als ap, b & j sandwich abstrakt zu modellieren und wie es mit der Welt interagiert.
John Kraft

16
Es ist konkret, jemandem 2 Stifte zu geben und ihm dann 1 Bleistift zu geben und zu fragen, wie viele Stifte er hat. 2 + 1 = 3 ist abstrakt.
JeffO

17
Ich stimme Jeff zu. Das Programmieren ist im Grunde das Verwalten von Abstraktionen. Zumindest gilt das für alles andere als den grundlegendsten Programmablauf (denn alles andere wird ohne Abstraktionen zu komplex). Es gibt eine bestimmte Phase beim Programmierenlernen, in der der Anfänger lernt, wie man Abstraktionen steuert. Hier fällt die Rezept-Metapher runter. Programmieren ist nichts anderes als Kochen, und während ein einzelner Algorithmus mit einem Rezept verglichen werden kann, unterscheidet sich Programmieren grundlegend von der Implementierung isolierter Algorithmen.
Konrad Rudolph

2
@ KonradRudolph Großartiger Punkt. +1 für "Alles andere wird ohne Abstraktionen zu komplex" .
Karthik Sreenivasan

21

Ich denke, Sie können die Grundschwierigkeiten so 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 an die Zuordnung von "left" zu 270 gewöhnen, und ja, "Car.Turn" anstelle von "turn the car" zu sagen, ist kein so großer Sprung. ABER, um gut mit diesen Objekten umzugehen und sie zu erstellen, muss man die Art und Weise umkehren, wie man normalerweise denkt.

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


7
Gute Einsicht. Ich denke, das Problem ist, dass es im wirklichen Leben nicht so viel gibt, was ein "Objekt" kann, das sich nicht auf andere Objekte bezieht. OO funktioniert gut, sofern Objekte angewiesen werden, ihren internen Status zu ändern: rectangle.enlarge (margin_in_pixels), aber ich habe die Grenzen vor Jahren erkannt. Eines Tages installierten wir Programmierer Hardware. Jemand hat "screw.turn" weisecracked Witzig, aber es hat mich zum Nachdenken gebracht: Sicher, eine Schraube kann ihre Ausrichtung ändern, aber es ist wirklich eine Operation zwischen Gehäuse und Schraube; Kein Objekt kann die Aufgabe selbst erledigen. OO ist einfach nicht gut genug.
DarenW

3
+1, nach Jahren des Schreibens von "substr (date, 0,4)" ist es schwer, "date.substring (0,4)" zu schreiben
ern0

4
+1 für das Code-Snippet. Es zeigt deutlich einen tatsächlichen Denkprozess.
Karthik Sreenivasan

2
Ich würde es tatsächlich als einen Befehl lesen, den Sie senden. Wie in "Sagen Sie dem Auto, dass es links abbiegen soll". Oop basierte darauf, Nachrichten an Objekte zu senden, also würde ich es so interpretieren.
Mistkerl

1
Guter Einblick, also ist OOP möglicherweise besser für die Modellierung von "Agentensystemen" geeignet?
Qbik

21

Jedes Paradigma erfordert für die meisten Menschen einen gewissen Schub "über den Rand", 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ßer Teil des Problems ist, dass die Methoden zum Unterrichten der Computerprogrammierung im Allgemeinen ziemlich schlecht sind. OOP ist mittlerweile so verbreitet, dass es nicht mehr so ​​auffällt, aber Sie sehen es immer noch häufig in der funktionalen Programmierung:

  • Wichtige Konzepte verbergen sich hinter ungeraden Namen (FP: Was ist eine Monade? OOP: Warum nennen sie sie manchmal Funktionen und Methoden zu anderen Zeiten?)

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

  • Das gute Zeug ist von Person zu Person unterschiedlich, 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 verbergen 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 beibehalten.)

Das Schlimmste daran ist, dass einige Leute, wie die Frage zeigt, sofort verstehen, warum das Konzept gut ist, und andere nicht. Es kommt wirklich darauf an, wie hoch der Wendepunkt ist. Für mich war das Erfassen, dass Objekte Daten und Methoden für diese Daten speichern, der Schlüssel, danach passt alles andere einfach als natürliche Erweiterung. Dann hatte ich später den Eindruck, 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 sonst noch etwas?"


8
Ich hasse besonders die Metaphorik, meistens verwirren sie eher als beschreiben sie.
Lie Ryan

3
"Dann hatte ich später den Eindruck, dass ein Methodenaufruf von einem Objekt sehr ähnlich ist wie ein statischer Aufruf mit diesem Objekt als erstem Parameter." Ich wünschte, dies würde von Anfang an mehr betont, da es in Sprachen wie Python ist.
Jared Updike

1
Mein Problem mit der Verwendung von Metaphern zur Erklärung von Konzepten ist, dass der Lehrer oft bei der Metapher anhält, als würde das die ganze Sache erklären. Nein, das ist keine vollständige Erklärung. Dies ist nur eine Illustration, die uns hilft, die eigentliche Erklärung in den Kopf zu schließen .
jhocking

Gute Antwort! +1 für die Erklärung, dass der erste Schritt zum Verständnis von OOP wichtiger ist als das, was später als natürliche Erweiterung mit dem guten Verständnis der Grundlage kommt. : D
Karthik Sreenivasan

Das Gleiche gilt für das "Sprung" -Lernen: Als ich begann, OOP als "nur" modularen / strukturierten / schrittweisen Aufbau, aber auf Steroiden wahrzunehmen; als ich einige sehr alte und über die Wartbarkeit hinausgehende COBOL-Programme umschrieb. Ungeachtet der globalen Reichweite von COBOL hatte ich die OO-Prinzipien im Wesentlichen mit benutzerdefinierten Datensatzstrukturen, Einzweckvariablen und eng fokussierten, modularen und strukturierten Absätzen (Methoden) angewendet.
Radarbob

15

Weil die grundlegende Erklärung von OOP sehr, sehr wenig damit zu tun hat, wie es im Feld eingesetzt wird. Die meisten Lehrprogramme versuchen, ein physikalisches Modell zu verwenden, z. B. "Stellen Sie sich ein Auto als Objekt vor und Räder als Objekte, Türen und Getriebe ...", jedoch außerhalb einiger dunkler Fälle von Simulationsprogrammierung. Objekte werden viel häufiger verwendet, um nicht-physikalische Konzepte darzustellen oder Indirektion einzuführen. Der Effekt ist, dass die Leute es auf die falsche Weise intuitiv verstehen.

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


13

Ich stimme der Antwort von dsimcha größtenteils nicht zu:

  1. OO von Anfang an zu unterrichten ist an sich keine schlechte Idee, ebenso wenig wie prozedurale Sprachen. Wichtig ist, dass wir Menschen lehren, klaren, prägnanten und zusammenhängenden Code zu schreiben, unabhängig von OO oder Verfahrensweisen.

  2. Einzelne Methoden in guten OO-Programmen sind in der Regel überhaupt nicht prozedural. Dies wird mit der Entwicklung der OO-Sprachen (lesen Sie C #, da ich neben C ++ die einzige andere OO-Sprache kenne) und deren Syntax, die von Tag zu Tag komplexer wird (Lambdas, LINQ zu Objekten usw.), immer wahrer. Die einzige Ähnlichkeit zwischen OO-Methoden und -Prozeduren in prozeduralen Sprachen besteht in der Linearität der einzelnen Methoden, die sich, wie ich bezweifle, bald ändern wird.

  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 häufig vorkommt, müssen Sie die Zeiger so gut verstehen, wie es zum Erlernen einer beliebigen OO-Sprache erforderlich ist.

  4. Ich denke nicht, dass Design Patterns in der OO-Programmierung überhaupt früh gelernt werden sollten, da sie für die OO-Programmierung überhaupt nicht grundlegend sind. Man kann definitiv ein guter OO-Programmierer sein, ohne etwas über Designmuster zu wissen. Tatsächlich kann eine Person sogar bekannte Entwurfsmuster verwenden, ohne zu wissen, dass sie als solche mit Eigennamen dokumentiert sind und dass Bücher darüber geschrieben sind. Grundsätzlich sollten Designprinzipien wie Single Responsibility, Open Close und Interface Segregation vermittelt werden. Leider sind viele Leute, die sich heutzutage als OO-Programmierer bezeichnen, entweder nicht mit diesem grundlegenden Konzept vertraut oder ignorieren es einfach und deshalb gibt es so viel OO-Code für den Müll.

Um die Frage des ursprünglichen Posters 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 denkt das menschliche Gehirn nicht ohne weiteres an "TurnOn" als eine TV-Methode, sondern sieht es als eine Funktion des menschlichen Einschaltens des Fernsehers. In ähnlicher Weise ist Polymorphismus für ein menschliches Gehirn ein Fremdwort, das jedes reale Objekt im Allgemeinen nur mit einem "Gesicht" sieht. Vererbung ist wiederum für unser Gehirn nicht selbstverständlich. Nur weil ich ein Entwickler bin, heißt das nicht, dass mein Sohn einer wäre. Im Allgemeinen muss das menschliche Gehirn trainiert werden, um OO zu lernen, während prozedurale Sprachen für das menschliche Gehirn natürlicher sind.


2
+1 - Ich denke auch nicht, dass Designmuster für den OOP-Unterricht auf der Grundebene notwendig sind. Sie können ein guter OOP-Programmierer sein und kennen kein Designmuster. Auf der anderen Seite sieht man, dass bekannte Designmuster von guten OOP-Programmierern auf natürliche Weise entstehen. Designmuster werden immer entdeckt, nicht erfunden.
Gary Willoughby

1
+1 - Tolle Antwort. Ich mag den 4. Punkt, den Sie angegeben haben. Es ist sehr richtig, dass man ein guter OO-Programmierer sein kann, ohne zu wissen, was Designmuster wirklich sind!
Karthik Sreenivasan

Ich stimme Nummer 4 zu, da die meisten Designmuster nichts anderes als ein Bubblegum / Klebeband-Ansatz sind, um die Einschränkungen der Sprache auszudrücken. In anderen Paradigmen können die Entwurfsmuster völlig unterschiedlich sein und auf ihren eigenen Einschränkungen beruhen. Ich bin mit 2 nicht einverstanden, LINQ und Lambdas werden immer noch in einer prozeduralen Weise ausgeführt. Sie stellen nur ordentlich verpackte Abstraktionen höherer Ebenen bereit. Verbringen Sie einige Zeit mit der Entwicklung einer dynamisch typisierten prozeduralen / funktionalen Sprache wie JavaScript, und Sie werden sehen, was ich meine.
Evan Plaice

6

Ich denke, viele Programmierer haben zunächst Schwierigkeiten mit der Vorausplanung. Selbst wenn jemand das gesamte Design für Sie erledigt, ist es dennoch möglich, sich von den OOP-Grundsätzen zu lösen. Wenn ich einen Haufen Spaghetti-Code nehme und in einer Klasse ablege, ist das dann wirklich OOP? Jemand, der OOP nicht versteht, kann immer noch in Java programmieren. Verwechseln Sie auch nicht die Schwierigkeit, etwas zu verstehen, mit der Absicht, einer bestimmten Methode zu folgen oder dieser nicht zuzustimmen.


5

Sie sollten Objekte nie lesen ? Kaum jemals. (ACM-Mitgliedschaft erforderlich) von Mordechai Ben-Ari, der vorschlägt, dass OOP so schwierig ist, weil es kein Paradigma ist, das für die Modellierung von irgendetwas geeignet ist. (Obwohl ich Vorbehalte gegen den Artikel habe, weil es nicht klar ist, welche Kriterien ein Programm erfüllen muss, um zu sagen, dass es auf dem OOP-Paradigma im Gegensatz zu einem prozeduralen Paradigma in einer OO-Sprache geschrieben ist.)


5

Objektorientierte Programmierung an sich ist nicht schwer.

Das Schwierige ist, es gut zu machen. Wo soll der Code zwischen zwei Codes eingefügt werden, damit Sie die Objekte problemlos in das gemeinsame Basisobjekt verschieben und später erweitern können? Wie Sie Ihren Code für andere nutzbar machen (Klassen erweitern, Proxies einbinden, Überschreibungsmethode), ohne dazu durch Rahmen springen zu müssen.

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 eine Menge Übung erfordert in allen Situationen zu haben , wo Sie es wünschen würden , dass man es anders getan hat, um es gut genug zu tun , diese Zeit.


"Meine persönliche Erfahrung ist, dass es viel Übung erfordert, in all den Situationen gewesen zu sein, in denen Sie sich WÜNSCHEN, dass Sie es anders gemacht haben, um es diesmal gut genug zu machen." OOP scheint eine kodifizierte Liste von Möglichkeiten zu sein, wie man es nicht falsch macht. Das macht keinen Sinn, bis man es auf all diese Arten falsch gemacht hat.
Jared Updike

@Jared, nicht ganz. Vergleichen Sie es mit dem Lösen von sodukus. Es gibt verschiedene Tricks, mit denen Sie es lösen können, aber es braucht Zeit und Übung, um es ohne Zurückverfolgung gut zu machen.

Wenn man sich ein "gemeinsames Stammobjekt" wie einen gemeinsamen Vorfahren vorstellt, wird es klar. Es ist wirklich so einfach. Es ist schwer zu verstehen, dass es so viele irreführende Erklärungen von Leuten gibt, die versuchen, klug auszusehen.
ärgerlich_squid

4

Ich habe mir gerade ein Video von Richard Feynman angesehen, in dem diskutiert wurde, wie Menschen tatsächlich völlig andere Methoden im Kopf haben, wenn sie denken - ich meine, ganz anders.

Wenn ich ein High-Level-Design mache, kann ich Objekte visualisieren, sie sehen, ihre Schnittstellen sehen und sehen, welche Pfade Informationen durchlaufen müssen.

Ich habe auch Probleme, mich an Details zu erinnern, und fand, dass OO eine große organisatorische Hilfe ist - viel einfacher zu finden als das Durchsuchen einer locker 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.


+1 Ich sehe das genauso, aber es gibt viele Schübe in die entgegengesetzte Richtung, einschließlich Ruby-Mixins ... was Sie erkennen lässt, dass strenge OO nicht für jedermann geeignet ist.
Dan Rosenstark

@ Yar Yep, das ist so ziemlich das, was ich gesagt habe. Obwohl ich mir persönlich nichts Besseres vorstellen kann (und Ruby mich für das Jahr, in dem ich es benutzt habe, zu NUTS gemacht hat), beginne ich zu akzeptieren, dass jeder eine andere Sichtweise darauf hat. Vielleicht benutzen manche Leute Berührungen oder Hören, wenn sie denken anstatt zu visualisieren und OO greift einfach nicht für sie ein.
Bill K

Ich denke, es hilft auch dabei, natürlichere Namenskonventionen zu fördern. Sie müssen den Typ einer Funktion nicht mehr in den Funktionsnamen (like INSTR) kodieren, da der Name mit dem Typ (like string::find)
Ken Bloom

@ Ken, obwohl ich damit einverstanden bin, denke ich, dass es eher um starkes Tippen als um OO geht - Ruby hat OO, aber Sie verlieren eine Menge Typinformationen aufgrund des Tippens von Enten - Ruby neigt dazu, einfach "send (it)" zu sagen und zu erwarten Sie wissen, welche magische Methode "es" implementieren muss, um zu funktionieren.
Bill K

@ Bill, du hast recht. Es geht eher um Sprachen, die die generische Programmierung unterstützen. Mit Modul- und Typenklassensystemen wie dem von Haskell können Sie schöne natürliche Namenskonventionen erzielen, und Haskell hat nichts Besonderes. Wenn C überladen wäre, könnten Sie die gleichen Arten von Gattungsnamen in C finden.
Ken Bloom

4

Ich habe getan GW-Basic und Turbo Pascal Programmierung ein gutes Stück vor dem OO eingeführt wird, so es zunächst DID tut meinen Kopf.

Keine Ahnung, ob das 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 als nächstes" usw. Ich habe die Variablen und Daten nie als etwas anderes als flüchtige Akteure im Fluss des Programms angesehen. Programmierung war "der Fluss der Handlungen".

Ich nehme an, was nicht leicht zu verstehen war (so dumm das jetzt 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 zu verstehen, was passiert und nicht, was ist , was der eigentliche Schlüssel zum Erfassen ist.


Interessante Sicht. Während ich mich bemühe, ein großes C ++ - Projekt zu verstehen, denke ich, dass ich genau das Gegenteil bin. Ich denke in erster Linie an Daten, den "Signalpfad" von Bits von einem "Eingang" zu einem "Ausgang". Während ich auch eine Menge Basic und Pascal gemacht habe, war mein frühestes technisches Denken in der Elektronik.
DarenW

3

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

Nach allem, 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ückkehrt und seinen Code nicht ändert, kann es wahrscheinlich schwierig sein, die Vorteile zu verstehen.

Außerdem gibt es da draußen eine Menge schlechter OOP, wenn die Leute das lesen / sehen, ist es leicht zu verstehen, warum sie es schwierig finden könnten.

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


5
Wenn Sie aus einem akademischen Umfeld kommen, erscheinen die Arten von Spielzeugprogrammen, die Sie dort schreiben, auch in OOP wirklich sinnlos. Ich habe im College angefangen, C zu lernen, und das war leicht zu verstehen, da jedes Programm aus einer Seite und weniger als 100 Zeilen bestand. Dann versuchst du, OOP zu lernen und es erfordert all dieses Gepäck und den Overhead von Objekten, um dasselbe zu tun, und es scheint sinnlos. Aber bis Sie ein Programm über viele Dateien und einige Tausend Zeilen geschrieben haben, ist es schwer zu verstehen, warum ein Programmierstil nützlich ist.
CodexArcanum

3

Ich denke, der Grund, warum OOP für viele schwierig ist, ist, dass 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 es sich bei dem, was wir abstrahieren, normalerweise um sehr komplexe physische / soziale Interaktionen handelt, und das ist kein Wunder.


2

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

Außerdem gibt es eine Reihe von Konzepten, die eine Sprache objektorientiert machen - Vererbung, Schnittstellen, Polymorphismus, Komposition usw. Bevor Sie Code effektiv und objektorientiert schreiben können, müssen Sie wirklich viel über die Theorie lernen Während es bei der prozeduralen Programmierung lediglich darum geht, Dinge wie die Speicherzuweisung für Variablen und Einstiegspunktaufrufe für andere Methoden zu verstehen.


Einverstanden - die meisten Schwierigkeiten, die Menschen mit OO haben, bestehen darin, dass sie sich darin geschult haben, „prozedural“ zu denken. OO ist von Natur aus nicht schwierig, aber wenn Sie Verfahrenstechniken kennen, ist es eine große Überraschung, einen anderen Weg zu finden, um Dinge zu strukturieren.
Kirk Broadhurst

Zweifellos ist es eine völlig andere Denkweise als die prozedurale Programmierung. Aber im Gegensatz zu dem, was viele sagen, ist es nicht A) eine unnatürliche Denkweise und B) kompliziert. Ich denke nur, dass es nicht gut gelehrt wird.
ärgerlich_squid

2

Motivation. Es ist schwieriger, etwas zu lernen, wenn Sie nicht wissen, 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, in einem Buch über Entwurfsmuster nachzuschlagen und eines zu finden, das offensichtlich nützlich ist und gut mit OO zusammenarbeitet. (Ich habe Strategy einmal ausprobiert. Etwas wie Flyweight oder Singleton wären eine schlechte Wahl, da sie generell Objekte verwenden und keine Objekte, um etwas zu erreichen.)


Die Leute reden immer nur über Singleton, aber dann ist er immer zu der Party eingeladen. Aber es ist wahr, er ist der Nicht-OO-OO-DP.
Dan Rosenstark

-1

Ich denke, es hängt vom Alter (Alter als Stellvertreter für Erfahrung) und vor allem vom Interesse ab. Wenn Sie "jung" sind (dh grün, vielleicht) und Sie noch nie anders gedacht haben, scheint es ganz einfach zu sein. Auf der anderen Seite, wenn Sie denken, dass es das Coolste ist, was Sie jemals gesehen haben - ist mir im Alter von 28 Jahren passiert oder so -, ist es leicht zu grocken.

Auf der anderen Seite, wenn Sie denken, wie viele meiner Java-Studenten, "warum lernen wir das, es ist nur eine Modeerscheinung", ist es praktisch unmöglich zu lernen. Dies gilt für die meisten Technologien.


1
OO eine Modeerscheinung? Wie alt sind deine Schüler - ich vermute, diese "Modeerscheinung" ist älter als sie (das erste OO, das ich tat - das wusste ich - war Simula um 1983/4 und Simula war zu diesem Zeitpunkt nicht neu)
Murph

@Murph Das war ungefähr 2004-2005 und die Studenten waren definitiv über 45-50 (professionelle Programmierer bei Iberia).
Dan Rosenstark

ok, ich kann irgendwie sehen, wie sie den Start der OO-Sache verpasst haben könnten. Aber von 2004/5 waren wir gut in .NET , der so ziemlich Wand ist OO an der Wand (-: Es gibt Dinge in der Entwicklung eines als Marotten beschreiben könnte , aber diejenigen , die nicht so schnell tun verpuffen neigen dazu , in gute Sachen zu entwickeln
Murph

1
@Murph um ehrlich zu sein, diese Leute waren Mainframe-Programmierer, die versuchten, nach Java zu konvertieren. Es war tatsächlich eine amüsante und einzigartige Erfahrung (kein normaler Tarif für meine Java Trainer-Tage). Es ist jedoch wahr, dass sie viele Dinge kommen und gehen gesehen hatten, aber offensichtlich ist OO mehr als eine Modeerscheinung. Auf einer separaten Anmerkung: Ich hatte gehofft, dass dieses Unit-Testing-Ding als Modeerscheinung auffliegt, aber jetzt muss ich eine Menge Unit-Tests schreiben ... :)
Dan Rosenstark

-1

Unabhängig davon, für welches Paradigma (OOP, funktional usw.) Sie sich entscheiden, um ein Computerprogramm zu schreiben, müssen Sie wissen, welche Schritte Ihr Programm ausführen wird.

Die natürliche Art, einen Prozess zu definieren, besteht darin, seine Schritte aufzuschreiben. Bei größeren Aufgaben teilen Sie die Aufgabe in kleinere Schritte auf. Dies ist der prozedurale Weg, so funktioniert der Computer, so gehen Sie Ihre Checkliste Schritt für Schritt durch.

OOP ist eine andere Denkweise. Anstatt an eine Checkliste mit Aufgaben zu denken, die Schritt für Schritt erledigt werden müssen, denken Sie an Objekte, ihre Fähigkeiten und Beziehungen. Sie werden also viele Objekte und kleine Methoden schreiben und Ihr Programm wird auf magische Weise funktionieren. Um dies zu erreichen, müssen Sie Ihren Verstand verdrehen ...

Und deshalb ist OOP schwierig. Da alles ein Objekt ist, bitten sie nur andere Objekte, etwas zu tun, und diese anderen Objekte tun im Grunde genommen das Einige. So kann die Steuerung in einem OOP-Programm wild zwischen den Objekten hin und her springen.


-1

Als jemand, der gerade Programmieren lernt und einige Probleme in diesem Bereich hat, denke ich nicht, dass es so schwer zu verstehen ist, wie die spezifischen Implementierungen dieses Konzepts. Ich sage das, weil ich die Idee zu OOP habe und sie seit ungefähr einem Jahr in PHP verwende, aber als ich mich mit C # befasse und die Verwendung von Objekten durch andere Programmierer betrachte, stelle ich fest, dass dies viele Leute auf unterschiedliche Weise tun das verstehe ich einfach nicht. Genau dies hat mich auf den Weg gebracht, die Prinzipien von OOP besser zu verstehen.

Natürlich ist mir klar, dass das Problem höchstwahrscheinlich mein Mangel an Erfahrung mit einer OOP-Sprache ist, und dass ich im Laufe der Zeit neue Wege finden werde, um Objekte zu nutzen, die für einen neuen Programmierer genauso unklar sind wie ich derzeit erleben. Jerry Coffin erwähnt dies einige Male, insbesondere in seinem Kommentar:

Dies wird besonders problematisch, wenn Sie einerseits erfahren, dass ein großer Vorteil von OOP darin besteht, die Realität genauer zu modellieren, aber Sie beginnen damit, dass Sie eine sehr ähnliche, von LSD inspirierte Sicht auf die grundlegendsten und offensichtlichsten Teile von OOP haben Wirklichkeit.

Ich finde das sehr genau, da es der Eindruck ist, den ich oft bekomme, wenn ich jemanden sehe, der Klassen für Dinge erstellt, die nicht wirklich Dinge sind. Ein konkretes Beispiel entgeht mir ein Objekt (ich bearbeite es, wenn ich das nächste Mal etwas sehe, das die gleiche Verwirrung hervorruft). Manchmal scheint OOP seine eigenen Regeln vorübergehend zu missachten und wird weniger intuitiv. Dies tritt meistens dann auf, wenn Objekte Objekte produzieren, die von einer Klasse geerbt werden, die sie usw. einkapselt.

Ich denke, für jemanden wie mich ist es hilfreich, sich das Konzept von Objekten als vielschichtig vorzustellen, wobei eine davon darin besteht, etwas wie ein Objekt zu behandeln, wenn es sonst nicht wäre. So etwas wie Distanz könnte mit nur einem kleinen Paradigmenwechsel als theoretisches Objekt erscheinen, aber nicht als Objekt, das in der Hand gehalten werden könnte. Ich muss mir vorstellen, dass es eine Reihe von Eigenschaften hat, aber eine abstraktere Reihe von Verhaltensweisen, z. B. den Zugriff auf seine Eigenschaften. Ich bin mir nicht sicher, dass dies der Schlüssel zu meinem Verständnis ist, aber es scheint, als ob dies der Weg ist, den meine derzeitigen Studien gehen.


1
Ein Paar von Punkten oder Objekten sollte als Objekt betrachtet werden. Die Entfernung sollte als Funktion vom Objekt genommen werden. Das Verwenden von Objekten bedeutet nicht, dass Sie Objekte aus allem erstellen.
Gangnus

Die Entfernung war, wie gesagt, ein schlechtes Beispiel. Bezüglich der Herstellung eines Objekts aus allem beziehe ich mich speziell auf das, was ich gesehen habe, und nicht auf das, was ich tatsächlich getan habe - was bis jetzt noch nichts ist.
Dsimer

Es kommt auf die Sprache an - in SmallTalk IST die Entfernung (und alles) ein Objekt. Aber in C # haben Sie erwähnt, dass es schlecht wäre.
Gangnus

-2

Terminologien waren mein Hindernis beim Erlernen der Prinzipien der objektorientierten Programmierung (POOP). Wenn Sie sich ein Bild von den Grundlagen machen, fangen die Teile an, sich zusammenzufügen. Genau wie alles, was das Lernen neuer Konzepte angeht, ist es etwas schwierig.

Einverstanden, dass Entwurfsmuster zumindest parallel zu OOP unterrichtet werden sollten.


-2

Der Hauptsprung für mich bestand darin, das abstrakte Konzept von OOP zu verstehen. Jetzt bin ich ganz neu in der Programmierung im Allgemeinen. Ich programmiere jetzt seit eineinhalb Jahren, und meine Einführung in OOP erfolgte mit Actionscript und Processing. Als ich das erste Mal Actionscript-Codierung gelernt habe, war es nicht in OOP. Ich habe gelernt, direkt im Bedienfeld Aktionen zu programmieren, und so habe ich die grundlegenden Grundlagen der Programmierung (Variablen, Funktionen, Schleifen usw.) gelernt. Ich habe es gelernt, indem ich etwas direkt mit der Bühne in Flash oder Processing gemacht habe.

Als OOP anfing, war es für mich zunächst schwierig zu verstehen, dass ich Methoden und Eigenschaften in einem Objekt erstellen konnte, um sie verwenden und wiederverwenden zu können. Alles war sehr abstrakt und schwierig zu verarbeiten, aber die Programmiersprachen selbst waren viel besser, aber es erforderte zunächst einen Vertrauenssprung, um diese Verbindungen herzustellen.


Wow, ein Teil davon ergab keinen Sinn. "Alles war sehr abstrakt und schwierig zwischen Klassen und Instanzen von Objekten zu verarbeiten. Aber die Programmiersprachen wurden viel einfacher zu verstehen, sobald ich OOP bekam. Aber es war ein kleiner Schritt, um diese Verbindungen

-2

Rezept

Gutes OOP-Verständnis = Guter Mentor oder gute Bücher oder beides + persönliches Interesse + Übung.

Persönliches Interesse

Persönliches Interesse ist meiner Erfahrung nach ein langer Weg, um die Brücke zwischen prozeduraler Programmierung und OOP zu schlagen, wobei die richtigen Inputs von Mentoren oder guten Büchern oder beidem kombiniert werden .

Üben, üben und üben

Mein bester Freund , um OOP besser zu verstehen, war nichts anderes als Übung. Dies wird definitiv Ihre OOP-Fähigkeiten fördern.

Wie das Sprichwort sagt: "Es gibt keinen Ersatz für harte Arbeit und keine Abkürzung zum Erfolg."

Viel Glück!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.