Das vielleicht größte Versprechen bei der Verwendung eines objektorientierten Paradigmas ist die Wiederverwendung von Code. Einige bestreiten, dass dies erreicht wurde. Warum wurde es (nicht) erreicht?
Wird Code nach OOP wiederverwendet, um die Produktivität von Projekten zu steigern?
Oder überschaubarer? Oder einfacher zu warten? Oder mit mehr Qualität?
Wahrscheinlich sind wir uns alle einig, dass die Wiederverwendung von Code eine gute Sache ist, aber es gibt mehrere Möglichkeiten, um dieses Ziel zu erreichen. Die Frage betrifft die von OOP angebotene Methode zur Wiederverwendung von Code. War es eine gute Sache? Gibt es bessere Methoden zur Wiederverwendung von Code als Objektorientierung, Unterklassifizierung, Polymorphismus usw.? Welche Wege sind besser? Warum ?
Teilen Sie uns Ihre Erfahrungen mit der Wiederverwendung von OOP oder anderen Paradigmen mit.
Antworten:
Die Wiederverwendung von Code ist eine ziemlich gute Idee. Kein großer .
Ich habe eine Perspektive aus ungefähr 30 Jahren Softwareentwicklung, die versucht, "wiederzuverwenden".
Ich begann in den 80er Jahren, die Wiederverwendung von Code als Forschungsthema zu untersuchen, nachdem ich herausgefunden hatte, dass ich das Design eines Betriebssystems, das ich in den frühen 70er Jahren gebaut hatte, für ein anderes Betriebssystem, das ich in den späten 70er Jahren gebaut hatte, wiederverwendet hatte.
Der gute Teil der Wiederverwendung von Code ist die Möglichkeit, manchmal ehrlichen Code wiederzuverwenden. Aber die Welt ist voller Code. Wie finden Sie, was Sie wollen? Folgendes nenne ich den Fluch der Wiederverwendung :
Ich bin der Weihnachtsmann (ok Open Source) und habe eine Tüte mit 1 Milliarde Softwarekomponenten. Sie können einen von ihnen haben.
Viel Glück bei der Auswahl.
Um das Wiederverwendungsproblem gut zu lösen:
Im Laufe der Jahre wurde vor allem festgestellt, dass Code für die Wiederverwendung zu diesem Zweck entwickelt werden muss oder zu viele implizite Annahmen enthält. Die erfolgreichsten Bibliotheken zur Wiederverwendung von Code waren tatsächlich recht klein. Bibliotheken und Frameworks sind vermutlich "wiederverwendbarer" Code und äußerst erfolgreich. Java und C # sind nicht deshalb erfolgreich, weil sie ziemlich gute Computersprachen sind, sondern weil sie über riesige, gut gestaltete, implementierte und dokumentierte Bibliotheken verfügen. Aber die Leute schauen sich den Quellcode in den Bibliotheken nicht an. Sie rufen einfach eine gut dokumentierte API auf (die allgemein verwendbar ist).
Was die Wiederverwendung von Code nicht getan hat (weder OOP noch OOP), ist die Verbesserung unserer Fähigkeit, Systeme zu codieren.
Ich denke, der Hauptfehler ist, dass jede Art der Wiederverwendung von Code grundsätzlich eingeschränkt ist, da in Code zu viele Annahmen eingebaut sind . Wenn Sie den Code winzig machen, minimieren Sie die Annahmen, aber die Kosten für das Erstellen von Grund auf sind nicht sehr hoch und die Wiederverwendungsgewinne sind nicht effektiv. Wenn Sie die Codestücke groß machen, sind sie in einem neuen Kontext so gut wie unbrauchbar. Wie Gulliver sind sie mit einer Million winziger Schnüre an den Strand gebunden, und Sie können es sich einfach nicht leisten, sie alle zu schneiden.
Woran wir arbeiten sollten, ist die Wiederverwendung von Wissen, um Code zu konstruieren . Wenn wir dies tun können, können wir dieses Wissen anwenden, um den Code zu konstruieren, den wir benötigen, und dabei die aktuellen Annahmen berücksichtigen.
Dazu benötigt man immer noch die gleiche Spezifikationsfähigkeit, um Softwarekomponenten zu charakterisieren (man muss immer noch sagen, was man will!). Aber dann wenden Sie dieses Konstruktionswissen auf die Spezifikationen an, um den gewünschten Code zu generieren .
Als Community sind wir noch nicht sehr gut darin. Aber die Leute machen es die ganze Zeit; warum können wir es nicht automatisieren? Es gibt viel Forschung, und dies zeigt, dass dies unter vielen Umständen möglich ist.
Ein Schlüsselelement hierfür sind mechanische Werkzeuge zur Aufnahme von "Komponentenbeschreibungen" (dies sind nur formale Dokumente, die wie Programmiersprachen analysiert werden können) und zur Anwendung von Programmtransformationen auf diese.
Compiler machen das bereits: -} Und sie sind wirklich gut in der Klasse von Problemen, die sie angehen.
UML-Modelle mit Codegenerierung sind ein Versuch, dies zu tun. Kein sehr guter Versuch; In den meisten UML-Modellen heißt es so ziemlich "Ich habe Daten, die so aussehen". Ziemlich schwer, ein echtes Programm zu generieren, wenn die Funktionalität weggelassen wird.
Ich versuche, praktische Programmtransformationssysteme zu erstellen, ein Tool namens DMS . Wir waren ziemlich abgelenkt, als wir Programmtransformationen nicht so sehr auf abstrakte Spezifikationen angewendet haben, um Code zu generieren, sondern auf Legacy-Code, um ihn zu bereinigen. (Dies sind die gleichen Probleme in der Zusammenfassung!). (Solche Werkzeuge zu bauen kostet viel Zeit; ich mache das seit 15 Jahren und in der Zwischenzeit muss man essen).
DMS verfügt jedoch über die beiden oben beschriebenen Schlüsseleigenschaften: Die Fähigkeit, beliebige formale Spezifikationen zu verarbeiten und das Wissen über die Codegenerierung als Transformation zu erfassen und bei Bedarf anzuwenden. Und bemerkenswerterweise generieren wir in einigen speziellen Fällen einen interessanten Code aus Spezifikationen. DMS wird größtenteils aus sich selbst erstellt, um seine Implementierung zu generieren. Das hat für uns zumindest das Versprechen der (Wissens-) Wiederverwendung erfüllt: äußerst signifikante Produktivitätssteigerungen. Ich habe ein Team von ungefähr 7 technischen Leuten; Wir haben wahrscheinlich 1-2 MSLOC "Spezifikationen" für DMS geschrieben, haben aber 10MSLOC generierten Code.
Zusammenfassung: Die Wiederverwendung von Generationswissen ist der Gewinn, nicht die Wiederverwendung von Code .
quelle
Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions.
Ich bin zu einem ähnlichen Schluss gekommen, konnte es aber nicht so prägnant ausdrücken.Die Wiederverwendung von Code erfolgt in OOP, aber auch in der funktionalen Programmierung. Jedes Mal, wenn Sie einen Codeblock nehmen und ihn für den Rest Ihres Codes aufrufbar machen, sodass Sie diese Funktionalität an anderer Stelle verwenden können, wird der Code wiederverwendet.
Diese Art der Wiederverwendung von Code macht den Code auch einfacher zu verwalten, da durch das Ändern dieses einen aufrufbaren Blocks alle Stellen geändert werden, an denen er aufgerufen wird. Ich würde sagen, dass dieses Ergebnis auch die Qualität und Lesbarkeit erhöht.
Ich bin nicht sicher, ob OOP einfach da ist, um die Wiederverwendung von Code zu ermöglichen. Ich betrachte OOP eher als eine Möglichkeit, mit Objekten zu interagieren und die Details der Datenstruktur zu abstrahieren.
Aus Wikpedia:
quelle
double sqrt (double x)
? Reine Funktionen sind der Archetyp der Wiederverwendbarkeit.double sqrt(double x)
,float sqrt(float x)
,int sqrt(int x)
können Sie eine Menge von ihnen, während sie mit einer generischen Programmiersprache definieren Sie müßtenNumber sqrt(Number x)
und mit ihr geschehen.Ja und nein
Die Wiederverwendung von Code ist ein Sammelbegriff für viele verschiedene Aktivitäten.
quelle
Ich würde eine lange Antwort posten, aber warum? Udi Dahan erklärt es viel besser als ich.
http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/
Hier ist der Beginn des Beitrags:
quelle
Ich stimme Chris zu, funktionale Programmierung ist eine gute Möglichkeit, Code wiederzuverwenden.
Viele Programme haben immer wiederkehrende Codestrukturen. Zu diesem Zweck werden in der OOP-Welt einige Entwurfsmuster verwendet. Dies kann jedoch durch rekursive Funktionen und Mustervergleiche in funktionalen Programmiersprachen erreicht werden. Weitere Informationen hierzu finden Sie im ersten Kapitel der funktionalen Programmierung in der realen Welt .
Ich denke, dass eine tiefe Vererbung von OOP in vielen Fällen irreführend sein kann. Sie haben eine Klasse und viele der eng verwandten Methoden sind in verschiedenen Dateien implementiert. Wie Joe Armstrong über OOP sagte:
Hohe Auftrag Funktionen sind auch sehr nützlich , wenn es darum geht , die Wiederverwendung zB codieren ,
map
undfoldr
das ist die Grundlage für Googles MapReduce .Die asynchrone Nachrichtenübermittlung ist auch ein guter Weg, um komplexe Software zu organisieren, und einige Computerwissenschaftler geben an, dass angenommen wurde, dass Objekte asynchron miteinander kommunizieren, wie im Tell, fragen Sie nicht nach dem OOP-Prinzip. Weitere Informationen hierzu finden Sie in Objektorientierte Programmierung: Der falsche Weg? wo Joe Armstrong zitiert wird:
Asynchrone Nachrichtenübermittlung wie in ereignisgesteuerten Systemen und in Erlang ist auch eine sehr gute Möglichkeit, Systeme zu entkoppeln, und lose Kopplung ist in komplexen Systemen wichtig. Mit einem ausreichend entkoppelten System können Sie das System weiterentwickeln, während es ausgeführt wird, möglicherweise auf verschiedenen Knoten. Unibet hielt hierzu eine großartige Präsentation: Domain Event Driven Architecture
Ich denke jedoch, dass der Großteil der Wiederverwendung von Code mithilfe von Bibliotheken und Frameworks erfolgt.
quelle
Die bescheidene Unix-Pipe hat mehr für die Wiederverwendung von Code getan als alles andere, was gekommen und gegangen ist. Objekte waren zufällig eine intuitive Art, Code zu strukturieren, als sie kamen, und später begannen die Leute, alles und jedes darauf anzuheften. Im Allgemeinen dienen Objekte zur Kapselung und nicht zur Wiederverwendung von Code. Die Wiederverwendung von Code erfordert etwas mehr und die Klassenvererbungshierarchie ist ein schlechter Ersatz für das, was ein Mechanismus zur Wiederverwendung von Code eigentlich sein sollte.
quelle
OOP ist nichts Besonderes; Sie können wiederverwendbaren Code mit oder ohne OOP erstellen. Reine Funktionen sind besonders wiederverwendbar : Nimmt zum Beispiel
java.lang.math.sqrt(double)
eine Zahl ein und gibt eine Zahl aus. Kein OOP, aber definitiv wiederverwendbarer als die meisten anderen Codes.quelle
Aus Sicht der funktionalen Programmierung geht es bei OOP hauptsächlich um die Verwaltung des Zustands.
In der funktionalen Programmierung stehen Ihnen Hunderte nützlicher Funktionen für Listen zur Verfügung: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html .
Hätten Sie Hunderte von Methoden in einer List-Klasse? Öffentliche Methoden werden als Schnittstelle zum internen Zustand betrachtet, den Sie klein halten möchten.
Leider duplizieren manche Leute die Funktionalität, anstatt viele kleine Funktionen (erneut) zu verwenden. Für mich liegt das daran, dass OOP die Wiederverwendung von Code nicht so sehr fördert wie die funktionale Programmierung.
quelle
Für mich ja, aber nicht die ganze Zeit, und es hätte auch anders gemacht werden können.
Meistens durch Erstellen einer abstrakten Basisklasse und Erstellen konkreter Implementierungen dieser Klasse.
Viele Frameworks verwenden Vererbung, um die Wiederverwendung von Code zu ermöglichen (Delphi, Java, .Net sind nur einige, die einem sofort in den Sinn kommen).
Das heißt nicht, dass viele Dienstprogrammbibliotheken und Code-Schnipsel diese Aufgabe nicht erledigt hätten, aber eine gut gestaltete Objekthierarchie hat etwas Angenehmes.
quelle
Meiner Erfahrung nach war es erfolgreicher, "wiederverwendbaren" Code durch generische Programmierfunktionen (wie C ++ - Vorlagen) zu nutzen, als OOP-Prinzipien wie Vererbungshierarchien zu verwenden.
quelle
OOP ist zu offen für eine effektive Wiederverwendung.
Es gibt zu viele Möglichkeiten zur Wiederverwendung. Jede öffentliche Klasse fragt: "Mach eine neue Instanz von mir!" Jede öffentliche Methode sagt: "Ruf mich an!" ergibt jede geschützte Methode: "Überschreibe mich!" - und alle diese Arten der Wiederverwendung sind unterschiedlich , sie haben unterschiedliche Parameter, sie erscheinen in unterschiedlichem Kontext, alle haben unterschiedliche Regeln, wie sie aufgerufen / erweitert / überschrieben werden.
API ist besser, es ist eine strenge Untermenge von OOP-Punkten (oder Nicht-OOP-Punkten), aber im wirklichen Leben sind APIs überfordert und wachsen ständig, es gibt immer noch zu viele Verbindungspunkte. Außerdem kann eine gute API das Leben erleichtern. Dies ist der beste Weg, eine Schnittstelle für OOP bereitzustellen.
Das Datadlow-Paradigma bietet eine strenge Schnittstelle für Komponenten. Sie haben Ports der folgenden Typen:
Abhängig von der Domäne gibt es einige Pakettypen, sodass Verbraucher und Hersteller verbunden werden können, wenn sie dieselben (oder kompatiblen) Ports haben. Das Schönste daran ist, dass es visuell möglich ist, da es keine Parameter oder andere Änderungen an den Verbindungen gibt, sondern nur einen Verbraucher und einen Produzenten miteinander verbindet.
Ich war ein bisschen unklar, vielleicht sehen Sie sich das "dataflow" -Tag auf StackOverflow oder Wikipedia "datafow programming" oder Wikipedia "flow-based programming" an .
(Außerdem habe ich ein Datenflusssystem in C ++ geschrieben. OOP und DF sind also keine Feinde, DF ist eine übergeordnete Organisationsmethode.)
quelle
In CommonLisp gibt es viele Möglichkeiten, die Wiederverwendung zu erreichen:
Dynamische Eingabe, wobei Ihr Code standardmäßig generisch ist
imperative Abstraktionen, dh Unterprogramme
Objektorientierung mit Mehrfachvererbung und Mehrfachversand
Syntax-Abstraktion, die Fähigkeit, neue syntaktische Konstrukte zu definieren oder Kessel-Platten-Code abzukürzen
funktionale Abstraktionen, Abschlüsse und Funktionen höherer Ordnung
Wenn Sie versuchen , die CommonLisp Erfahrung in anderen Sprachen zu vergleichen , werden Sie sehen , dass die Hauptfunktion , die die Wiederverwendung von Code erleichtert ist das Vorhandensein von sowohl objektorientierten und funktionalen Abstraktionen. Sie sind komplementärer als alternativ: Ohne eine von ihnen müssen Sie die fehlenden Funktionen ungeschickt neu implementieren. Siehe zum Beispiel Funktionsklassen, die als Closures und Pattern Matching verwendet werden, um einen nicht erweiterbaren Methodenversand zu erhalten.
quelle
- Kevlin Henney
quelle
Ich werde Spott riskieren und gestehen, ich habe OOP erst vor kurzem benutzt. Es kommt nicht automatisch zu mir. Der Großteil meiner Erfahrung bezieht sich auf relationale Datenbanken, daher denke ich in Tabellen und Joins. Es gibt Behauptungen, dass es besser ist, es von Anfang an zu lernen, damit Sie beim Programmieren nicht umdenken müssen. Ich habe diesen Luxus nicht und lehne es ab, meine Karriere wegen irgendeiner Elfenbeinturmtheorie aufzugeben. Wie alles andere werde ich es herausfinden.
Zuerst dachte ich, dass das ganze Konzept keinen Sinn ergibt. Es schien nur unnötig und zu viel Mühe. Ich weiß, das ist verrücktes Gerede. Offensichtlich ist ein gewisses Maß an Verständnis erforderlich, bevor Sie die Vorteile von etwas einschätzen oder es für bessere Methoden ablehnen können.
Die Wiederverwendung von Code erfordert die Bereitschaft, Code nicht zu wiederholen, ein Verständnis dafür, wie dies erreicht werden kann und eine Vorausplanung. Sollten Sie die Wiederverwendung von Code vermeiden, wenn Sie sich für einen Fall entschieden haben, in dem es sich einfach nicht lohnt? Und keine Sprache ist so streng OO, dass sie einen Fehler auslöst, wenn sie denkt, dass Sie Code von einer anderen Klasse geerbt haben sollten. Bestenfalls bieten sie eine Umgebung, die der Implementierung förderlich ist.
Ich denke, der größte Vorteil von OOP ist die allgemeine Akzeptanz, wie Code organisiert werden sollte. Alles andere ist Soße. Ein Team von Programmierern ist sich vielleicht nicht ganz einig, wie alle Klassen strukturiert sein sollen, aber sie sollten in der Lage sein, den Code zu finden.
Ich habe genug Prozedurcode gesehen, um zu wissen, dass er überall sein kann, und manchmal ist er überall.
quelle
OOP bietet Ihnen mehr Möglichkeiten, Code wiederzuverwenden. Das ist alles.
quelle
Horizontale Wiederverwendung: Aspekte, Merkmale, Transplantate
In Classic OO wird die Wiederverwendung von Code manchmal nicht ausreichend unterstützt, insbesondere dann, wenn die Vererbung aus Mangel an einer besseren Möglichkeit, die tatsächliche Funktionalität zwischen Klassen zu teilen, völlig verrückt wird. Für dieses Problem wurden horizontale Wiederverwendungsmechanismen wie AOP, Merkmale und Transplantate geschaffen.
Aspektorientierte Programmierung
Ich betrachte AOP als das fehlende halbe Orange von OOP. AOP ist nicht wirklich so bekannt, hat es aber zum Seriencode geschafft.
Ich werde es versuchen, um es in einfachen Worten zu erklären: Stellen Sie sich vor, Sie können Funktionen mit einer speziellen Struktur, die als Aspekt bezeichnet wird, einspeisen und filtern. Diese Aspekte haben "Methoden", die definieren, was und wie durch Reflektion beeinflusst wird , aber beim Kompilieren Diesen Vorgang nennt man Weben .
Ein Beispiel wäre ein Aspekt, der besagt, dass für alle Methoden bestimmter Klassen, die mit get beginnen, das Programm die erhaltenen Daten und den Zeitpunkt des Abrufs in eine Protokolldatei schreibt.
Sehen Sie sich diese beiden Vorträge an, wenn Sie AOP besser verstehen möchten:
Traits & Grafts
Merkmale sind ein weiteres Konstrukt zur Definition von wiederverwendbarem Code, das OOP ergänzt. Sie ähneln Mixins , sind aber sauberer.
Anstatt sie zu erklären, gibt es einen großartigen PHP-RFC, der beide erklärt . Traits kommen übrigens zu PHP, sie sind bereits auf Trunk festgelegt.
in Summe
OOP ist meiner Meinung nach immer noch der Schlüssel zur Modularität, und wie wir es heute allgemein kennen, ist OOP immer noch unvollständig .
quelle
OOP Bietet eine Reihe nützlicher Tools, mit denen Sie Code schreiben können, der an mehr Stellen verwendet werden kann, als Sie ohne diese Tools hätten. Wenn Sie eine
PrintIt
Funktion schreiben , die ein altes Objekt übernimmt und aufruft.toString()
, haben Sie diesen Code wieder verwendet, sobald Sie ihn mit mehr als einem Objekttyp aufrufen. Mit diesen Tools leistet jede Codezeile mehr.Die funktionale Programmierung ist im Moment unter den Hipstern sehr heiß. Es bietet Ihnen eine ganze Reihe von Werkzeugen, mit denen jede Codezeile mehr leisten kann. Es ist wahrscheinlich nicht besser oder funktioniert, bietet aber ein weiteres Tool in der Toolbox.
(Es gab eine verrückte Idee für eine ganze zusätzliche Ebene der objektorientierten Wiederverwendung: Die Idee war, dass wir eine einzelne
Customer
Klasse definieren und sie in jeder von uns geschriebenen Anwendung verwenden könnten . Dann wären Anwendungen hier und da nur ein kleiner Klebstoff. Dies hat nicht funktioniert, aber das bedeutet nicht, dass der OO fehlgeschlagen ist oder sogar, dass die Wiederverwendung fehlgeschlagen ist.quelle
Lesen Sie die obigen Beiträge, ein paar Anmerkungen:
quelle
Das Problem ist imho subtiler:
Also ist OOP an sich nicht schlecht, wenn es darum geht, wiederverwendbaren Code zu erstellen , aber die Arten von Code, die mit OOP geschrieben werden, sind von Natur aus schwer wiederzuverwenden .
Die funktionale Programmierung kann auch zu mehr wiederverwendbarem Code führen . Es ist jedoch möglicherweise nicht machbar, die Abstraktionen so zu gestalten, dass sie bei Einhaltung einer Frist einen vernünftigen Funktionscode schreiben. Und "halb-rechts" -Abstraktionen werden den OOP-Stil leichter ausdrücken. Und es wird nicht dazu führen, dass Code einfacher wiederverwendet werden kann - ein höherer Grad an Abstraktionen bedeutet, dass das Codeverständnis eine höhere Anfangsinvestition der begrenzten kognitiven Kapazität der Programmierer erfordert.
Als praktisches Beispiel: Spielcode beinhaltet viele veränderbare Zustände, da dies die natürliche Art ist, ein Spiel zu codieren, es sei denn, es ist ein sehr rätselhaftes / algorithmisches, so dass es offensichtlich mit OO strukturiert wird. Und natürlich ist es schwer wiederzuverwenden. Aber derselbe Code, der das gleiche Wissen enthält, wäre ohne OOP noch schwieriger wiederzuverwenden . Und das Umschreiben in einen funktionalen Stil erfordert möglicherweise eine grundlegende Änderung der Art und Weise, wie Sie über diesen Code denken, sowie des Wissens, das dahinter steckt. Ja, das resultierende Wissen hinter dem Code wäre nach dem Umschreiben von OO zu FP vielleicht viel klarer ... aber die Kosten könnten riesig sein und es könnte seinDie Art von Kosten, die auch von Leuten bezahlt werden müssten, die den unglaublich intelligenten und gut abstrahierten Code wiederverwenden möchten, mit dem Sie enden. Paradoxerweise würden die Leute den Code nicht wiederverwenden, selbst wenn er technisch wiederverwendbarer ist.
... was zur letzten Subtilität führt: Bei der Wiederverwendung von Code geht es um die People | Code- Oberfläche, nicht nur um den Code. OOP leistet gute Dienste für diese Schnittstelle, da es gut zu erkennen ist, wie viele Leute über viele Arten von Code nachdenken, der heutzutage geschrieben wird. FP ist vielleicht besser für die Wiederverwendung von Code, aber imho nicht für die einfache Wiederverwendung der Art von Code, die die Leute heutzutage tatsächlich schreiben müssen. Dies ändert sich mit der Art des Codes, den wir zum Schreiben von Änderungen benötigen.
PS Und wenn jemand sagen will, dass es sich bei OO nicht um einen veränderlichen Zustand handelt, kann es sich auch um OO mit unveränderlichem Zustand handeln. Ich nenne das "FP mit Klassen als Namespaces". Es ist großartig, wenn es für Sie funktioniert, und es vermeidet einige Mängel der Modulsysteme einiger Sprachen und kann zu mehr wiederverwendbarem Code führen. Aber das ist nicht OO;)
quelle