OOP vs Functional Programming vs Procedural [geschlossen]

237

Was sind die Unterschiede zwischen diesen Programmierparadigmen und sind sie besser für bestimmte Probleme geeignet oder bevorzugen Anwendungsfälle einen gegenüber den anderen?

Architekturbeispiele geschätzt!

Ashutosh Singh-MVP SharePoint
quelle
Dies ist keine vollständige Antwort, aber ich schreibe hier ein wenig darüber, wie "funktional" den "OO" -Stil (im Kontext von F #) beeinflusst / kontrastiert: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511. Eintrag
Brian
Sie könnten dies lesen ! Es gibt viele Beispiele, wann welche Ameise verwendet werden soll, was die Hauptunterschiede, Vor- / Nachteile usw. sind
Nikita Ignatov
1
Siehe auch: stackoverflow.com/questions/1530868
dreftymac
Onkel Bob hat darüber getwittert . Und auch hier .
jaco0646

Antworten:

129

Alle von ihnen sind auf ihre Weise gut - sie sind einfach unterschiedliche Ansätze für die gleichen Probleme.

In einem rein prozeduralen Stil sind Daten in der Regel stark von den Funktionen entkoppelt, die sie ausführen.

In einem objektorientierten Stil neigen Daten dazu, eine Sammlung von Funktionen mit sich zu führen.

In einem funktionalen Stil haben Daten und Funktionen tendenziell mehr Gemeinsamkeiten (wie in Lisp und Scheme) und bieten gleichzeitig mehr Flexibilität hinsichtlich der tatsächlichen Verwendung von Funktionen. Algorithmen werden eher als Rekursion und Komposition als als Schleifen und Iteration definiert.

Natürlich beeinflusst die Sprache selbst nur, welcher Stil bevorzugt wird. Selbst in einer rein funktionalen Sprache wie Haskell können Sie in einem prozeduralen Stil schreiben (obwohl davon dringend abgeraten wird), und selbst in einer prozeduralen Sprache wie C können Sie in einem objektorientierten Stil programmieren (wie in GTK + und EFL-APIs).

Der "Vorteil" jedes Paradigmas liegt einfach in der Modellierung Ihrer Algorithmen und Datenstrukturen. Wenn Ihr Algorithmus beispielsweise Listen und Bäume enthält, ist ein Funktionsalgorithmus möglicherweise am sinnvollsten. Wenn Ihre Daten beispielsweise stark strukturiert sind, ist es möglicherweise sinnvoller, sie als Objekte zusammenzustellen, wenn dies das native Paradigma Ihrer Sprache ist - oder sie können genauso einfach geschrieben werden wie eine funktionale Abstraktion von Monaden, die ist das native Paradigma von Sprachen wie Haskell oder ML.

Die Wahl, die Sie verwenden, ist einfach sinnvoller für Ihr Projekt und die Abstraktionen, die Ihre Sprache unterstützt.

grau verblassen
quelle
5
Was Sie gesagt haben, scheint nicht das zu reflektieren, was Sie geschrieben haben. Sie sagen, sie haben keine "Vor- und Nachteile" und sagen dann, wie unterschiedlich sie sind. Warum sollte jemand je nach Situation einen Ansatz einem anderen vorziehen? Stärken und Schwächen, Vor- und Nachteile, wie auch immer Sie sie nennen, sie existieren! Ich sage nicht, dass einer von Natur aus besser ist, und Sie auch nicht. Ich glaube, das haben Sie wirklich versucht zu sagen. es sei denn, Sie glauben wirklich, dass ein gewählter Ansatz im Vergleich zu einem anderen Ansatz keine positiven und negativen Aspekte aufweist.
JM Becker
1
@TechZilla: Ich stimme zu, dass mein Wortlaut schlecht war, aber ich meinte, dass es nicht wirklich eine Liste von Funktionen gibt, auf die Sie verweisen und sagen können, dass Sprache X besser als Y ist, ohne zu qualifizieren, dass Sprache X besser zum Schreiben von Algorithmus U und Sprache geeignet ist Y ist möglicherweise besser zum Schreiben des Algorithmus V geeignet, während beide problemlos in beiden Sprachen implementiert werden können.
Greyfade
2
Der Unterschied zwischen prozedural und funktional ist mir nicht klar. Ich lerne Scheme / Rackett am College, aber ich kann den großen Unterschied zwischen ihm und prozeduralem C oder PHP wirklich nicht erkennen. Können Sie ein Beispiel geben?
Leonel
7
@Leonel: Der größte Unterschied, den die meisten Leute anführen werden, besteht darin, dass Sie in prozeduralen Sprachen möglicherweise eine for-Schleife verwenden, aber in funktionalen Sprachen gibt es so etwas nicht. Stattdessen verwenden Sie rekursive Aufrufe von Funktionen, um dieselbe Aufgabe auszuführen. Funktionale Sprachen machen Funktionen auch zu erstklassigen Objekten - Sie können sie wie eine Zahl weitergeben -, aber das können Sie in C nicht (und die Unterstützung von PHP dafür ist fehlerhaft).
Greyfade
2
@tastro: Wenn ein Paradigma sinnvoller ist als das andere. Das ist wirklich alles. Manchmal ist es sinnvoller, Ihren Code als Zusammensetzung von Funktionen zu modellieren, und manchmal ist es sinnvoller, Ihre Daten als Objekte zu modellieren. Es gibt viele Möglichkeiten, Algorithmen und Datenstrukturen auszudrücken. OOP und funktional sind zwei dieser Dinge.
Greyfade
25

Ich denke, die verfügbaren Bibliotheken, Tools, Beispiele und Communitys übertreffen das Paradigma heutzutage völlig. Zum Beispiel könnte ML (oder was auch immer) die ultimative Allzweck-Programmiersprache sein, aber wenn Sie keine guten Bibliotheken für das bekommen, was Sie tun, sind Sie fertig.

Wenn Sie beispielsweise ein Videospiel erstellen, gibt es in C ++ mehr gute Codebeispiele und SDKs, sodass Sie damit wahrscheinlich besser dran sind. Für eine kleine Webanwendung gibt es einige großartige Python-, PHP- und Ruby-Frameworks, mit denen Sie sehr schnell loslegen können. Java ist aufgrund der Überprüfung der Kompilierungszeit und der Unternehmensbibliotheken und -plattformen eine gute Wahl für größere Projekte.

Früher war es so, dass die Standardbibliotheken für verschiedene Sprachen ziemlich klein und leicht zu replizieren waren - C, C ++, Assembler, ML, LISP usw. kamen mit den Grundlagen, neigten jedoch dazu, sich zu standardisieren, wenn es um die Standardisierung von Dingen ging Wie Netzwerkkommunikation, Verschlüsselung, Grafiken, Datendateiformate (einschließlich XML) wurden auch grundlegende Datenstrukturen wie ausgeglichene Bäume und Hashtabellen weggelassen!

Moderne Sprachen wie Python, PHP, Ruby und Java verfügen jetzt über eine weitaus anständigere Standardbibliothek und verfügen über viele gute Bibliotheken von Drittanbietern, die Sie problemlos verwenden können, was zum großen Teil auf die Verwendung von Namespaces zurückzuführen ist, um zu verhindern, dass Bibliotheken miteinander kollidieren. und Speicherbereinigung, um die Speicherverwaltungsschemata der Bibliotheken zu standardisieren.

Dobes
quelle
5
Python, Ruby, ... haben keine "Standard" -Bibliotheken wie C oder LISP, da es sich um einzelne Implementierungssprachen handelt. Python ist das, was Guido sagt, es gibt keinen Standard. Jede bestimmte C- oder LISP-Implementierung (oder was auch immer) enthält heutzutage eine große Anzahl von Bibliotheken, die über die Standardbibliotheken hinausgehen.
Dan Andreatta
8
Die Frage betraf die Unterschiede zwischen objektorientierter, funktionaler und prozeduraler Programmierung. Während sich die in diesen Antworten erwähnten Sprachen sicherlich für einen dieser Ansätze eignen, erwähnt die Antwort keines dieser Konzepte ... Unabhängig davon, ob "die verfügbaren Bibliotheken [...] das Paradigma [trumpfen]" oder nicht, das beantwortet die vorliegende Frage nicht und tritt damit zur Seite, was eine völlig gültige Frage ist.
Rinogo
1
ircmaxells verwandte Beschimpfungen
rinogo
20

Diese Paradigmen müssen sich nicht gegenseitig ausschließen. Wenn Sie sich Python ansehen, unterstützt es Funktionen und Klassen, aber gleichzeitig ist alles ein Objekt, einschließlich Funktionen. Sie können den funktionalen / oop / prozeduralen Stil in einem Code kombinieren.

Ich meine, in funktionalen Sprachen (zumindest in Haskell, der einzigen, die ich studiert habe) gibt es keine Aussagen! Funktionen sind nur ein Ausdruck in ihnen erlaubt !! ABER Funktionen sind erstklassige Bürger, Sie können sie zusammen mit einer Reihe anderer Fähigkeiten als Parameter weitergeben. Sie können mit wenigen Codezeilen mächtige Dinge tun.

In einer prozeduralen Sprache wie C können Sie Funktionen nur mithilfe von Funktionszeigern weitergeben, und dies allein ermöglicht nicht viele leistungsstarke Aufgaben.

In Python ist eine Funktion ein erstklassiger Bürger, kann jedoch eine beliebige Anzahl von Anweisungen enthalten. Sie können also eine Funktion haben, die prozeduralen Code enthält, aber Sie können ihn genau wie funktionale Sprachen weitergeben.

Gleiches gilt für OOP. In einer Sprache wie Java können Sie keine Prozeduren / Funktionen außerhalb einer Klasse schreiben. Die einzige Möglichkeit, eine Funktion weiterzugeben, besteht darin, sie in ein Objekt zu verpacken, das diese Funktion implementiert, und dieses Objekt dann weiterzugeben.

In Python gibt es diese Einschränkung nicht.

hasen j
quelle
Ich glaube, Sie meinten "diese Paradigmen müssen sich nicht gegenseitig ausschließen". Die drei sind orthogonal, da Sie im Idealfall eine, zwei oder die drei in einem einzigen Programm verwenden können (sofern Ihre Sprache dies zulässt).
Joe Pineda
Ja, ich denke, sich gegenseitig auszuschließen ist ein besserer Begriff dafür! danke
hasen
14

Für die GUI würde ich sagen, dass das objektorientierte Paradigma sehr gut geeignet ist. Das Fenster ist ein Objekt, die Textfelder sind Objekte und die Okay-Schaltfläche ist auch eines. Auf der anderen Seite können Dinge wie die String-Verarbeitung mit viel weniger Aufwand erledigt werden und sind daher mit einem einfachen prozeduralen Paradigma einfacher.

Ich denke auch nicht, dass es eine Frage der Sprache ist. Sie können in fast jeder gängigen Sprache funktional, prozedural oder objektorientiert schreiben, obwohl dies in einigen Sprachen ein zusätzlicher Aufwand sein kann.

panschk
quelle
17
Ich bin versucht, für die Aufrechterhaltung des Missverständnisses "Object = GUI Widget" zu stimmen, aber ich werde es unterlassen. OOP funktioniert genauso gut für die Darstellung abstrakter Konzepte wie "UserAccount" oder "PendingSale" wie für sichtbare Schnittstellenelemente wie "Window" und "Button".
Dave Sherohman
5
Ich habe geschrieben, dass ein Fenster ein Objekt sein kann. Wie ziehen Sie den Schluss, dass jedes Objekt ein Fenster von dort ist? Es war nur ein Beispiel. Natürlich kann OOP genauso gut verwendet werden, um abstrakte Entitäten und ihre Beziehung zu modellieren. Wie auch immer, danke, dass du nicht abgestimmt hast. Ich habe sowieso nicht viele Punkte: D
panschk
6
-1. OOP hat nichts mit GUIs zu tun. Idealerweise ist die beste Methode zum Entwerfen von Guis die Verwendung einer externen Textdatei (z. B. HTML). Während Dinge wie String-Verarbeitung eigentlich viel besser mit Objekten gemacht werden. (Denken Sie an Zeichenfolgen in C) !!
Hasen
1
Ich weiß nicht, vielleicht bin ich es einfach gewohnt, mit Objekten zu programmieren, um es zu realisieren. Aber wie würden Sie interaktive Dinge wie das Ändern des Werts in TextBox X tun, wenn der Wert von TextBox Y ohne Verwendung von Objekten geändert wurde? Okay, Sie könnten einfach globale Vars für alles verwenden ...
Panschk
1
Die Zeichenfolgenverarbeitung erfolgt hervorragend in Perl (100x besser als in Java, C ++ oder C #), die Zeichenfolgenfunktionalität der Sprache ist jedoch absolut NICHT objektorientiert. Cs String-Handling war schrecklich, aber dann ist C nicht die einzige prozedurale Sprache (noch die beste).
Joe Pineda
6

Um Ihre Frage zu beantworten, benötigen wir zwei Elemente:

  1. Verständnis der Eigenschaften verschiedener Architekturstile / -muster.
  2. Verständnis der Eigenschaften verschiedener Programmierparadigmen.

Eine Liste der Softwarearchitekturstile / -muster finden Sie im Artikel zur Softwarearchitektur auf Wikipeida. Und Sie können sie einfach im Internet recherchieren.

Kurz gesagt und allgemein ist Procedural gut für ein Modell, das einer Prozedur folgt, OOP ist gut für das Design und Functional ist gut für die Programmierung auf hoher Ebene.

Ich denke, Sie sollten versuchen, die Geschichte jedes Paradigmas zu lesen und herauszufinden, warum Menschen es schaffen, und Sie können sie leicht verstehen.

Nachdem Sie beide verstanden haben, können Sie die Elemente von Architekturstilen / -mustern mit Programmierparadigmen verknüpfen.

Gabriel Chung
quelle
2

Ich denke, dass sie oft nicht "gegen" sind, aber Sie können sie kombinieren. Ich denke auch, dass die Wörter, die Sie erwähnen, oft nur Schlagworte sind. Es gibt nur wenige Menschen, die tatsächlich wissen, was "objektorientiert" bedeutet, selbst wenn sie die schärfsten Evangelisten davon sind.

Svante
quelle
1

Einer meiner Freunde schreibt eine Grafik-App mit NVIDIA CUDA . Die Anwendung passt sehr gut zum OOP-Paradigma und das Problem kann ordentlich in Module zerlegt werden. Um CUDA verwenden zu können, müssen Sie jedoch C verwenden, das die Vererbung nicht unterstützt . Deshalb müssen Sie klug sein.

a) Sie entwickeln ein cleveres System, das bis zu einem gewissen Grad die Vererbung emuliert. Es kann getan werden!

i) Sie können ein Hook-System verwenden , das erwartet, dass jedes Kind C von Elternteil P eine bestimmte Überschreibung für Funktion F hat. Sie können Kinder dazu bringen, ihre Überschreibungen zu registrieren, die gespeichert und bei Bedarf aufgerufen werden.

ii) Sie können struct verwenden Speicherausrichtung Funktion Guss Kinder in Eltern.

Dies kann ordentlich sein, aber es ist nicht einfach, eine zukunftssichere, zuverlässige Lösung zu finden. Sie werden viel Zeit damit verbringen, das System zu entwerfen, und es gibt keine Garantie dafür, dass Sie in der Mitte des Projekts nicht auf Probleme stoßen. Die Implementierung der Mehrfachvererbung ist noch schwieriger, wenn nicht sogar fast unmöglich.

b) Sie können eine konsistente Namensrichtlinie verwenden und den Divide and Conquer- Ansatz verwenden, um ein Programm zu erstellen. Es wird keine Vererbung haben, aber da Ihre Funktionen klein, leicht verständlich und konsistent formatiert sind, benötigen Sie sie nicht. Die Menge an Code, die Sie schreiben müssen, steigt, es ist sehr schwierig, konzentriert zu bleiben und nicht einfachen Lösungen (Hacks) zu erliegen. Diese Ninja-Codierungsmethode ist jedoch die C-Codierungsmethode. Das Gleichgewicht zwischen Freiheit auf niedriger Ebene und dem Schreiben von gutem Code halten. Ein guter Weg, dies zu erreichen, besteht darin, Prototypen in einer funktionalen Sprache zu schreiben. Zum Beispiel eignet sich Haskell hervorragend für Prototyping-Algorithmen.

Ich tendiere zur Annäherung b. Ich habe eine mögliche Lösung mit Ansatz a geschrieben, und ich werde ehrlich sein, es fühlte sich mit diesem Code sehr unnatürlich an.

sneg
quelle
Die ersten C ++ - Copmpiler waren nichts anderes als Vorprozessoren, die C-Code generierten. Daher können ALLE Funktionen von c ++ - einschließlich der Mehrfachvererbung - mit C implementiert werden (das Emulieren der Behandlung von c ++ - Ausnahmen in C würde eine Art Plattformunterstützung für Ausnahmen erfordern, aber C ++ - Implementierungen erfordern dies auch, sodass ich nicht denke, dass dies die Basis ist Idee ungültig).
Chris Becke
2
@ Chris Becke deine Antwort ist zu philosophisch. Zum einen hat C mehrere Standards (im Laufe der Jahre), von denen kaum einer vollständig von C-Compilern übernommen wurde, geschweige denn von C ++. Zu sagen, dass C ++ eine Obermenge von C ist, weil es C-Syntax verwendet, bedeutet nicht viel, weil Sie nicht einmal Code für einen C-Compiler schreiben können, der ohne erheblichen Aufwand in einem anderen C-Compiler kompiliert wird. Darüber hinaus werden Sprachfunktionen (Typsysteme, OOD-Unterstützung) in anderen Sprachen angeboten, die in C nicht implementiert werden könnten, ohne C zum Entwerfen einer neuen Sprache zu verwenden (genau deshalb gibt es "neue Sprachen")
Sprague
Wissen Sie. Ich kann nicht mehr sehen, welche Relevanz mein Kommentar für diesen Beitrag überhaupt hat. : P
Chris Becke
Cuda unterstützt C ++ seit einiger Zeit.
Aryeh Leib Taurog