MVC: Mein Controller scheint die Hälfte der Zeit nutzlos zu sein. Ist das ein Problem?

9

Wenn ich ein Programm mit MVC entwerfe, ist der Controller oft die Hälfte der Zeit nutzlos.

Was ich damit meine ist Folgendes: In der Ansicht passiert etwas (z. B. ein Klick auf eine Schaltfläche). Die Ansicht benachrichtigt dann den Controller. Der Controller delegiert dann direkt an das Modell und unternimmt nichts anderes, da er nichts zu tun hat.

Zum Beispiel:

Der Benutzer drückt die Taste 'Farbe Blau'> Ansicht teilt dem Controller mit controller.colorBlue()> Controller teilt dem Modell mit model.colorBlue()> Modellfarben etwas Blaues.

In diesem Beispiel scheint der Controller nutzlos zu sein. Es fügt nichts hinzu. Die Ansicht hätte genauso gut direkt mit dem Modell sprechen können.

In der anderen Hälfte der Zeit führt der Controller jedoch eine Art Vermittlung zwischen Ansicht und Modell durch.

Meine Frage lautet: Wie häufig ist dies in MVC-Strukturen? Ist es vernünftig, dass die Hälfte der Zeit, die mein Controller benötigt, unnötig erscheint? Oder ist das ein Problem? Ist das üblich? Wie soll ich das angehen?

Wenn meine Frage nicht klar genug ist, sagen Sie es bitte.

Aviv Cohn
quelle
1
Wie von Robert Harvey angedeutet, ist es für dieses spezielle Beispiel möglicherweise besser, wenn controller.colorBlue()tatsächlich tatsächlich angerufen wird model.setColor(0, 0, 255);. Ein Grund für die Trennung zwischen Modell und Ansicht ist, dass häufig mehrere Benutzeroberflächenelemente einen einzelnen Status im Modell darstellen (z. B. wird ein Element im Menü aktiviert, die Symbolleiste gedrückt und der Zeiger ändert sich in eine Füllung Das Symbol all entspricht dem aktuell ausgewählten Werkzeugfeld im Modell. Bei der MVC-Trennung müsste sich das Modell nicht um die Synchronisierung der verschiedenen UI-Elemente kümmern.
Lie Ryan

Antworten:

12

Sie unterschätzen die Bedeutung einer Abstraktionsebene zwischen Ihrer Benutzeroberfläche und Ihrem Modell. Der Controller erfüllt diese Funktion zu 100 Prozent.

Ihr Beispiel model.colorBlue()ist etwas spekulativ. In einem realen Modell wäre dies wahrscheinlich eine CRUD-Methode. Ihre Schaltfläche könnte also eine Schaltfläche "Kunde erstellen" sein, Ihre Controller-Methode CreateCustomer()und Ihr Modell CreateCustomer(). Sicher, Sie gehen gerade durch den Anruf.

Aber was ist, wenn Sie die Funktionsweise des Modells ändern müssen? Wenn Ihre Ansicht Ihr Modell direkt aufruft, wird Ihre Anwendung unterbrochen, wenn Sie das Modell ändern. Controller-Methoden bieten einen "Zugriffspunkt" für Ihre Ansicht. Sie können eine einfache Änderung an der Controller-Methode vornehmen, indem Sie möglicherweise den Model-Aufruf in ändern CreateCustomerWithVerification(), und alles funktioniert weiterhin.

Die gleiche Begründung gilt für eine Service-Schicht. Anstatt einfach CRUD-Methoden in Ihrem Modell zu haben, sollten Sie Geschäftsaktionen durchführen. Auf diese Weise halten Sie die Geschäftslogik von Ihren Controllern fern und ermöglichen die Verwendung des Modells an einem anderen Ort, möglicherweise in einer WPF-Anwendung.

Stellen Sie sich den Controller als "Switchyard" vor. Es sollte ein Vermittler sein, der Anforderungen zwischen Ihrer Benutzeroberfläche und Ihrem Modell vermittelt, aber Controller-Methoden sollten so wenig Logik wie möglich enthalten.

Robert Harvey
quelle
Lassen Sie mich sehen, ob ich verstehe, was Sie sagen. Sie sagen, auch wenn der Controller einfach direkt an das Modell delegiert, ist es aus diesem Grund immer noch gut, eine zwischen Ansicht und Modell zu haben: Wenn sich das Modell ändert, müssen sich möglicherweise alle Objekte ändern, die seine Methoden aufrufen. Wenn die Ansicht Methoden für das Modell aufruft, muss sie geändert werden. Wenn der Controller die Methoden aufruft, muss er sich ebenfalls ändern. Der Unterschied besteht jedoch darin, dass die Ansicht für die Anzeige der Benutzeroberfläche verantwortlich ist - ein wichtiger Bestandteil der App. Die einzige Verantwortung des Controllers ist jedoch genau dies - kommunizieren [..]
Aviv Cohn
mit dem Modell. Aus diesem Grund ist es besser, den Controller zu ändern, wenn sich das Modell ändert (und die Ansicht unverändert zu lassen), und dann die Ansicht zu ändern.
Aviv Cohn
3
Ja, das ist genau richtig. Die von der Controller-Schicht bereitgestellte Trennung ermöglicht Änderungen im Modell, ohne die Benutzeroberfläche oder das Routing zu beschädigen.
Robert Harvey
Aha. Und nur um sicher zu gehen: Es ist besser, den Controller zu ändern als die Ansicht, wenn sich das Modell ändert, da die Ansicht für wichtige Logik verantwortlich ist - die Anzeige der Benutzeroberfläche. Wenn Sie es theoretisch ändern, ist der gesamte andere Code gefährdet. Der einzige Zweck des Controllers besteht jedoch genau darin, dem Modell Inhalte mitzuteilen und somit vom Modell abhängig zu sein - die Ansicht muss dies also nicht. Und da der Controller keine andere wichtige Logik enthält, ist es besser, dass sich der Controller ändert, wenn das Modell dies tut, als dass sich die Ansicht ändern muss. Ist das richtig?
Aviv Cohn
Ja, im Wesentlichen. Indem Sie solche Änderungen an der API-Oberfläche des Modells und den Controller-Methoden isolieren, können Sie eine bessere Entkopplung von der Benutzeroberfläche erzielen. Die Ansicht sollte sich niemals aufgrund einer Änderung der Geschäftslogik ändern müssen, es sei denn, die Ansicht muss auch die Änderungen in der Art und Weise widerspiegeln, wie das Geschäft funktioniert. Anders ausgedrückt, die Ansicht sollte so wenig wie möglich über die Modellobjekte wissen. Aus diesem Grund haben wir Dinge wie ViewModels (die eine zusätzliche Entkopplung vom Modell bieten).
Robert Harvey
-1

Beim Codieren könnte man so denken:

  • Kann ich die Ansicht in eine andere Ansicht (Konsole, Dienst) oder denselben Controller für eine andere Ansicht ändern?
  • Kann ich das Modell ändern, um andere Datenbanken zu verarbeiten, oder in einen externen Dienst schreiben?

In Ihrem Fall scheinen Sie die Domänenlogik in das Modell einzufügen, und dies würde Ihnen Probleme bereiten, wenn Sie sie ändern möchten: Sie müssen Methoden wie "model.colorBlue" in ein neues Modell kopieren.

Und was würde passieren, wenn sich die Definition von "blau" ändert? Sie müssen es 2 Modelle ändern. Auch in Controller sollten Sie nicht direkt in Ihre Datenbank schreiben, aber wie Lie Ryan betonte , sollten Sie verwenden model.setColor.

Gleiches gilt für Ansichten. Wenn Sie anfangen, Logik oder Validierung anzuzeigen, müssen Sie alle Funktionen kopieren, wenn Sie die Ansicht ändern möchten.

Mantas Karanauskas
quelle