heinetz: Überlegungen MVC

Hallo Forum,

ich versuche immernoch mir Sinn, Zeck und Herangehensweise von MVC zu erarbeiten. Langsam gewinne ich an Orientierung ;)

Von meinem ursprünglichen Plan, mein aktuelles Projekt mit Zend 2 umzusetzen, habe ich mich nach der Auseinandersetzung hier verabschiedet und habe mir statt dessen diverse einfache MFC-Beispiele angesehen, um Gemeinsamkeiten und Unterschiede herauszuarbeiten. Alle haben zuerstmal jeweils eine controller-, view- und model-class um daraus eine Ansicht zu generieren. Interessant ist, wie mit unterschiedlichen Ansichten umgegangen wird. Für die Beispiele werden gerne mal die beiden Ansichten 'list' und 'entry' eines bspw. Gästebuchs herangezogen. Mit je einem m, v und c werden die unterschiedlichen Ansichten unterschiedlich realisiert.  Bspsw. in diesem Beispiel wird jeweils in m und in c eine Fallunterscheidung (if 'entry') getroffen. Und so gibt es am Ende zwar nur jeweils einmal m, v und c aber die kümmern sich jeweils um unterschiedliche Fälle.

Ganz gut finde ich dieses Beispiel:

Während in der ersten Version auch jeweils nur ein m,v und c benötigt wird weil nur eine Seite angezeigt wird, wird in der 3. Version für jede Ansicht ein m, ein v und ein c benötigt.

Unter der Aspekt, dass das MVC-Muster dazu dient, den Code modular aufzubauen, damit er übersichtlich und wiederverwendbar ist, wird in dem letzten (sicher extremen) Beispiel aber doch erstmal sehr viel Code produziert. Statt 3 Seiten-Files werden hier 3 Controller, 3 Models, 3 Views und 3 Templates, also 12 Files benötigt.

Ist nur so eine Überlegung ...

gruss,
heinetz

  1. Hallo Forum,

    Ist nur so eine Überlegung ...

    Eine Subklasse, verschiedene Templates und den Controller als Interface, ist auch ne Überlegung wert.

    MfG

  2. Moin

    Unter der Aspekt, dass das MVC-Muster dazu dient, den Code modular aufzubauen, damit er übersichtlich und wiederverwendbar ist, wird in dem letzten (sicher extremen) Beispiel aber doch erstmal sehr viel Code produziert. Statt 3 Seiten-Files werden hier 3 Controller, 3 Models, 3 Views und 3 Templates, also 12 Files benötigt.

    Es geht in dem Beispiel von lemme.at, was nicht zu den schlechtesten gehört, im letzten Schritt um Trennung der Ansichten für die gesamte Seite (äußeres Template) und den Modulansichten (inneres Template). So kannst du für außen mittels entscheidungsvariablen sagen ob Rahmenansicht für normale Seite oder Forum (unterscheidet sich vielleicht) und für das Forum kannst du 2 Ansichten für Liste und beitragsansicht erstellen. Diese Unterteilung hilft auch dem Model die entsprechenden richtigen Daten zu entlocken.

    Wenn du dein erstes größeres projekt so aufbaust, wirst du schnell den Vorteil erkennen. Wobei ich im Moment eher zur MVP-Struktur übergegangen bin. Da wissen view und Model nichts von ein ander und nur der Controller kommuniziert und steuert.

    Sinn und Zweck hinter MVC ist übrigens die strikte Trennung zwischen Datenhaltung/Geschäftslogik, Steuerungslogik und Präsentation. Somit kannst du verschiedene DAtenbanken hinten dran hängen, Verschiedene Ansichten für verschiedene Endgeräte und Anwendungsfälle erzeugen (z.B. für API o.ä.) das ganze wird über den Controller als Kommunikationsschnittstelle geregelt.

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
    ### Henry L. Mencken ###
    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
    ### Viktor Frankl ###
    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
  3. Tach!

    Von meinem ursprünglichen Plan, mein aktuelles Projekt mit Zend 2 umzusetzen, habe ich mich nach der Auseinandersetzung hier verabschiedet und habe mir statt dessen diverse einfache MFC-Beispiele angesehen, um Gemeinsamkeiten und Unterschiede herauszuarbeiten. Alle haben zuerstmal jeweils eine controller-, view- und model-class um daraus eine Ansicht zu generieren. Interessant ist, wie mit unterschiedlichen Ansichten umgegangen wird. Für die Beispiele werden gerne mal die beiden Ansichten 'list' und 'entry' eines bspw. Gästebuchs herangezogen. Mit je einem m, v und c werden die unterschiedlichen Ansichten unterschiedlich realisiert.  Bspsw. in diesem Beispiel wird jeweils in m und in c eine Fallunterscheidung (if 'entry') getroffen. Und so gibt es am Ende zwar nur jeweils einmal m, v und c aber die kümmern sich jeweils um unterschiedliche Fälle.

    Das sehe ich nicht als besonders gutes Beispiel an.

    Ganz gut finde ich dieses Beispiel:
    Während in der ersten Version auch jeweils nur ein m,v und c benötigt wird weil nur eine Seite angezeigt wird, wird in der 3. Version für jede Ansicht ein m, ein v und ein c benötigt.

    Auch das unterschiedet sich vom Prinzip her nicht vom obigen. Beide unterscheiden sich aber sehr deutlich vom Aufbau und der Verwendungsweise der MVC-Frameworks, welche mir bisher über den Weg gelaufen sind. Grundlegend können die beiden Beispiele das MVC-Muster und die Zuständigkeiten der Teile erklären. In der Praxis der anderen Frameworks ist es jedoch so, dass die Controller nicht nur eine Methode namens display haben und via Fallunterscheidung die unterschiedlichen Requests abarbeiten, oder dass gar jeder Request seinen eigenen Controller bekommt, selbst wenn die Aufgaben daselbe Themengebiet betreffen.

    Die Frameworks haben vor den eigentlichen MVC-Teil einen Frontcontroller (quasi ein Türsteher) geschaltet, der alle Requests entgegennimmt und ein paar grundsätzliche Initialisierungen erledigt. Der gibt dann ab an den Router, der aus den Daten des Requests ermittelt, was eigentlich zu tun ist. Das Ergebnis des Routings ist, dass ein Controller gefunden wird, der die Aufgabe zu erledigen hat. Es ist nun aber nicht sinnvoll, jede kleine Aufgabe in einen eigenen Controller zu packen. Es gibt diverse Initialisierungsschritte, die man gern nur einmal als Code notiert hat. Sie auszulagern in einen Elternklasse, mag eine Lösung sein. Eine große Methode, die per Fallunterscheidung arbeitet, wird irgendwann zu groß und unhandlich. Auch das ist kein gescheiter Weg.

    Man geht stattdessen den Weg, dass man dem Controller eine generelle Aufgabe zuweist, beispielsweise kümmert sich der eine Controller um allgmeine Dinge, wie die Startseite und die Kontaktseite und ähnlichen Kleinkram, ein anderer kümmert sich um die Verwaltung der Schüler, mit dem nächsten verwaltet man die Fächer und so weiter und so fort. Das Beispiel hier ist mal ein ganz kleiner Ausschnitt einer Anwendung zur Verwaltung einer Schule. Die zwei bisher ins Spiel gebrachten Models sind Schüler und Fach. Ein Schüler hat bestimmte Daten, ein Fach hat andere.

    Um einen Datensatz zu bearbeiten gibt es die vier grundlegenden Aktionen CRUD: Create, Read, Update und Delete (auch als RUDI bekannt mit Insert statt Create). Das Read ist meist zweiteilig, einmal als Liste und einmal als Detail-Ansicht. Damit hat man 5 Aktionen, die alle am selben Model was zu schaffen haben. Diese Aktionen bringt man alle in einem Controller unter, jeweils in einer eigenen Methode. Es gibt da also den Schüler-Controller und der hat die Actions list, view (für die Detailansicht eines Schülers), create, update und delete. Und es gibt den Fach-Controller, der erstmal grundlegend dieselben Aufgaben hat, aber eben aufs Fach bezogen. Nun ist es aber so, dass dann doch nicht dasselbe mit nur unterschiedlichen Namen zu erledigen ist, sondern die Anforderungen bescheren einem, dass man mit Schülern und Fächern unterschiedliche Dinge machen muss. Deshalb ist es keine schlechte Idee, das auf diese Weise zusammenzufassen und getrennt zu halten. Um ähnlichen Code nicht mehrfach schreiben zu müssen, gibt es andere Lösungswege, abseits des MVC-Musters.

    Ein Controller kümmert sich also um ein Themengebiet und um die einzelnen Aktionen innerhalb dieses Gebiets/Controllers sind die Actions-Methoden zuständig. Der oben erwähnte Router ermittelt nicht nur den für den jeweiligen Request zuständigen Controller, er ermittelt auch die passende Action. Mehr fällt nicht in seinen Zuständigkeitsbereich. Das Instantiieren des Controllers und das Aufrufen der Action macht ein anderer Teil des Frameworks. Damit kommt man in der Regel nicht in Berührung. Man konfiguriert nur den Router und schreibt dann den Code für die Controller-Actions.

    Unter der Aspekt, dass das MVC-Muster dazu dient, den Code modular aufzubauen, damit er übersichtlich und wiederverwendbar ist, wird in dem letzten (sicher extremen) Beispiel aber doch erstmal sehr viel Code produziert. Statt 3 Seiten-Files werden hier 3 Controller, 3 Models, 3 Views und 3 Templates, also 12 Files benötigt.

    Das stimmt, und so wie das dort gemacht ist, ist das auch nicht üblich. Andererseits geht es nicht, dass man eine komplexe Aufgabenstellung mit drei Zeilen Code erledigt. Wenn man ein Framework verwendet, dann ist das Hauptziel meistens, dass trotz der Komplexität die Übersicht erhalten bleibt. Der notwendige Code wird nicht geringer, oftmals sogar mehr (auch ohne den Code des Frameworks mitzuzählen), dafür ist er aber besser strukturiert, so dass man sich selbst und als Außenstehender schneller (wieder) einarbeiten kann, wenn das notwendig wird. Jede Vereinfachung verschiebt die Komplexität nur an eine andere Stelle. Man braucht eine Menge Wissen und Erfahrung, um die Dinge so zu verschieben, dass Übersicht entsteht, trotz weiter erhöhter Komplexität.

    dedlfix.