MVC - Es ist falsch, vom Modell umzuleiten

8

Ich möchte fragen, ob es ein guter Ansatz ist, um von einem Modell statt von einem Controller umzuleiten.

Der Grund, warum ich das machen möchte, ist, dass es einfacher ist, die Testumleitung von einem Modell zu vereinigen (ich übergebe einfach ein Mock-Redirector-Objekt an das Modell in meinen Tests), im Gegensatz zu einem Controller, der schwieriger zu testen ist. Es hält auch den Controller dünner, da alles, was ich in der Steuerung mache, eine Instanz des Modells erzeugt und diese Parameter vom Anforderungsobjekt übergibt. Auf diese Weise gibt es keinen einzigen if / else im Controller.

Ist es eine schlechte Übung?

    
Richard Knop 21.05.2013, 12:26
quelle

5 Antworten

3

Weder Controller noch Modell sollten irgendwo etwas umleiten. HTTP-Location-Header ist eine Form einer Antwort, die ausschließlich im Blickwinkel der Ansichten.

Model-Layer beschäftigt sich mit Business-Logik, sollte es sogar für die Existenz der Präsentationsschicht völlig blind sein.

Grundsätzlich geht es darum: Controller handhaben Eingaben, Ansichten handhaben Ausgabe . HTTP-Header sind Teil der Ausgabe.

  

Hinweis: Beim Umgang mit Rails-Klonen werden häufig Weiterleitungen in "controller" ausgeführt. Es ist, weil das, was sie "Controller" nennen, eigentlich eine Verschmelzung von View- und Controller-Verantwortlichkeiten ist. Dies ist ein Nebeneffekt der Entscheidung, echte Ansichten durch einfache Vorlagen als dritte Seite der Dreiergruppe zu ersetzen.

    
tereško 21.05.2013, 12:31
quelle
3

Am häufigsten in Webapplikationen - MVC oder nicht - werden Redirects auf einer höheren Ebene implementiert. In nicht-OOP-Code ist dies oft eine globale Funktion auf hoher Ebene, die viel über den globalen statischen Zustand weiß und was eine Anfrage und eine Antwort darin repräsentiert.

In mehr OOP-getriebenen Sites finden Sie dies oft als eine Methode mit dem "response" -Objekt (vergleiche Symfony2 und HTTP Fundamentals ; beachten Sie, dass Symfony2 nicht MVC ist), es hat jedoch oft auch ähnliche Methoden (zB Unterschied zwischen $this->render und $this->redirect Symfony2 ).

Da diese "Antwort" -Objekte meistens in der Web-Anwendung eine zentrale Rolle spielen, ist dies in meinen Augen ebenso möglich wie eine höhere Ebene.

Aus Testsicht - insbesondere bei Integrationstests - müssen Sie normalerweise nicht speziell auf Weiterleitungen testen. Sie sollten testen, dass in der Regel Ihre Redirect-Funktionalität auf der HTTP-Ebene funktioniert, so dass Teile Ihrer Anwendung, die davon Gebrauch machen, darauf vertrauen können. Häufige Probleme sind, den Vorschlägen in den HTTP / 1.1-Spezifikationen nicht wirklich zu folgen, wie etwa die Bereitstellung eines Antwortkörpers mit Weiterleitungen. Eine gut funktionierende Webanwendung sollte dies berücksichtigen. Dies gilt auch für die Verwendung von vollständig qualifizierten URIs.

Wie passt das alles hier in MVC? In einem HTTP-Kontext könnte dies wie folgt vereinfacht werden:

  • Die Antwort besteht darin, dem Benutzer mitzuteilen, dass er woanders hingehen soll.
  • Wenn der Benutzer nicht wichtig wäre, könnte die Anwendung forward direkt - das ist ein anderer Befehl ausführen, der Client würde nicht dafür verwendet werden, die Umleitung nicht notwendig (Unterbefehl).
  • Die Antwort lautet: Erledigt. Und dann: Siehe als nächstes diesen Befehl (in Form eines URI).

Das hört sich ziemlich so an, als wäre die tatsächliche Weiterleitung nur eine Ausgabe, die Sie in der Client-Kommunikation auf Protokollebene an den Client senden. Es gehört in die Schnittstelle des Protokolls, das Sie unterstützen möchten. Also nicht in das Modell, sondern in die Client-Schnittstelle und die Grenze der Client-Schnittstelle innerhalb einer MVC-Anwendung ist der Controller AFAIK.

Also ist die Weiterleitung wahrscheinlich ein View-Value-Objekt mit einer besonderen Bedeutung. Um das in einem HTTP-MVC zu erreichen, benötigen Sie eine vollständige URL-Abstraktion, die die meisten PHP-Frameworks und -Bibliotheken groß machen, weil es nicht gut bekannt ist, wie das funktioniert. Also würde ich am Ende sagen: Tun Sie, wie Symfony2 es getan hat, legen Sie es in eine Layer-Komponente auf hoher Ebene, lassen Sie MVC fallen und leben Sie mit den Mängeln.

Alles andere ist schwer zu erreichen, wenn Sie es anders versuchen, besteht ein hohes Risiko, nicht mehr mit dem Abstrahieren aufzuhören.

    
hakre 21.05.2013 13:37
quelle
2

Ich würde ja sagen, es ist falsch. Soweit ich verstanden habe, sind die Controller während der Verwaltung von Daten und Ansichten für die Verwaltung von Layouts (dh wie Daten angezeigt werden sollen) für die HTTP-Anfragen / -Antworten nur und ausschließlich zuständig Management (im Falle einer Web-App), und Umleitungen gehören meiner Meinung nach normalerweise zu dieser Ebene.

Beispiele in gemeinsamen Frameworks

Symfony :

%Vor%

Spring MVC :

%Vor%     
sp00m 21.05.2013 12:43
quelle
0

Ich denke, Sie könnten ein Modell für den Workflow oder die Navigation Ihrer Anwendungen (in Ihrer Modellschicht) haben und dann Ihren Controller die verschiedenen Konzepte in Ihrem Workflow / Navigationsmodell in die Ansichten übersetzen lassen, die angezeigt werden sollen. p>

Ihre Arbeitsablaufklasse / Ihr Arbeitsmodul könnte über die verschiedenen Aktivitäten / Phasen / Schritte, die dem Benutzer zur Verfügung stehen, Bescheid wissen und Ihre Anwendung wie eine Zustandsmaschine modellieren. Ihr Controller würde also Aufrufe an dieses Modul senden, um den Status zu aktualisieren und eine Antwort erhalten, die dem Controller mitteilt, in welche Aktivität / Phase / Schritt es gehen soll.

Auf diese Weise ist Ihr Workflow-Modell leicht zu testen, aber es weiß immer noch nichts über Ihre Ansichtstechnologie.

    
Simon 21.05.2013 12:34
quelle
0

Viele haben diese Gedanken in Kommentaren erwähnt, daher hier eine Zusammenfassung:

Die Logik, um herauszufinden, ob Sie eine Weiterleitung benötigen und was Ihre Weiterleitung sein sollte, gehört in den Controller. Das Modell nimmt einfach die Daten, die eine Ansicht benötigt. Dies geschieht, nachdem Sie entschieden haben, welche Ansicht gerendert werden soll. Stellen Sie sich die Weiterleitung als eine Anweisung vor, um eine andere Controller-Aktion auszuführen.

Ich benutze ASP.NET MVC und die Controller generieren zu diesem Zweck ein RedirectResult, das komplett Unit-testbar ist. Ich weiß nicht, was in Ihrem Framework unterstützt wird, aber MVC würde dies tun:

%Vor%

In Ihren Komponententests instanziieren Sie MyController und überprüfen den Typ des Ergebnisses und optional den URL- oder Ansichtsnamen.

Unabhängig davon, ob die Weiterleitung tatsächlich ausgeführt wird, handelt es sich nicht um ein Problem mit dem Komponententest. Dies stellt im Wesentlichen sicher, dass Ihr Framework ordnungsgemäß funktioniert. Was Sie testen müssen, ist, dass Sie die richtige Anweisung (d. H. Die Weiterleitung) und die richtige URL geben.

    
gabnaim 21.05.2013 14:35
quelle