JavaRush /Java-Blog /Random-DE /Objektorientierte Programmierung (Übersetzung des Artikel...
Exidnus
Level 38
Санкт-Петербург

Objektorientierte Programmierung (Übersetzung des Artikels)

Veröffentlicht in der Gruppe Random-DE
Vom Übersetzer: Leider habe ich keine nennenswerte Erfahrung im Übersetzen aus dem Englischen, obwohl ich ziemlich viel auf Englisch lese. Es stellte sich jedoch heraus, dass Lesen und Übersetzen zwei verschiedene Dinge sind. Außerdem verfüge ich leider nicht über nennenswerte Programmiererfahrung (ich habe kürzlich eine einfache Webanwendung in Spring MVC und Hibernate erstellt). Daher fiel die Übersetzung viel schlechter aus, als sie hätte sein können. Ich habe mir erlaubt, die im Artikel angegebenen Codebeispiele leicht zu korrigieren, da sie nicht den Namenskonventionen in Java entsprechen. Vielleicht hat es sich nicht gelohnt, die Namen einiger Muster zu übersetzen (eine solche Übersetzung bringt nicht viel Verständnis), aber ich dachte, dass dies das kleinere Übel sei. „Hohe Kohäsion“ als Übersetzung von „hohe Kohäsion“ ist gesondert zu erwähnen. Ich stimme zu, nicht die beste Übersetzung. Aber „starke Konnektivität“ ist „hohe Kopplung“ (ein weiteres wichtiges Konzept), und „Kohärenz“ ist hier wahrscheinlich nicht geeignet. Ich bin offen für Kritik und nehme Kommentare zum Artikel in jeder Form dankbar an. Objektorientierte Programmierung ist ein Programmierstil, bei dem ein Programm aus Komponenten besteht, die realen Objekten entsprechen. Jedes reale Objekt hat einige Eigenschaften (die sich im Laufe der Zeit ändern können oder nicht) und ein Verhalten (das sich ändern kann oder auch nicht). abhängig von anderen Bedingungen). Ein Bleistift ist beispielsweise ein reales Objekt mit den folgenden Eigenschaften:
  • Es ist rot (dies ändert sich im Laufe der Zeit nicht).
  • Es ist jetzt 10 Zentimeter lang (dies kann sich ändern, wenn der Bleistift angespitzt wird).
Und es hat das folgende Verhalten:
  • Bei richtiger Anwendung hinterlässt es Spuren.
  • Die Spur kann je nach Druck (abhängig von externen Faktoren) unterschiedlich sein.
  • Seine Länge verkürzt sich beim Schärfen (permanentes Verhalten).
Wie in diesem Beispiel können reale Objekte viele Eigenschaften haben, aber beim Schreiben von Programmen berücksichtigen wir nur die notwendigen Eigenschaften. Objektorientierte Programmierung hat ihre Vorteile. So lässt sich beispielsweise leichter eine Verbindung zwischen einem realen Objekt und einem Programm auf die erwartete Weise herstellen. Das hilft wirklich, wenn die Anwendung wächst und viele Objekte miteinander interagieren. Dies hilft bei der Verteilung der Verantwortlichkeiten innerhalb der objektiven Welt, sodass Sie sich auf das Durchdenken der Anwendung konzentrieren können. Ein weiteres wichtiges Merkmal von OOP (Object Oriented Programming) ist die Klassifizierung von Objekten. Da die Welt (real/virtuell) voller Objekte ist, ist es schwierig, diese einzeln zu steuern. Wir brauchen eine Möglichkeit, diese Objekte zu klassifizieren, die uns hilft, verschiedene Objekte und ihre Eigenschaften zuzuordnen, wie zum Beispiel einen schwarzen Stift. Wenn es im vorherigen Beispiel verwendet würde, wäre es nicht zu unterscheiden (dasselbe?), aber es ist ein anderes Objekt. Da es sich aber beide um Bleistifte handelt, gehören sie zur selben Klasse „Bleistift“. Ein Kugelschreiber hingegen, der einem Bleistift sehr ähnlich ist, gehört zu einer anderen Klasse. Kugelschreiber und Bleistift sind jedoch beide „Schreibgeräte“. Die objektorientierte Programmierung basiert auf den folgenden Prinzipien:
Abstraktion
Abstraktion wird als die Qualität der Interaktion mit Ideen und nicht mit Ereignissen definiert oder mit anderen Worten als Freiheit von Darstellungsqualitäten . Dadurch können sich Programmierer auf das konzentrieren, was sie programmieren , und nicht darauf , wie sie programmieren . Abstraktion kann als ein Vertrag betrachtet werden, durch den wir Funktionalität bereitstellen. Bei Verwendung dieses Konzepts können Implementierungsdetails ausgeblendet werden. Wenn wir beispielsweise eine schreibende Klasse benötigen, müssen wir sicherstellen, dass sie über eine „Schreib“-Methode verfügt. abstract class writer { write (); } Was haben wir getan? Wir haben eine High-Level-Klasse entworfen, die abstrakt ist, das heißt, sie weiß, welche Funktionalität wir benötigen, aber wie sie implementiert wird, liegt außerhalb des Geltungsbereichs dieser Klasse. Das bietet viele Vorteile:
  • Wir geben die minimal notwendigen Informationen an externe Stellen weiter. Dies ermöglicht es uns, uns auf das Durchdenken des Programms zu konzentrieren (dies ermöglicht gezieltes Denken), Verwirrung zu vermeiden und unbeabsichtigte Versprechungen zu vermeiden.
  • Wir lassen Raum für zukünftige Verbesserungen, die bei Offenlegung von Implementierungsdetails nicht möglich wären.
Nachlass
„Inheritance“ bedeutet im allgemeinen Englisch „erwerben und weitergeben“. Dieses Wort existiert in unserer Kultur schon sehr lange. Die Vorfahren erwarben durch harte Arbeit Land und vererbten es an ihre Kinder, auch die Natur begünstigt die Vererbung. Alle Körpereigenschaften wie Größe, Haut-/Augen-/Haarfarbe usw. hängen von den Genen ab, die wir von unseren Eltern erben. Vererbung verhindert, dass das Rad neu erfunden wird, und beschleunigt den Fortschritt. Das Gleiche gilt für OOP. Wir erstellen eine übergeordnete Klasse mit einigen grundlegenden Eigenschaften/Verhaltensweisen. Alle von dieser übergeordneten Klasse erbenden Klassen enthalten dieselben Eigenschaften/Verhaltensweisen wie ihre übergeordneten Klassen. Geerbte Klassen können jedoch mehr Eigenschaften/Verhalten erhalten oder die Implementierung des Verhaltens ändern. class WritingInstrument { colour; write() { } } class Pen (child of parent) { inkcolour; } Im obigen Beispiel verfügt die übergeordnete Klasse (WritingInstrument) über eine „Color“-Eigenschaft und ein „Write“-Verhalten. Wenn die abgeleitete Klasse (Handle) deklariert wird, müssen die Eigenschaft „Farbe“ und das Verhalten „Schreiben“ nicht erneut deklariert werden. Aufgrund der Vererbung sind sie in der Klasse „handle“ vorhanden. Eine Nachkommenklasse kann jedoch ihre eigenen zusätzlichen Eigenschaften/Verhalten deklarieren. Wie können wir das in der Praxis nutzen? Wir Entwickler sind sehr faul. Wir wollen etwas nicht immer und immer wieder drucken. Von der Existenz mehrerer Kopien desselben Codes wird aus folgenden Gründen abgeraten:
  • Je weniger Codekopien vorhanden sind, desto einfacher ist die Wartung.
  • Wenn nicht viele Kopien des Codes vorhanden sind, wird eine Änderung an einer Stelle überall sichtbar.
  • Je weniger Code, desto weniger Fehler.
  • Wenn ein Code an vielen Stellen verwendet wird, wird eine Verallgemeinerung erreicht.
  • Wir konzentrieren uns auf das Schreiben von Code.
  • Wir konzentrieren uns auf Tests.
Die Vererbung in Java erfolgt über die Schlüsselwörter „extends“ und „implements“. class WritingInstrument { } class Pen extends WritingInstrument { }
Polymorphismus
Das Wort „Polymorphismus“ setzt sich aus zwei Wörtern zusammen: „Poly“ , d. h. „viele“ / „mehr als eins“ „morphen“ , d.h. „Form“ Wörtlich bezieht sich das Wort „Polymorphismus“ auf die Fähigkeit von Objekten, sich je nach Bedingungen unterschiedlich zu verhalten. In der Programmierung kann Polymorphismus an mehreren Stellen implementiert werden:
  • Klassen
  • Methoden
  • Betreiber
Alle oben genannten Elemente können sich je nach den Bedingungen, möglicherweise dem Kontext, in dem sie verwendet werden, unterschiedlich verhalten. Dies ist nützlich, da der Client (der Programmierer, der Ihre Bibliotheken verwendet) nicht viele Feinheiten kennen muss und die gewünschte Funktionalität durch Auswahl der erforderlichen Informationen aus dem Kontext implementiert wird. Class WritingObject { wrire() { // пишем, используя стандартные (по дефолту) цвета } } class Pencil extends WritingObject { write() { // пишем, используя серый цвет, написанный текст можно стереть } } class Pen extends WritingObject { write() { // пишем, используя голубой цвет, написанный текст нельзя стереть } } class Main { main() { WritingObject wr = new WritingObject(); wr.write(); // первый вызов WritingObject wr = new Pen(); wr.write(); // второй вызов WritingObject wr2 = new Pencil(); wr2.write(); // третий вызов } } Das obige Beispiel verfügt über eine Standardimplementierung in WritingObject, die durch die Nachkommenklassen pen und pen erweitert/überschrieben wird. Die Methode write() wird in der Main-Klasse dreimal aufgerufen. Jedes Mal wird eine andere Implementierung aufgerufen, je nachdem, für welches Objekt die Methode aufgerufen wird. In diesem Fall weist die Methode write() viele Verhaltensweisen auf, da sie polymorph ist.
Verkapselung
Unter Kapselung versteht man das Sammeln verwandter Daten/Funktionen in einer Einheit. Dies hilft bei der Erleichterung des Datenzugriffs/der Datenänderung. Wenn wir beispielsweise alle Eigenschaften eines bestimmten Benutzers drucken müssen, haben wir die folgenden Optionen: Wir haben printUserProperties(userName, userId, firstname, lastname, email, phone, … … ….) eine Methode erstellt, die alle Eigenschaften übernimmt und sie nacheinander ausgibt. Wenn die Anzahl der Elemente in der Liste zunimmt, ist es nicht mehr möglich, korrekte Felder zu identifizieren, und das Hinzufügen/Entfernen eines Felds ändert die Methodensignatur. Daher müssen wir alle Benutzer dieser Methode ersetzen, auch wenn sie die kürzlich hinzugefügten Felder nicht benötigen. Um den Code besser lesbar zu machen und zukünftige Änderungen zu erleichtern, kapseln wir Eigenschaften in einer Klasse und wandeln sie in ein kollektives Objekt um. class User { userName userId firstname lastname email phone .. .. .. } printUserProperties(user) {} Ein Objekt ist ein Softwarepaket aus Variablen und zugehörigen Methoden. Sie können Objekte der realen Welt mithilfe von Programmobjekten darstellen. Sie können sich echte Hunde in einem Animationsprogramm oder ein echtes Fahrrad als Softwareobjekt in einem Heimtrainer vorstellen. In OOP ist eine Klasse eine erweiterbare Vorlage (Programmcode-Vorlage) zum Erstellen von Objekten, zum Versehen mit einem Anfangszustand (Variablen) und zum Implementieren von Verhalten (Funktionen, Methoden). Das Akronym SOLID wurde von Michael Feather für die „ersten fünf Prinzipien“ geprägt, die Robert C. Martin Anfang der 2000er Jahre benannte. Das Ziel der Prinzipien besteht bei gemeinsamer Umsetzung darin, die Wahrscheinlichkeit zu erhöhen, dass der Programmierer ein System erstellt, das einfach zu warten und zu erweitern ist. Die SOLID-Prinzipien sind Richtlinien in der Programmentwicklung, die notwendig sind, um „faulen“ Code durch Refactoring zu entfernen, wodurch der Code leicht lesbar und erweiterbar werden soll. Dies ist Teil der agilen und adaptiven Programmierstrategie.
Prinzip der Einzelverantwortung
In OOP besagt das Einzelverantwortungsprinzip, dass jede Klasse für einen Teil der vom Programm bereitgestellten Funktionalität verantwortlich sein sollte und dass die Verantwortung vollständig von dieser Klasse gekapselt werden sollte. Seine gesamte Funktionalität sollte eng mit dieser Verantwortung verbunden sein.
Offen/Geschlossen-Prinzip
In OOP besagt das Offen/Geschlossen-Prinzip, dass „Softwareeinheiten (Klassen, Module, Methoden usw.) offen für Erweiterungen, aber geschlossen für Änderungen sein sollten.“ Mit anderen Worten: Die Entität muss zulassen, dass ihr Verhalten erweitert wird, ohne den Quellcode zu ändern.
Liskov-Substitutionsprinzip
Substituierbarkeit ist ein Prinzip in OOP. Es besagt, dass, wenn S in einem Computerprogramm ein Untertyp von T ist, Objekte vom Typ T so sein müssen, dass sie ohne Änderung durch Objekte vom Typ S ersetzt werden können (d. h. Objekte vom Typ S können durch Objekte vom Typ T ersetzt werden). alle erforderlichen Eigenschaftenprogramme (Genauigkeit, Aufgabenerledigung usw.).
Prinzip der Schnittstellentrennung
Das Prinzip der Schnittstellentrennung besagt, dass der Client-Programmierer nicht gezwungen werden sollte, sich auf Methoden zu verlassen, die er nicht verwendet. Nach diesem Prinzip ist es notwendig, große Schnittstellen in kleinere und spezifischere zu unterteilen, damit der Client-Programmierer nur die für ihn interessanten Methoden kennt. Der Zweck des Schnittstellenentkopplungsprinzips besteht darin, das System entkoppelt zu halten, was das Refactoring, das Vornehmen von Änderungen und die erneute Bereitstellung erleichtert.
Abhängigkeitsinversionsprinzip
In OOP bedeutet das Prinzip der Abhängigkeitsinversion eine bestimmte Form der Trennung zwischen Programmmodulen. Durch die Befolgung dieses Prinzips werden die Standardabhängigkeitsbeziehungen, die von High-Level-Modulen, die die Anwendungsarchitektur bilden (Richtlinieneinstellung), zu abhängigen Low-Level-Modulen eingerichtet werden, invertiert (umgekehrt), sodass modifizierte High-Level-Module unabhängig von den Implementierungsdetails von werden Low-Level-Module. Dieses Prinzip besagt:
  • High-Level-Module sollten nicht von Low-Level-Modulen abhängig sein. Beide Arten von Modulen müssen von Abstraktionen abhängen.
  • Abstraktionen sollten nicht von Implementierungsdetails abhängen. Details müssen von Abstraktionen abhängen.
Das Prinzip kehrt die Denkweise der Menschen über objektorientiertes Design um, indem es argumentiert, dass Objekte auf hoher und niedriger Ebene von denselben Abstraktionen abhängen sollten.

GRASP-Prinzipien

Die General Responsibility Assignment Software Patterns (GRASP) bieten Richtlinien für die Zuweisung von Verantwortlichkeiten zu Klassen und Objekten im objektorientierten Design.
Regler
Das Controller-Muster weist die Verantwortung für die Interaktion mit Systemereignissen Nicht-GUI-Klassen zu, die das gesamte System oder Anwendungsszenario darstellen. Regler:
  • Dabei handelt es sich um ein Objekt, das nicht direkt mit dem Benutzer interagiert und für den Empfang und die Reaktion auf Systemereignisse verantwortlich ist.
  • Muss verwendet werden, um alle Systemereignisse eines (oder mehrerer miteinander verbundener) Anwendungsfälle zu verarbeiten.
  • Es ist das erste Objekt hinter der GUI, das den Systembetrieb steuert.
  • Er muss die Arbeit nicht selbst erledigen; seine Aufgabe ist es, den Ablauf der Ereignisse zu steuern.
Schöpfer
Die Aufgabe der Erstellerklasse besteht darin, Objekte für die spätere Verwendung zu erstellen und zu initiieren. Es kennt die Initialisierungsparameter und weiß, welches Objekt erstellt wird. Manchmal erstellt die Erstellerklasse aktiv Objekte, legt sie im Cache ab und stellt bei Bedarf eine Instanz bereit.
Hoher Zusammenhalt
Hohe Kohäsion ist ein Bewertungsmuster, dessen Zweck darin besteht, Objekte in einem Zustand zu halten, in dem sie auf die Erfüllung einer klaren Aufgabe ausgerichtet sind und leicht kontrolliert und verstanden werden können. Eine hohe Kopplung wird normalerweise zur Unterstützung einer niedrigen Kopplung verwendet. Hohe Kohärenz bedeutet, dass die Verantwortlichkeiten eines bestimmten Elements klar definiert sind (stark verbunden und stark fokussiert). Die Aufteilung eines Programms in Klassen und Subsysteme ist ein Beispiel für Aktionen, die den Zusammenhalt von Systemeigenschaften erhöhen. Bei einer losen Kopplung hingegen handelt es sich um eine Situation, in der ein Element zu viele voneinander unabhängige Aufgaben hat. Lose gekoppelte Elemente sind in der Regel schwer zu verstehen, wiederverwendbar, schwer zu warten und schwer zu ändern.
Indirektion
Das Roundabout-Muster sorgt für eine lose Kopplung (und Wiederverwendbarkeit) zwischen zwei Elementen, indem die Verantwortung für die Interaktion zwischen ihnen einem Zwischenobjekt zugewiesen wird. Ein Beispiel ist die Einführung eines Controllers zur Vermittlung zwischen den Daten (Modell) und ihrer Anzeige (Ansicht) im Model-View-Controller (MVC)-Muster.
Informationsexperte
Informationsexperte (auch Experte oder Expertenprinzip) ist ein Grundsatz, der bestimmt, an wen Verantwortung delegiert werden soll. Zu den Verantwortlichkeiten gehören Methoden, berechnete Felder usw. Bei der Anwendung dieses Prinzips bei der Zuweisung von Verantwortung besteht der Hauptansatz in der folgenden Abfolge von Maßnahmen: Analyse der Verantwortung, Identifizierung der Informationen, die zu ihrer Erfüllung erforderlich sind, und schließlich Feststellung, wo sich diese Informationen befinden. Die Verwendung des Information-Expert-Prinzips führt dazu, dass die Verantwortung für die Ausführung der Klasse zugewiesen wird, die über die meisten Informationen verfügt.
Niedrige Kopplung
Bei der losen Kopplung handelt es sich um ein Bewertungsmuster, das angibt, wie Verantwortlichkeiten zugewiesen werden: lose Kopplung zwischen Klassen, die Änderung einer Klasse sollte nur minimale Auswirkungen auf die andere haben und die Wiederverwendbarkeit maximieren.
Polymorphismus
Gemäß dem Polymorphismus wird die typabhängige Verhaltensvariation den Typen zugeordnet, bei denen diese Variation auftritt. Dies wird durch die Verwendung polymorpher Operationen erreicht.
Geschützte Variationen
Das Muster „Geschützte Änderungen“ schützt Elemente vor Änderungen an anderen Elementen (Objekten, Systemen, Subsystemen), indem es den Schwerpunkt der Instabilität in eine Schnittstelle einschließt und Polymorphismus verwendet, um verschiedene Implementierungen dieser Schnittstelle zu erstellen.
Reine Herstellung
Bei der reinen Konstruktion handelt es sich um eine Klasse, die kein Konzept in der Problemdomäne darstellt und speziell darauf ausgelegt ist, eine lose Kopplung, eine hohe Kopplung und damit ein maximales Wiederverwendungspotenzial zu erreichen (die vom Information Expert-Muster angebotene Lösung erreicht dies nicht). Eine solche Klasse wird im domänengesteuerten Design üblicherweise „Service“ genannt.

Kritik

Untersuchungen von Potok et al. zeigten keine signifikanten Unterschiede zwischen OOP und verfahrenstechnischen Ansätzen.
Ein kritischer Vergleich von OOP mit anderen Technologien, insbesondere relationalen Technologien, ist schwierig, da es keine strenge und allgemein akzeptierte Definition von OOP gibt (Christopher J. Date).
Im Vergleich zu anderen Sprachen (LISP-Dialekte, funktionale Sprachen usw.) haben OOP-Sprachen keinen einzigartigen Vorteil und bringen unnötige Komplexität mit sich. (Lawrence Krubner)
Ich finde objektorientierte Programmierung technisch gesehen dürftig. Es versucht, die Welt anhand von Schnittstellen, die innerhalb eines einzigen Typs variieren, in Teile zu zerlegen. Um echte Probleme zu lösen, benötigt man multisortierte Algebren – Familien von Schnittstellen, die sich über viele Typen erstrecken. Ich finde objektorientierte Programmierung philosophisch ungesund. Es besagt, dass alles ein Objekt ist. Auch wenn dies wahr ist, ist es nicht sehr interessant: Zu sagen, dass alles ein Objekt ist, heißt überhaupt nichts zu sagen. (Alexander Stepanow)
Die Beliebtheit von OOP bei großen Unternehmen ist auf „große (und häufig wechselnde) Gruppen mittelmäßiger Programmierer“ zurückzuführen. Die durch OOP auferlegte Disziplin verhindert, dass der Programmierer „zu viel Schaden“ anrichtet. (Paul Graham)
Bei der objektorientierten Programmierung stehen Substantive an erster Stelle. Warum so extreme Maßnahmen ergreifen und einen Teil der Rede auf ein Podest stellen? Warum hat ein Konzept Vorrang vor einem anderen? Es ist für OOP unmöglich, Verben plötzlich weniger wichtig für unser Denken zu machen. Es ist eine seltsam verzerrte Perspektive. (Steve Yegge)
Rick Hickey, der Erfinder von Clojure, beschrieb Objektsysteme als extrem vereinfachte Modelle der realen Welt. Er betonte die Unfähigkeit von OOP, die Zeit korrekt zu modellieren, was zu großen Problemen führt, wenn Multithreading in Programmen üblich wird. Eric S. Raymond, ein Unix-Programmierer und Verfechter von Open-Source-Software, hat die Behauptung, OOP sei „die einzige Lösung“, kritisch gesehen und geschrieben, dass OOP mehrschichtige Programme fördert, was die Transparenz behindert. Als gegensätzlichen Ansatz führte Raymond das Beispiel von Unix und C an.

Links

Von Margaret Rouse @ WhatIs.com Wikipedia! ( Russische Version ) Vererbung ist Polymorphismus SOLID (Objektorientiertes Design) ( Russische Version ) EinzelverantwortungsprinzipArgumente gegen OOPS ( Russische Version ) Was ist OOPS (ohne den Hype) Übersetzung: Varygin D.V.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION