Ist MVC nicht gegen OOP?


62

Die Hauptidee hinter OOP ist die Vereinheitlichung von Daten und Verhalten in einer einzigen Entität - dem Objekt. Bei der prozeduralen Programmierung gibt es Daten und separate Algorithmen, die die Daten modifizieren.

In dem Model-View-Controller-Muster sind die Daten und die Logik / Algorithmen in unterschiedlichen Einheiten, dem Modell bzw. dem Controller, angeordnet. Sollte in einem äquivalenten OOP-Ansatz das Modell und der Controller nicht in derselben logischen Entität platziert werden?


11
Warum müssten sie sich in derselben logischen Einheit befinden? Sie haben nicht angegeben, warum dies vorteilhaft wäre oder warum OOP diese Anordnung diktieren würde.
Robert Harvey

26
Nun, die Geschäftslogik geht in das Modell, nicht in den Controller. Der Controller ist wirklich nur ein Vermittler, um die Ansicht und das Modell miteinander zu verbinden. Im Modell befinden sich also Daten und Verhalten am selben Ort.
Robert Harvey

2
Was? Das Zusammenführen von Daten und Verhalten ist genau das, worum es bei OOP geht.
Andy

3
Bei OOP geht es darum, Implementierungen von Schnittstellen zu trennen. Schnittstellen haben mehr mit Verhalten zu tun und Implementierungen mehr mit Daten (weshalb Daten häufig ausgeblendet werden). Bei OOP geht es also nicht darum, Daten und Verhalten zu vereinheitlichen, sondern sie zu trennen.
Kaz

5
Auf jeden Fall möchten Sie nicht alle Daten und Verhaltensweisen in eine Klasse packen. OOP-Programme verwenden mehr als eine Klasse, um Frameworks von Objekten zu erstellen. Und überhaupt, wenn etwas "Anti-OOP" ist, könnte das eine gute Sache sein. OOP ist nicht das A und O. OOP geradezu zum Kotzen. Es ist Zeit, über OOP hinwegzukommen.
Kaz

Antworten:


45

MVC ist eine Übung in Separation of Concerns , einer UI-Architektur. Dies ist eine Möglichkeit, die Komplexität zu korrigieren, die in Benutzeroberflächen auftreten kann, wenn die Präsentation nicht vom Inhalt getrennt wird .

Theoretisch können alle Objekte ein Verhalten aufweisen, das auf den Daten beruht, die sie enthalten, und dass Daten und Verhalten eingekapselt bleiben . In der Praxis kann ein bestimmtes OOP-Objekt eine Logik aufweisen, die seinen Daten entspricht, oder es kann überhaupt keine Logik aufweisen (beispielsweise ein Datenübertragungsobjekt ).

In MVC geht die Geschäftslogik in das Modell und nicht in den Controller. Der Controller ist wirklich nur ein Vermittler, um die Ansicht und das Modell miteinander zu verbinden. Im Modell können Sie also Daten und Verhalten an derselben Stelle haben.

Aber selbst diese Anordnung garantiert keine strikte Daten- / Verhaltensfusion. Objekte, die nur Daten enthalten, können von anderen Klassen bearbeitet werden, die nur Logik enthalten. Dies ist eine durchaus akzeptable Verwendung von OOP.


Ich gebe Ihnen ein konkretes Beispiel. Dies ist ein bisschen erfunden, aber nehmen wir an, Sie haben ein CurrencyObjekt, und dieses Objekt kann sich in jeder verfügbaren Währung darstellen, die an den Dollar gebunden ist. Sie hätten also Methoden wie:

public decimal Yen { get { return // dollars to yen; } }
public decimal Sterling { get { return // dollars to sterling; } }
public decimal Euro { get { return // dollars to euro; } }

... und dieses Verhalten würde mit dem Currency-Objekt gekapselt.

Aber was ist, wenn ich die Währung von einem Konto auf ein anderes übertragen oder eine Währung einzahlen möchte? Würde dieses Verhalten auch im Currency-Objekt enthalten sein? Nein, würde es nicht. Das Geld in Ihrer Brieftasche kann nicht von Ihrer Brieftasche auf Ihr Bankkonto überwiesen werden. Sie benötigen einen oder mehrere Agenten (einen Kassierer oder Geldautomaten), um dieses Geld auf Ihr Konto zu bekommen.

Dieses Verhalten würde also in ein TellerObjekt eingekapselt Currencyund AccountObjekte als Eingaben akzeptieren , es würde jedoch keine Daten selbst enthalten, außer möglicherweise ein wenig lokalen Status (oder möglicherweise ein TransactionObjekt), um die Verarbeitung der Eingabeobjekte zu unterstützen.


Und in welcher Entität / in welchem ​​Paket soll das Tellerplatziert werden? In dem, Controllervon wo aus die Teller'sMethoden aufgerufen werden oder in dem, Modelweil es Teil der Geschäftslogik ist?
m3th0dman

Tellergeht in die Model, obwohl es vom controller aufgerufen werden könnte. Es ist Teil der Geschäftsdomäne.
Robert Harvey

Ich habe immer gedacht, dass die Verwendung des Modells für Geschäftsregeln MVC zu einem semi-effektiven Muster macht. Die Verwendung des Modells für Adapter für die reale Anwendung und die Vermittlung der Controller zwischen den Adaptern und der Ansicht ist immer sehr viel effektiver, um SoC zu erzielen.
Yam Marcovic

@ YamMarcovic: Ich bin nicht sicher, was du meinst. Das Model ist eine Art Allrounder. In der Praxis werden Geschäftsregeln normalerweise in einer eigenen Serviceschicht platziert, sie werden jedoch weiterhin als Teil des Modells betrachtet (Sie würden beispielsweise keine bestimmten Geschäftsregeln in einer einzelnen Controllermethode codieren). Sie haben Recht, dass die Controller ein Vermittler sind.
Robert Harvey

5
Eine Sache, von der ich denke, dass die meisten Leute sich beim Lesen von MVC irren, sind zu breite Annahmen darüber, was "Geschäftslogik" bedeutet. Wenn Sie Ihr Modell in einer brandneuen App, die die gleichen Geschäftsziele, aber eine ganz andere Architektur über einen Controller mit völlig anderer Anwendungslogik hat, nicht mit minimaler bis gar keiner Änderung verwenden können, machen Sie es falsch IMO. Es ist natürlich immer noch sinnvoll, die Ansichten von allem anderen zu entkoppeln, aber C als leichtes Konstrukt scheint mir einen wichtigen Trennungspunkt zu verfehlen.
Erik Reppen

73

MVC arbeitet auf einer viel höheren Abstraktionsebene als einzelne Objekte. Tatsächlich besteht jedes der drei Objekte (Modell, Ansicht und Controller) in der Regel aus vielen Objekten, die sowohl Daten als auch Verhalten aufweisen.

Dass Objekte, die Daten und Verhalten einschließen, ein guter grundlegender Baustein für Programme im Allgemeinen sind, bedeutet nicht, dass es das beste Muster auf allen Abstraktionsebenen und für alle Zwecke ist.


Der objektorientierte Ansatz kann in der Abstraktionsebene skaliert werden. Siehe zum Beispiel den Grund für Domain Driven Design, der auftrat, weil die klassische Schichtenarchitektur nicht OOPisch, sondern prozedural ist. Dies geschieht auf einer höheren Abstraktionsebene als MVC.
m3th0dman

6
@ m3th0dman: Du sprichst in weiten, allgemeinen Worten. Wie wäre es mit einer Diskussion über Einzelheiten, wie MVC den Spaghetti-Code-Albtraum von Winforms oder Webforms beseitigt?
Robert Harvey

3
@ m3th0dman: das ist eine ziemlich vereinfachte Beschreibung von DDD.
Michael Borgwardt

1
@RobertHarvey Um sicher zu gehen, dass Sie den Kontrapunkt dafür darstellen, warum MVC gut ist, weil es die Spaghetti beseitigt, wird hier nicht wirklich gestritten. Ich bin damit einverstanden, aber ich sehe MVC tendenziell auch im prozeduralen Muster. Ich denke, es ist eine relevante Frage, die gestellt werden muss, oder besser gesagt, die Frage, die gestellt werden muss: "Wie oft implementieren die Leute MVC prozedural?"
Jimmy Hoffa

1
@ Robert Harvey Der Zweck der Frage ist nicht, wie gut oder schlecht MVC ist; es geht um die Tatsache, dass auf OO-Prinzipien basiert oder nicht.
m3th0dman

71

OOP schränkt die Interaktionen zwischen Objekten, die jeweils eigene Daten und ein eigenes Verhalten aufweisen, nicht ein.

Denken Sie an eine Ameisen- und eine Ameisenkolonie-Analogie: Das Verhalten einer einzelnen Ameise (den ganzen Tag herumlaufen, Nahrung bringen) unterscheidet sich vom Verhalten der gesamten Kolonie (den begehrtesten Ort finden, mehr Ameisen bilden). Das MVC-Muster beschreibt die gewünschte soziale Struktur einer Ameisenkolonie, während OOP das Design einzelner Ameisen steuert.


5
+1: Ich mag normalerweise keine Erklärungen durch Analogien, aber diese ist brillant.
Michael Borgwardt

@Caleb Das ist ein ausgezeichneter Punkt, vielen Dank!
dasblinkenlight

19

Bei OOP geht es auch um die Trennung von Belangen , dh die Trennung verschiedener Rollen / Verantwortlichkeiten in verschiedenen Objekten.

MVC unterteilt sich in folgende Komponenten:

  • Modell: die Daten und ihre Geschäftslogik
  • Ansicht: Darstellung der Daten
  • Controller: Koordination zwischen dem Modell und der Ansicht.

Diese Zuständigkeiten sind also klar voneinander getrennt und sollten in der Tat in mehrere Einheiten aufgeteilt werden.


Es ist wahr, dass das Prinzip der Einzelverantwortung hilfreich ist, um OOP effektiv zu nutzen, aber ich denke, es ist eine Strecke zu sagen, dass es bei OOP auch um das Prinzip der Einzelverantwortung geht. Das scheint rückständig zu sein.
Caleb

@Caleb Ja, ich verstehe was du meinst. Vielleicht könnte es umformuliert werden, aber Sie verstehen es.
Marco-Fiset

18

In dem Model-View-Controller-Muster sind die Daten und die Logik / Algorithmen in unterschiedlichen Einheiten, dem Modell bzw. dem Controller, angeordnet.

Modell und Controller sind zwei unterschiedliche Rollen. Ein Modell hat sowohl Status als auch Logik, und ein Controller hat sowohl Status als auch Logik. Die Tatsache, dass sie kommunizieren, unterbricht weder die Kapselung einer der beiden - der Controller weiß oder kümmert sich nicht darum, wie das Modell seine Daten speichert oder was er mit den Daten macht, wenn der Controller einen Teil davon abruft oder aktualisiert. Das Modell weiß oder kümmert sich nicht darum, was der Controller mit den vom Modell bereitgestellten Daten macht.

Stellen Sie sich das so vor: Wenn Objekte Daten nicht ohne Unterbrechung der Kapselung hin und her übertragen könnten, könnten Sie wirklich nur ein Objekt haben!

Sollte in einem äquivalenten OOP-Ansatz das Modell und der Controller nicht in derselben logischen Entität platziert werden?

MVC ist ein OOP-Ansatz - insbesondere ein Rezept für die Entscheidung, wie Objekte zum effektiven Organisieren eines Programms verwendet werden sollen. Und nein , das Modell und der Controller sollten nicht dieselbe Entität sein. Ein Controller ermöglicht die Trennung zwischen Modell und Ansicht. Durch die Unabhängigkeit von Modell und Ansicht sind sie sowohl testbarer als auch wiederverwendbarer.


Ich würde hoffen, dass der Controller nur wenig bis gar keinen logischen Zustand hat. Was für einen Zustand hat der Controller Ihrer Meinung nach?
Matthew Flynn

1
@MatthewFlynn Für den Anfang muss ein Controller über die Ansicht und das Modell Bescheid wissen. Darüber hinaus kann es davon abhängen , welche besonderen Geschmack von MVC wir reden, aber im Allgemeinen kann ein Controller Zustand halten in Bezug auf , wie Informationen angezeigt werden sollen (zB aktuelle Auswahl), während die Modell befasst sich mit welchen Informationen angezeigt werden.
Caleb

1
@MattFenwick Genau das meine ich mit dem 'Flavour' ... Genau das, was Sie im Controller speichern und was im Modell eine Frage des Geschmacks und der Konvention ist. In Cocoa / Cocoa Touch ist es üblich, Dinge wie die aktuelle Auswahl und sogar Benutzereinstellungen im Controller beizubehalten. MVC, wie es in einigen Webframeworks verwendet wird, kann fast alles in das Modell und sehr wenig in den Controller einfügen. YMMV.
Caleb

4
@MatthewFlynn Die meisten werden Ihnen zustimmen, aber die Leute halten die Geschäftslogik für eine umfassendere Kategorie, als sie eigentlich sein sollte. Der Controller verwaltet die Anwendungslogik, die häufig mit der Geschäftslogik verwechselt wird. Bei einer idealen Trennung von Bedenken sollte es mir möglich sein, ein Modellobjekt in einer völlig anderen App-Architektur wiederzuverwenden, die denselben Geschäftszielen dient, ohne das Geschäftsobjekt zu ändern. Alles, was die neue Anwendung tun muss, ist, die Schnittstelle zu verwenden und ihre eigenen Dinge mit Daten und Transaktionen zu tun, die zurückgegeben und verarbeitet wurden.
Erik Reppen

1
@MattFenwick: Betrachten Sie eine Mehrbenutzeranwendung. Es ist naheliegend, die Grenze zwischen Modell und Controller zu ziehen, wenn das Modell den gemeinsam genutzten Status und der lokale Status des Controllers verarbeitet. Die aktuelle Auswahl ist lokal, daher erfolgt sie im Controller.
Jan Hudec

4

MVC ist ein Muster, das eine sinnvolle Art der Interaktion von Objekten beschreibt. es ist selbst keine Meta-Klasse. Dabei geht es bei OO darum, Verhaltensweisen und Daten von Entitäten zu beschreiben und wie diese Entitäten interagieren. Es geht nicht darum, das gesamte System zu einem massiven Objekt zu vereinen.


2

Controller repräsentiert nicht das Verhalten eines Modells. Controller repräsentieren insgesamt das Verhalten der gesamten Anwendung - was ein Benutzer tun und was ein Benutzer sehen kann.

Es ist falsch, Controller und Modelle als eine Einheit anzusehen. Sie haben unterschiedliche Zwecke, unterschiedliche Semantiken und sollten daher nicht in einem Objekt vereint werden.


2

Die Modellschicht besteht nicht nur aus Daten, sondern die Controllerschicht ist nur aus Logik.

Die Controller-Ebene verfügt für ihre Zwecke über eine vollständige Sammlung von Objekten. Es gibt Objekte zum Empfangen von Eingaben aus der Ansicht und zum Umwandeln dieser Eingaben in eine Form, die das Modell verarbeiten kann. Das Struts Java-Framework hat ein gutes Beispiel dafür in seinem Aktions- / Formularmodell. Das Formular wird mit Eingaben des Benutzers ausgefüllt und dann an die Aktion übergeben. Die Aktion verwendet diese Daten, um das Modell zu bearbeiten.

Ebenso besteht der Model-Layer nicht nur aus Daten. Nehmen Sie zum Beispiel ein Benutzerobjekt - Sie benötigen möglicherweise Code, der einen Benutzer aus einer Datenbank abruft, oder Code, um einen Benutzer mit einem Auftrag zu verknüpfen oder um zu überprüfen, ob die Adresse des Benutzers in dem Bereich liegt, in dem sich die Dienste Ihres Unternehmens befinden Bild. Dies ist keine Steuerungslogik. Es ist eine Geschäftslogik, die viele dazu veranlasst, ihre Modellebene in mehrere Ebenen zu unterteilen, z. B. Service- oder Manager-Ebenen für die Geschäftslogik, eine DAO-Ebene (Database Access Object) für den Datenbankzugriff und andere.

MVC ist keine Methode zum Organisieren einzelner Modelloperationen. Es funktioniert auf einer höheren Ebene - es ist eine Methode zum Organisieren, wie auf die Anwendung zugegriffen wird. Die Ansicht dient zum Darstellen von Daten und menschlichen Handlungen zum Manipulieren, der Controller zum Übersetzen zwischen Benutzeraktionen und den verschiedenen Ansichten, und im Modell befinden sich Geschäftsdaten und die Geschäftsgründe dafür.


2

Bei OOP geht es darum, Daten und Funktionen , die zusammengehören, zu gruppieren . Eine Berechnung, die auf bestimmten Daten basiert, gehört nicht immer zu diesen Daten.

In MVC wird die Funktionalität zum Anzeigen eines Datenelements (Ansicht) von den Daten (Modell) getrennt gehalten. Warum ist das so? Dies ist speziell so, dass die Anzeigelogik geändert werden kann, ohne dass die zugrunde liegenden Daten geändert werden müssen. Dies erleichtert das Ändern der Ansicht, wenn Sie die gleichen Daten anders darstellen müssen: oder wenn sich die Eigenschaften der Anzeigehardware ändern: oder wenn Sie von Windows zu Linux wechseln. oder wenn Sie möchten, dass zwei Personen die gleichen Daten auf zwei verschiedene Arten betrachten.

MVC steht nicht in Konflikt mit OOP - es wird tatsächlich von einer korrekten Anwendung objektorientierter Prinzipien abgeleitet.


0

Ich glaube, Sie verwechseln persistente Daten, die an ein Modellobjekt gebunden sind, mit den Anwendungsdaten aus den Datenbanken, mit denen das Modell interagiert. Ein Modell enthält Geschäftslogik und Regeln für die Arbeit mit Datenbanken und die Durchführung von Transaktionen. Es kann interne Statusflags setzen und prüfen, z. B. ob heute ein Verkauf stattfindet, ob der Benutzer für den VIP-Status qualifiziert ist, und dann die Logik entsprechend verzweigen, wenn es Zeit ist, auf Daten zuzugreifen, diese zu setzen, sie zu bearbeiten oder einen Kauf durchzuführen. Es sind diese Flags, über die wir sprechen, wenn wir Objekte in Bezug auf die Kapselung einer Reihe von Methoden und persistenten Werten oder Daten diskutieren.

So wie das Modellobjekt Daten verwaltet, um festzustellen, welche Geschäftsregeln im Spiel sind, sollte sich ein Controller, IMO, an allgemeineren Anwendungsstatusdaten festhalten, die sich darauf beziehen, wie sich die App verhalten soll, z. B. ob der Benutzer angemeldet ist oder über ein gültiges Guthaben verfügt Kartendaten vorhanden. Modellmethoden würden in erster Linie den Status dieser Dinge bestimmen, aber es ist sinnvoll, dass der Controller Flags beibehält, die für den allgemeinen App-Fluss relevant sind, wenn sie nicht für den Geschäftsbetrieb oder die Durchführung von Datentransaktionen gelten. Wenn Sie festgestellt haben, dass sie nicht angemeldet sind, sollten Sie das Modell nicht einmal mit Benutzerstatusprüfungen belästigen, bis klar ist, dass ein weiterer Anmeldeversuch durchgeführt wird.

Ebenso mit einem richtigen Ansichtsobjekt im Vergleich zu den typischeren HTML-Vorlagen, die Sie in den meisten serverseitigen Webframeworks sehen. Sobald die Farbeinstellungen des Benutzers geladen sind, sollte es die Ansicht sein, die diese Daten enthält und auf der sie ausgeführt werden. Das Laden, Überprüfen und Ändern von Einstellungen sind Modellprobleme. Sie sollten jedoch nur einmal Modellprobleme sein, bis Änderungen vorgenommen werden.

Laut IMO können Controller keine zusammengesetzten Objekte mit Ansichten und Modellen als interne Aggregatobjekte sein. Dies ist tatsächlich sinnvoll, wenn Sie MVC in einem kleineren Maßstab wie eine UI-Widget-Factory anwenden, da der Controller der ideale Ort ist, um eine Schnittstelle für übergeordnete App-Objekte bereitzustellen und gleichzeitig die Daten und logischen Details der Interaktion von Ansicht und Modell zu vergraben. Für monolothische App-Objekte, bei denen der Controller tatsächlich das Objekt der höchsten Ebene ist, ist dies nicht wirklich sinnvoll.


0

So wie ich es verstehe; Das Argument ist komponentenbasierte Architektur im Vergleich zu OOP. Und ohne in den Religionskrieg einzusteigen, denke ich, dass beide dasselbe beschreiben; Ich betrachte es nur aus verschiedenen Blickwinkeln.

Der Sinn von OOP / OOD besteht beispielsweise darin, Ihren Code modularer und wiederverwendbarer zu gestalten. Ja?

Welches ist genau das Ziel der komponentenbasierten Architektur. Sie sind sich also ähnlicher als alles andere.

Ich denke, dass MVC nur die natürliche Entwicklung von OOP ist und wage es, es zu sagen; Eine bessere Möglichkeit, Ihre Objekte zu organisieren, Probleme zu trennen und Code wiederzuverwenden.


Ich würde sagen, MVC und Component-Based Architecture sind Entwurfsmuster, die nicht außerhalb des Bereichs von OOP-Ansätzen liegen, während OOD / OOP nur eine Ansammlung von Verwirrung und Aufeinandertreffen von Denkschulen und Malacademia in Bezug auf die Verwendung einer an Grenzen grenzenden allgegenwärtigen Programmierung ist richtig konstruieren. Der Vergleich der beiden Kategorien ähnelt dem Vergleich von Quadraten und dem Stift, mit dem Sie die Quadrate gezeichnet haben.
Erik Reppen

-1

Ich komme zu spät zu dieser Party und unter Berücksichtigung aller Antworten vor meiner, gebe ich zu, dass ich nicht viel Neues zu bieten habe. Es scheint mir jedoch, dass es nicht um das Muster selbst, sondern um die Implementierung geht. MVC an und für sich eignet sich nicht für eine bestimmte Methodik. Tatsächlich kann ich mir einfach prozedurorientierten Code in einem MVC-Muster vorstellen (wie ich es mir vorgestellt habe).

Ich denke also, die eigentliche Frage ist: Sind wir anfälliger für prozeduralen Code, wenn wir das MVC-Muster verwenden?

(und vielleicht bekomme ich nur ein paar runter Stimmen?)


-1

Nicht anti, sondern auch OOP ist für MVC nicht erforderlich.

Weil Controller, die normalerweise von Classess dargestellt werden, keine Daten enthalten. Wofür reine Funktionen ausreichen würden.

Wenn Sie weiter gehen und Daten vom Verhalten trennen, nehmen wir beispielsweise an, dass Modelle nur Datenbankdaten verarbeiten, die sie jedes Mal abrufen, wenn ihre Funktion (die für die Datenmanipulation verantwortlich ist) aufgerufen wird (stattdessen, um eine Art von Daten in der Instanz zu speichern) Felder) - dann können Sie das gleiche für die Modelle sagen.

Wenn Sie die Ansichtsebene einer Anwendung in ähnlicher Weise unterteilen, werden Sie zu dem Schluss kommen, dass MVC nichts mit OOP zu tun hat, und dass es durchaus möglich ist, die MVC-Implementierung ohne Probleme nur mit einem prozeduralen Ansatz zu schreiben .


Haha, ich sehe, dass einige Leute Schmerzen in der A ** haben, wenn sie mit Fakten konfrontiert werden. Zu viel Aufwand, eigene Frameworks mit OOP zu erstellen? Kannst du die verlorene Zeit nicht aushalten? Die einfachsten Antworten sind die besten.
Luke1985

Ich bin mir nicht sicher, warum diese Antwort falsch ist. Er sagt, sie sind nicht verwandt und nicht "anti". Scheint ziemlich genau zu sein.
mwilcox

-3

Meiner Meinung nach haben OOPs den Nachteil, dass dies mehr Kopplungseffekt als Kohäsion zeigt, da die (Daten und Verhalten) als eine Einheit (Klasse) geformt sind. Auf der anderen Seite verfügt MVC über ein Modell mit ... (Beans, DAOs, andere Logikklassen), einen Controller, der angibt, wie das Steuerelement verschoben werden muss, und Ansichten, um festzulegen, wie die Daten angezeigt werden sollen, werden getrennt angegeben. Ausgehend davon, ob das Projekt zu groß für die Vorbereitung ist, kann es im Gegensatz zu OOPs einfach als separate Entität erstellt werden. Das Problem wird in logischen Mustern gelöst, genau wie bei der Strategie zum Teilen und Erobern, und MVC folgt diesem Prinzip.


Ist das nur deine Meinung oder kannst du es irgendwie bestätigen?
gnat
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.