it-swarm-eu.dev

Vorteile der objektorientierten Programmierung

Hinweis : Diese Frage ist ein bearbeiteter Auszug aus einem Blogeintrag Ich habe vor einigen Monaten geschrieben. Nachdem ich einen Link zum Blog in einem Kommentar auf Programmers.SE platziert hatte, bat mich jemand, hier eine Frage zu posten, damit er sie beantworten konnte. Dieser Beitrag ist mein beliebtester, da die Leute anscheinend "Ich bekomme keine objektorientierte Programmierung" in Google viel eingeben. Fühlen Sie sich frei, hier oder in einem Kommentar bei Wordpress zu antworten.

Was ist objektorientierte Programmierung? Niemand hat mir eine zufriedenstellende Antwort gegeben. Ich habe das Gefühl, dass Sie von jemandem, der mit der Nase in der Luft „Objekt“ und „Objektorientiert“ sagt, keine gute Definition erhalten. Sie erhalten auch keine gute Definition von jemandem, der nur objektorientierte Programmierung durchgeführt hat. Niemand, der sowohl prozedurale als auch objektorientierte Programmierung versteht, hat mir jemals eine konsistente Vorstellung davon gegeben, was ein objektorientiertes Programm tatsächlich tut.

Kann mir bitte jemand seine Vorstellungen von den Vorteilen der objektorientierten Programmierung geben?

35
Joel J. Adamson

Stellen Sie sich Software als Maschine oder Montagelinie vor, die im Computer vorhanden ist. Einige Rohstoffe und Komponenten werden in die Maschine eingespeist, und es folgen eine Reihe von Verfahren, um sie zu einem Endprodukt zu verarbeiten. Die Verfahren sind so eingerichtet, dass eine bestimmte Operation an einem Rohmaterial oder einer Komponente mit einem bestimmten Satz von Parametern (z. B. Zeit, Temperatur, Entfernung usw.) in einer bestimmten Reihenfolge ausgeführt wird. Wenn die Details des auszuführenden Vorgangs falsch waren oder die Sensoren der Maschine nicht korrekt kalibriert waren oder wenn ein Rohmaterial oder eine Komponente nicht den erwarteten Qualitätsstandards entsprach, könnte dies das Ergebnis des Vorgangs ändern und das Produkt würde sich nicht herausstellen wie erwartet.

Eine solche Maschine ist sehr starr in ihrem Betrieb und akzeptablen Eingaben. Maschinen stellen weder die Intelligenz der Konstrukteure noch die aktuelle Betriebsumgebung in Frage. Es wird weiterhin Verfahren befolgen, solange es angewiesen ist. Selbst wenn eine Änderung der Rohstoffe oder Komponenten dramatische Auswirkungen auf die späteren Betriebsabläufe haben könnte, würde die Maschine ihre Verfahren dennoch ausführen. Der Prozess müsste überprüft werden, um festzustellen, welche Änderungen an den Verfahren erforderlich sind, um das gewünschte Ergebnis zu kompensieren und zu erzielen. Eine Änderung des Produktdesigns oder der Produktkonfiguration kann auch eine wesentliche Änderung der durchgeführten Vorgänge oder ihrer Reihenfolge erforderlich machen. Obwohl die Produktionsverantwortlichen schnell gelernt haben, wie wichtig es ist, Vorgänge so weit wie möglich zu isolieren, um unerwünschte Auswirkungen zwischen ihnen zu verringern, werden viele Annahmen darüber getroffen, in welchem ​​Zustand sich die Komponenten befinden, während sie verarbeitet werden. Annahmen, die möglicherweise erst erkannt werden, wenn sich das Endprodukt in einer anderen Betriebsumgebung in den Händen des Benutzers befindet.

So ist prozedurale Programmierung.

Die Objektorientierung bietet eine Möglichkeit, die Annahmen über den Zustand von Komponenten zu entfernen. Daher die Operationen, die an dieser Komponente ausgeführt werden müssen, und wie sie in das Endprodukt integriert werden kann. Mit anderen Worten, OOP ist so, als würde man die Prozessdetails für den Umgang mit einer bestimmten Komponente übernehmen und sie einer kleineren Maschine übergeben. Die größere Maschine, die für den Prozess verantwortlich ist, teilt der komponentenspezifischen Maschine mit, welche Der erwartete Vorgang wird ausgeführt, die Details für die Schritte werden jedoch der komponentenspezifischen Maschine überlassen.

Zu den Vorteilen der Objektorientierung gegenüber nicht objektorientierter Software:

  • komponentenspezifisches Verhalten - Wenn Sie festlegen, wie mit einer bestimmten Komponente umgegangen werden soll, wird die Verantwortung der kleineren komponentenspezifischen Maschine sichergestellt, dass die Maschine dies bei jeder Handhabung der Komponente angemessen tut.
  • polymorphe Ausdrücke - Da komponentenspezifische Maschinen Operationen ausführen, die auf die jeweilige Komponente zugeschnitten sind, kann dieselbe an verschiedene Maschinen gesendete Nachricht unterschiedlich wirken.
  • Typabstraktion - Es ist oft sinnvoll, dass mehrere verschiedene Arten von Komponenten dasselbe Vokabular für die Operationen verwenden, die ihre Maschinen ausführen.
  • Trennung von Bedenken - Wenn komponentenspezifische Details ihren Maschinen überlassen werden, muss die Prozessmaschine nur die allgemeineren, größeren Bedenken ihres Prozesses und die für die Verwaltung erforderlichen Daten behandeln. Außerdem ist es weniger wahrscheinlich, dass Änderungen an anderen Komponenten auftreten.
  • Anpassungsfähigkeit - Komponenten, die sich auf ihren Fachbereich konzentrieren, können an unvorhergesehene Verwendung angepasst werden, indem einfach die verwendeten Komponenten geändert oder einer anderen Prozessmaschine zur Verfügung gestellt werden.
  • Wiederverwendung von Code - Komponenten mit einem engen Fokus und größerer Anpassungsfähigkeit können ihre Entwicklungskosten nutzen, indem sie häufiger verwendet werden.
7
Huperniketes

Aus Ihrem Blog geht hervor, dass Sie sowohl mit der imperativen als auch mit der funktionalen Programmierung vertraut sind und mit den grundlegenden Konzepten der objektorientierten Programmierung vertraut sind, aber Sie haben es nie wirklich "angeklickt", worauf es ankommt macht es nützlich. Ich werde versuchen, dieses Wissen zu erklären, und hoffe, dass es Ihnen hilfreich ist.

Im Kern ist OOP eine Möglichkeit, das imperative Paradigma zu verwenden, um hohe Komplexitätsgrade besser zu verwalten, indem "intelligente" Datenstrukturen erstellt werden, die die Problemdomäne modellieren. In einem (standardmäßigen prozeduralen Nichtobjekt) -orientiertes Programm haben Sie zwei grundlegende Dinge: Variablen und Code, der weiß, was mit ihnen zu tun ist. Der Code nimmt Eingaben vom Benutzer und verschiedenen anderen Quellen entgegen, speichert sie in Variablen, bearbeitet sie und erzeugt Ausgabedaten das geht an den Benutzer oder verschiedene andere Orte.

Objektorientierte Programmierung ist eine Möglichkeit, Ihr Programm zu vereinfachen, indem Sie dieses Grundmuster verwenden und es in kleinerem Maßstab wiederholen. So wie ein Programm eine große Sammlung von Daten mit Code ist, der weiß, was damit zu tun ist, ist jedes Objekt ein kleines Datenelement, das an Code gebunden ist und weiß, was damit zu tun ist.

Indem Sie die Problemdomäne in kleinere Teile zerlegen und sicherstellen, dass so viele Daten wie möglich direkt an Code gebunden sind, der weiß, was damit zu tun ist, können Sie den gesamten Prozess und auch die Subdomäne viel einfacher überdenken Probleme, die den Prozess ausmachen.

Durch Gruppieren von Daten in Objektklassen können Sie Code in Bezug auf diese Daten zentralisieren und so das Auffinden und Debuggen von relevantem Code erleichtern. Indem Sie die Daten hinter Zugriffsspezifizierern kapseln und nur über Methoden (oder Eigenschaften, sofern Ihre Sprache diese unterstützt) darauf zugreifen, verringern Sie das Risiko einer Datenbeschädigung oder der Verletzung von Invarianten erheblich.

Durch die Verwendung von Vererbung und Polymorphismus können Sie bereits vorhandene Klassen wiederverwenden und an Ihre spezifischen Anforderungen anpassen, ohne die Originale ändern oder alles von Grund auf neu schreiben zu müssen. (Was ist ein was Sie niemals tun sollten , wenn Sie es vermeiden können.) Seien Sie nur vorsichtig, dass Sie Ihr Basisobjekt verstehen, oder Sie könnten mit Killerkängurus enden.

Für mich sind dies die Grundprinzipien der objektorientierten Programmierung: Komplexitätsmanagement, Codezentralisierung und verbesserte Modellierung von Problemdomänen durch die Erstellung von Objektklassen, Vererbung und Polymorphismus sowie erhöhte Sicherheit ohne Einbußen bei Leistung oder Kontrolle durch die Verwendung von Kapselung und Eigenschaften. Ich hoffe, das hilft Ihnen zu verstehen, warum so viele Programmierer es nützlich finden.

EDIT: Als Antwort auf Joels Frage in den Kommentaren,

Können Sie erklären, was ein "objektorientiertes Programm" enthält (abgesehen von diesen ausgefallenen Definitionen, die Sie skizziert haben), das sich grundlegend von einem imperativen Programm unterscheidet? Wie bringt man den Ball ins Rollen?

Ein kleiner Haftungsausschluss hier. Mein Modell eines "objektorientierten Programms" ist im Grunde das Delphi-Modell, das dem C # /. NET-Modell sehr ähnlich ist, da sie von ehemaligen Delphi-Teammitgliedern erstellt wurden. Was ich hier sage, gilt möglicherweise nicht oder nicht so oft in anderen OO Sprachen).

Ein objektorientiertes Programm ist eines, bei dem die gesamte Logik um Objekte herum strukturiert ist. Natürlich muss dies irgendwo gebootet werden. Ihr typisches Delphi-Programm enthält Initialisierungscode, der ein Singleton-Objekt mit dem Namen Application erstellt. Zu Beginn des Programms wird Application.Initialize, dann ein Anruf an Application.CreateForm für jedes Formular, das Sie von Anfang an in den Speicher laden möchten, und dann Application.Run,, das das Hauptformular auf dem Bildschirm anzeigt und die Eingabe-/Ereignisschleife startet, die den Kern aller interaktiven Computerprogramme bildet.

Die Anwendung und Ihre Formulare suchen nach eingehenden Ereignissen vom Betriebssystem und übersetzen sie in Methodenaufrufe für Ihr Objekt. Eine Sache, die sehr häufig vorkommt, ist die Verwendung von Ereignishandlern oder "Delegaten" in .NET-Sprache. Ein Objekt verfügt über eine Methode, die besagt: "X und Y ausführen, aber auch prüfen, ob dieser bestimmte Ereignishandler zugewiesen ist, und ihn aufrufen, falls dies der Fall ist." Ein Ereignishandler ist ein Methodenzeiger - ein sehr einfacher Abschluss, der einen Verweis auf die Methode und einen Verweis auf die Objektinstanz enthält -, mit dem das Verhalten von Objekten erweitert wird. Wenn ich beispielsweise ein Schaltflächenobjekt in meinem Formular habe, passe ich sein Verhalten an, indem ich einen OnClick-Ereignishandler anhänge, der bewirkt, dass ein anderes Objekt eine Methode ausführt, wenn auf die Schaltfläche geklickt wird.

In einem objektorientierten Programm wird der größte Teil der Arbeit erledigt, indem Objekte mit bestimmten Verantwortlichkeiten definiert und miteinander verknüpft werden, entweder über Methodenzeiger oder durch ein Objekt, das direkt eine in der öffentlichen Schnittstelle eines anderen Objekts definierte Methode aufruft. (Und jetzt sind wir wieder bei der Kapselung.) Dies ist eine Idee, von der ich kein Konzept hatte, bevor ich OOP) Kurse am College belegte.

46
Mason Wheeler

Ich denke, OOP ist im Grunde nur ein Name für etwas, zu dem Sie auf dem Weg versucht waren, so wie ich es war.

Als ich noch ein Babyprogrammierer war, gab es sogar in Fortran so etwas wie einen Zeiger auf eine Unterroutine. Es ist sehr nützlich, einen Zeiger auf eine Unterroutine als Argument an eine andere Unterroutine übergeben zu können.

Dann wäre das nächste, was wirklich nützlich wäre, einen Zeiger auf eine Unterroutine in einem Datensatz einer Datenstruktur zu speichern. Auf diese Weise könnte man sagen, dass der Datensatz "weiß", wie Operationen an sich selbst ausgeführt werden.

Ich bin mir nicht sicher, ob sie das jemals in Fortran eingebaut haben, aber es ist einfach in C und seinen Nachkommen.

Darunter ist es eine einfache und nützliche Idee, dass Sie möglicherweise versucht waren, sich selbst zu tun, und es ist einfacher, dies in neueren Sprachen zu tun, selbst wenn einige Leute daraus einen riesigen Zug voller gruseliger Schlagworte machten.

6
Mike Dunlavey

Es gibt verschiedene Arten von OO - Systemen, und es ist schwierig, eine Definition zu erhalten, auf die sich alle einigen werden. Anstatt zu zeigen, wie Java OO] dem Common ähnelt LISP Object System, ich beginne Schritt für Schritt mit etwas Konventionellerem.

Angenommen, Sie haben viele Objekte als verstreute Daten. Punkte können beispielsweise Elemente in einem X-, einem Y- und einem Z-Array sein. Um einen Punkt selbst zu betrachten, ist es sinnvoll, alle Daten zu einem C struct zusammenzufassen.

Jetzt haben wir für jedes Datenobjekt alle Daten zusammen. In einem prozeduralen Programm ist der Code jedoch verstreut. Angenommen, wir haben es mit geometrischen Formen zu tun. Es gibt eine große Funktion zum Zeichnen von Formen, und es muss über alle Formen Bescheid wissen. Es gibt eine große Funktion, um einen Bereich zu finden, und eine andere für den Umfang. Der Code für einen Kreis ist über mehrere Funktionen verteilt. Um eine andere Form hinzuzufügen, müssen wir wissen, welche Funktionen geändert werden müssen. In einem objektorientierten System sammeln wir die Funktionen in der gleichen Art von Dingen (class) wie die Daten. Wenn wir uns also den gesamten Kreiscode ansehen möchten, befindet er sich in der Definition von Circle. Wenn wir ein Quartercircle hinzufügen möchten, schreiben wir einfach seine Klasse und haben den Code .

Ein Nebeneffekt davon ist, dass wir Klasseninvarianten beibehalten können, Dinge, die für jedes Mitglied der Klasse zutreffen. Indem wir verhindern, dass Code außerhalb der Klasse direkt mit Klassendatenelementen in Konflikt gerät, haben wir den gesamten Code, der Klassendaten an einem Ort ändern kann, und wir können bestätigen, dass er nichts Verrücktes bewirkt (wie ein Dreieck mit einem Bein) länger als die beiden anderen zusammen). Dies bedeutet, dass wir uns auf einige Eigenschaften jedes Mitglieds der Klasse verlassen können und nicht jedes Mal überprüfen müssen, ob ein Objekt gesund ist, wenn wir es verwenden.

Der Hauptvorteil liegt in der Vererbung und dem Polymorphismus. Indem wir all diese verschiedenen Formen als Unterklassen einer Klasse mit dem Namen Shape definieren, können wir unseren Code Shapes manipulieren lassen, und es ist die Aufgabe der Form-Unterobjekte, alles zu tun, was für die Manipulationen erforderlich ist . Dies bedeutet, dass wir den alten getesteten Code nicht berühren müssen, wenn wir neue Formen hinzufügen oder das Verhalten älterer Formen verfeinern. Wir haben automatisch alten Code, der neuen Code direkt nutzen kann. Anstatt den Steuerungscode auf die verschiedenen möglichen Formen aufmerksam zu machen und Funktionen zu verwalten, die alle verschiedenen möglichen Formen kennen, behandeln wir lediglich Formen und ihre Eigenschaften, während Shape Unterklassen beibehalten werden. Dies vereinfacht den Steuercode.

Wir haben hier mehrere Vorteile. Da wir Klasseninvarianten haben, können wir über größere Datenobjekte genauso argumentieren wie über integrierte Typen, was bedeutet, dass wir komplexe Konzepte häufig in einfachere aufteilen können. Da der Kreiscode größtenteils in Circle enthalten ist, haben wir die Lokalität erhöht. Da es keine Konzepte für einen Kreis gibt, der über verschiedene Funktionen an verschiedenen Orten verstreut ist, erhalten wir weniger Kopplung zwischen Routinen und müssen uns nicht darum kümmern, sie synchron zu halten. Da Klassen praktisch Typen sind, können wir das vorhandene Typsystem nutzen, um eine inkompatible Verwendung unserer Klassen zu erkennen.

5
David Thornley

OO hat viele verschiedene Definitionen, ja. Ich bin sicher, Sie können viele davon selbst finden. Ich persönlich mag Rees Re: OO , um sie zu verstehen. Ich vermute, Sie haben das schon gelesen, seit Sie Paul Graham zitiert haben. (Ich empfehle es jedem, der an OO interessiert ist.) Ich werde mehr oder weniger die Definition Java hier {1,2,3,7,8,9} übernehmen.

Die Frage nach dem Nutzen von OO, insbesondere nach meiner Herangehensweise, verdient eine viel umfassendere Antwort mit einigen tausend Codezeilen (teilweise, um nicht nur eine Reihe von Behauptungen zu sein). Hier ist jedoch eine Zusammenfassung dieses hypothetischen Dokuments.

Ich denke nicht, dass OO in kleinem Maßstab, etwa ein paar hundert Zeilen, furchtbar nützlich ist. Insbesondere neigen OO Sprachen ohne gute funktionale Einflüsse dazu um es wirklich schmerzhaft zu machen, einfache Dinge mit jeder Art von Sammlung oder irgendetwas zu erledigen, das viele Datentypen benötigt. Hier kommen die meisten Entwurfsmuster ins Spiel; sie sind Pflaster für die geringe Leistung des Basiswerts Sprache .

Bei ungefähr tausend Zeilen wird es schwieriger, alle Vorgänge und Datenstrukturen und ihre Beziehung zu verfolgen. An dieser Stelle ist es hilfreich, Datenstrukturen und -vorgänge explizit zu organisieren, Modulgrenzen zu zeichnen und Verantwortlichkeiten zu definieren und diese Definitionen bequem zu verstehen, während Sie versuchen, gegen sie zu programmieren.

Java-ish OO ist eine halbe Lösung für diese Probleme, die zufällig den Beliebtheitswettbewerb gewonnen haben. Weil es der gleiche Mechanismus ist, den Java Leute auf die Kleinen anwenden Skalierungsprobleme, die durch eine unterkompetente Sprache verursacht werden, sehen eher wie eine magische Lösung für alles aus als nur wie eine Möglichkeit, organisiert zu bleiben. Personen, die mit funktionaler Programmierung vertraut sind, bevorzugen andere Lösungen wie CLOS- oder Haskell-Typklassen oder Template-Metaprogrammierung, wenn stecken in C++, oder (wie ich, arbeite täglich in C #) benutze OO, aber sei einfach nicht so aufgeregt darüber.

3
Jesse Millikan

OOP = Datenstrukturen + Nachrichtenübermittlung + Vererbung, alles logische Entwicklungen in Programmiermodellen.

OOP kann (von Programmierern) in ca. 90 Sekunden verstanden werden (siehe mein Profil für einen Link). Die Konzepte sind sehr einfach.

Wie man es anwendet, ist eine andere Sache. Nur weil Sie wissen, wie man einen Hammer schwingt, heißt das nicht, dass Sie wissen, wie man ein Haus entwirft und baut. ;-);

1
Steven A. Lowe

OOP versucht, reale Konzepte in Bezug auf Objekte und Interaktionen zwischen ihnen zu modellieren. Als Menschen neigen wir dazu, die Welt in Bezug auf Objekte zu verarbeiten. Die Welt ist voll von Objekten, die bestimmte Eigenschaften haben und Dinge wie die Interaktion mit anderen Objekten tun können. OOP ermöglicht es, die Welt in ähnlichen Begriffen zu modellieren. Zum Beispiel:

  • Person ist ein Objekt. Eine Person hat einige Eigenschaften wie Alter und Geschlecht. Eine Person kann Dinge tun: essen, schlafen, Auto fahren.
  • Auto ist auch ein Objekt (obwohl von unterschiedlichem Typ). Es hat auch Eigenschaften wie Marke, Modell und Jahr. Ein Auto kann Dinge tun: sich bewegen.

Aber ein Auto kann sich nicht alleine bewegen, es braucht eine Person, um es zu fahren - Interaktion zwischen Objekten.

1
ysolik

Da Sie Strukturen verstehen und Funktionszeiger verstehen und Strukturen mit Funktionszeigern verstehen, würde ich aus Ihrer Sicht objektorientierte Programmierung einfach als "Programmierung mit starker Verwendung von Strukturen mit Funktionszeigern" definieren. Es wird immer noch im traditionellen Sinne programmiert - es sind alle Daten und Code, die auf die Daten einwirken. Der Unterschied besteht einfach darin, wie all diese Informationen definiert sind und wie Sie sie definieren.

Möglicherweise besteht eine übermäßige Vereinfachung darin, dass die traditionelle Programmierung "Code mit einigen Datenstrukturen" und die objektorientierte Programmierung "Datenstrukturen mit einigen Codes" ist. Beide haben noch Datenstrukturen und beide haben noch Code. Objektorientierte Programmierung ist also nichts anderes als das Definieren von Datentypen im Voraus und das Durchsetzen von Verträgen für deren Kommunikation über Funktionssätze.

Wie Sie bemerkt haben, gibt es eine große Klasse von Anwendungen, für die dies keine großartige Möglichkeit ist, eine Lösung zu implementieren. Sie scheinen in einer Welt zu leben, die überwiegend aus solchen Anwendungen besteht. In Ihrem Blog-Beitrag erwähnen Sie die Implementierung des Problems "99 Flaschen Bier" (Ihr "Lieblingsprogrammier-Schaufenster"). 99 Flaschen Bier gehören sicherlich zu dieser Kategorie. Der Versuch, die objektorientierte Programmierung anhand von Implementierungen von 99 Flaschen Bier zu verstehen, ähnelt dem Versuch, die Hochhausarchitektur anhand eines Baumhauses zu verstehen. Selbst ein sehr gut gebautes Baumhaus kann Ihnen nur so viel beibringen.

TL; DR: OO Programmierung ist wie herkömmliche Programmierung, außer dass Sie sich mehr auf die Definition der Datenstrukturen im Voraus konzentrieren und diese Datenstrukturen über Funktionszeiger miteinander kommunizieren.

0
Bryan Oakley

Ich habe es zuerst so verstanden:

Vor der objektorientierten Programmierung hatten Sie Strukturierte Programmierung . Alles dreht sich um den Prozess. Die erste Frage, die Sie sich stellen müssen, lautet " Was möchte ich mit den Informationen machen? ".

Bei der objektorientierten Programmierung werden die Daten zentriert. Die erste Frage, die Sie sich stellen müssen, lautet " Hexeninformationen, mit denen ich mich befassen muss? ". Dies erleichtert die Abstraktion.

0
DavRob60

Ich habe vor einiger Zeit einen Blog-Beitrag geschrieben, den Sie vielleicht hilfreich finden: Procedural vs. OOP Explained .

0
VirtuosiMedia