MVC – ist das Alles?
Model View Controller ist mitlerweile so etwas wie ein Mantra für Fullstack-Framework-Nutzer geworden. Ähnlich wie beim buddhistischen OOOOm erlangt man nach einer gewissen Zeit den Zustand der absoluten Konzentration. Es wird einfach als gegeben hingenommen, dass die Nutzung des MVC-Patterns die Lösung aller unserer Probleme in der Programmierung von Webanwendungen ist.
Zuerst einmal kommt das Pattern aus der „normalen“ Anwendungsentwicklung und ist gedacht für die Trennung zwischen Anzeige(fenster), also der View, der Daten (Model) und der Businesslogik (Controller). Hier werden jetzt die ersten aufschreien und sagen: Die Logik gehört nicht in den Controller sondern in die Models. Und sie haben recht. Aber ich auch. Denn: Es ist gar nicht definiert wo genau die Logik sein soll. Manche sagen: Thin Controller, Big Models. Andere Big Controller, Thin Models. Es gibt keinen Standard für die Verortung von Businesslogik.Jedenfalls keinen, der im MVC-Pattern beschrieben ist.
Die heutigen PHP Fullstack-Frameworks setzen die Logik teilweise in den Controller, teilweise in die Models. Einige gehen auch einen anderen Weg und führen eine Zwischenschicht zwischen Controller und Model ein. Ich nenne sie mal Functional Model. Ein Model ist für mich einfach eine Schicht, die mir Daten bereit stellt. Entweder aus der Datenbank oder egal von wo. Das heisst es ist eigentlich ein DAO (Data Access Object). Ich bin aber ein Fan von Thin Controllern. Und jetzt komme ich in die Bedroullie: Wohin kommt denn bitte nun meine Business-Logik? Ich würde sie in die Functional-Models bauen. Diese stellen dem Controller und ggf. der View die erforderlichen Daten bearbeitet und validiert zur Verfügung; bzw. auch anders herum beim Speichern von Daten. Wichtig ist, dass diese Zwischenschicht in beiden Richtungen funktioniert und zum Beispiel die Validierung von Daten vornimmt.
Die Idee an den Function-Models ist, dass sie die Logik zusammenfassen können. Das heisst man kann zum Beispiel Helper-Klassen einsetzen, die ggf. auch in anderen Teilen des Systems genutzt werden können und vermeidet Redundanzen. Auf der anderen Seite könnnen mehrere Models (DAOs) in einem Functional Model genutzt werden und sie können sehr einfach verändert werden, weil sie komplett unabhängig von der Businesslogik funktionieren.
Ich frage also: Was ist eure Meinung zu der Frage, wohin die Businesslogik gehört und wie geht ihr mit DRY im Bezug auf Models um, wenn ihr eure Logik in die Models packt?
Vielleicht sollte erst einmal geklärt werden, was denn diese Business-Logik eigentlich genau ist. Aus Gesprächen mit anderen Entwicklern und aus Diskussionen in Foren, Blogs und Mailinglisten weiß ich, dass darunter auch viele etwas anderes verstehen.
Die einen sagen, Business-Logik ist sowas wie das Ausrechnen der MwSt. für einen Preis. Die anderen sagen, Business-Logik ist auch das Weiterverarbeiten von Daten, die von einem Formular versandt worden sind.
Also, was versteht ihr unter Business-Logik? Und danach können wir klären, wohin der Kram am besten gehört… 😉
Das Model ist doch nicht einfach nur ein DAO, sondern besteht aus mehreren Schichten. Wobei das DAO die unterste Schicht bildet. In meinem Model kommen darüber noch der Data Mapper, der Service Layer und alle schieben das eigentliche Domain Model hin und her. Die von Dir als „Functional Model“ bezeichneten Teile des Models entsprechen in etwa meinem Service Layer. Matthew Weier O´Phinney hat einen interessanten Vortrag zu dem Thema bei Slideshare zur Verfügung gestellt und auch in seinem Blog gibt es einige interessante Beiträge zum Thema Object Modeling.
http://www.slideshare.net/weierophinney/playdoh-modelling-your-objects-1766001
http://weierophinney.net/matthew/archives/202-Model-Infrastructure.html
Persönlich bin in ein Freund der Zwischenschicht, für mich ist Business-Logik alles das was nicht direkt mit Anzeige oder Aufnahme von Daten zu tun hat.
In meiner Zwischenschicht (bei mir Service) werden die Daten validiert, gecached, gefiltert, berechnet oder was auch immer. Anschließend ruft der Service die benötigten Dao’s aus, mag das die Twitter Api oder meine Datenbank sein.
Ich bin eher ein Fan von Big Controllern. Die Datenhaltung sollte nichts anderes tun, also die Daten transparent! zu halten. Wenn dort wilde Berechnungen stattfinden ist das in meinen Augen nicht gut. Da geht das vertrauen in die Datenhaltung verloren.
Es ist auch schwieriger die Datenbank zu wechseln (oder mehrere zu nutzen), wenn zuviel Logik in der Datenhaltung steckt. Mitunter sind die Datenstrukturen ja doch sehr unterschiedlich.
Zum DRY: Die Businesslogik ist ja nicht nur der funktionale Code, sondern auch das Framework. Sofern man auf ZF setzt, sollte man parallel sein eigenes noch dazu tun. Eine hübsche Klassensammlung vermeidet die ungewollte Redundanz ganz gut. Wichtig ist aber alles gut zu dokumentieren und sprechende Klassen-, Methoden- und Eigenschaftsnamen zu wählen. Je besser die gewählt sind, desto leichter fällt es, sich daran zu erinnern und nicht die Methode unter einem neuen Namen erneut zu implementieren.
Gehe ich von einer anderen Perspektive heran, kann ich das ‚Model‘ als die abstrakte Syntax meiner (domänenspezifischen) Sprache sehen. Es gibt also vor, wie die Elemente meines Modells zueinander in Beziehung stehen.
Das ‚View‘ wäre die konkrete Syntax. Also die Art und Weise der Darstellung von Ausprägungen (bzw. Instanzen) meines Modells.
Ein Controller steuert in dem Szenario was (Model), wie (View) dargestellt wird. Dabei kann jede Menge Logik zum Einsatz kommen. Das würde ich aber nicht als „Businesslogik“ bezeichnen. Es beeinflusst mein Model nicht, sondern nur die Darstellung desselben.
Um in die reale Welt zurückzukehren: ein Controller sollte keine MwSt berechnen. Ein Controller sollte dafür sorgen, dass der Betrag im richtigen View dargestellt wird.
Was jetzt aber genau „Businesslogik“ ist, hängt möglicherweise zu stark von der Domäne ab, als das man das pauschal beantworten kann. Wenn man aber meint, es handele sich um „Businesslogik“, sollte man sie in die Nähe des Models packen. Wenn ein Dritter dann nicht lange nach einer Methode suchen muss, hat man es wahrscheinlich richtig gemacht 🙂
Bisher habe ich diese ominöse „Business-Logik“ am ehesten im Controller gehalten. Manchmal in eigene Klassen ausgelagert. Vielleicht ist es wie immer die richtige Mischung 🙂 Aber Fat Controller können manchmal echt unübersichtlich sein. Den optimalen Weg habe ich für mich also noch nicht gefunden.
Hatte ich bei einem Gren Field Project die Wahl, würde ich auch eine Zwischenschicht einbauen, wie auch immer ich dann diese nenne. Fat Controller erinnert mich zu sehr an das prozeduale „PHP Dark Age“ 😉
Die Trennung der oben genannten Komponenten ist ehrlich gesagt nicht einfach. Businesslogik ist meiner Meinung das Verhalten zu bestimmten Zuständen der jeweiligen Applikation.
Hierbei gibt es allerdings bei mir einen wichtigen Aspekt: Die Manipulation von Daten gehört definitiv nicht in das Model oder in den Controller. Das hat einfach den Hintergrund, dass Daten immer wieder in verschiedenen zuständen benötigt werden, welche allerdings zunächst als Rohdaten geliefert werden. Eine neue Ebene in der Applikation wäre hier fehl am Platz, da sonst diese Ebene zu viel Müll enthalten würde, weil sie wiederrum in der Verarbeitungsebene Daten unterschiedlich behandelt.
Es ist ein heikles Thema und ich glaube auch nicht, dass man hier auf einen nenner kommen wird. Jeder hat ein anderes Bild von seinen Applikationen und handhabt abfolgen meist anders als fremde Entwickler, da ihm diese Varianten einfach nicht gefallen möchten oder auch aus prinzip um strukturell vorzugehen.
Und wie geht man mit Vorgaben durch die eingesetzte Software um?
Gerade Full Stack Frameworks implementieren meist einen MVC, nutzen diesen selbst und dokumentieren Best Practices.
Ich kann mir gut vorstellen, dass eine neue BL Schicht in manches Framework einfach nicht richtig reinpasst und mir den Zugang zur Dokumentation verbaut oder zumindest erschwert.
Moment mal: Business-Logik im Controller? Das gehört doch zum Model! 😉
Meine bescheidene Meinung ist, dass man einen Controller im Web nicht unbedingt braucht. Event-Hooks oder ein Even-Abo-System mit einem Scheduler erfüllen einen ähnlichen Zweck, sofern die Geschäftslogik ausreichend gut gekapselt ist, eine geringe Kopplung und hohe Kohärenz aufweist.
Grund ist, dass im Web zustandslose Systeme vorherrschen. Folglich reduziert sich auch der Aufwand für Transitionen zwischen Zuständen, deren Steuerung eigentlich Aufgabe des Controllers wäre.
Was übrig bleibt ist aufgrund von Zustandsänderungen das korrekte Nachfolgeereignis zu finden – also, auf die richtige URL zu verweisen. Diese Aufgabe ist jedoch so einfach, dass man den Controller automatisieren kann.
Wie haben zum Beispiel ein Event-Abo-System mit virtuellem Controller. Das Abonnieren von Ereignissen geschieht über Annotations im Doc-Block der PHP-Funktion, welches das Ereignis behandeln soll. Auf die gleiche Weise wird auch über Annotation der aufzurufende Handler für eine Exception angegeben. Den Rest macht der Controller vollautomatisch. Die Annotations lesen wir über die Reflection-API aus.
Die Notwendigkeit selbst einen Controller vorzusehen entfällt somit und es bleiben in unserem Fall nur noch Business-Logik + Smarty als Template Engine.
Einen Fat Controller halte ich jedenfalls genau wie @stijnk für keine gute Idee – man verliert sehr schnell den Überblick.
Also meiner MEinung nach müsste das wie folgt aussehen:
Controller -> BaseModel (bereitet Daten auf) -> DataModel (holt Daten)
Ein „BaseModel“ kann natürlich auch auf mehrere DataModels zugreifen. So kann man auch problemlos DataModels austauschen, wenn diese z.B. bestimmte Interfaces implementieren – und schon habe ich das Problem gelöst. Der Controller deligiert am Ende nur noch die Anfrage, holt die Daten aus dem BaseModel und stellt sie dem View zur Verfügung.
also ich bin kein experte und arbeite mit MVC erst seit 6 monaten. dabei habe ich den folgenden holzworkflow entwickelt. alles was sich abstrahieren oder refaktorisieren (geiles wort) lässt pack ich in das model den rest in den controller.
Wenn es unterschiedliche Meinungen darüber gibt, ob die Logik im Model oder im Controller untergebracht werden sollte, ist das Pattern Design an dieser Stelle gescheitert. Also sollte man sich nicht fragen, was der bessere/schlechtere Weg ist, sondern das Pattern generell in Frage stellen, oder?
Nehmen wir z.B. mal Hybride Table_Abstract-Models in Zend. Ich persönlich halte das für einen Missbrauch, aber ohne Joins geht es eben nicht. Ein Model repräsentiert eine Tabelle, über ein setIntegrityCheck(false), auf Deutsch: „ach nimm dass doch bitte nicht so ernst!“, schaltet man die Idee hinter dem Pattern einfach aus. Das Pattern hat versagt und man muss es irgendwie umgehen. Eine Alternative ist mir nicht bekannt, gibt es eine?
Ich glaube, wenn man mehr und mehr Unit-Tests in seine Anwendung implementiert, dann stellt sich automatisch ein ausgewogenes Verhältnis der Verteilung der Business-Logik zwischen Controller und Model heraus. Allein schon deshalb, redundanten Code zu vermeiden und eine möglichst hohe Test-Coverage zu haben.
Ich überlege aber schon länger über die Sinnhaftigkeit von MVC bei modernen Web-Anwendungen. Allein schon, wenn man in Richtung Service-Programmierung (Schnittstellen) oder AJAX-Anwendungen schaut, stellt man fest, dass MVC einen gewissen, unnötigen Overhead mitbringt. Eventuell ist es auch endlich an der Zeit, Anwendungen mit zustands-orientierten Verbindungen zu erstellen. Mal schauen, wohin die Reise geht.
— Zitat: —
Ich glaube, wenn man mehr und mehr Unit-Tests in seine Anwendung implementiert, dann stellt sich automatisch ein ausgewogenes Verhältnis der Verteilung der Business-Logik zwischen Controller und Model heraus. Allein schon deshalb, redundanten Code zu vermeiden und eine möglichst hohe Test-Coverage zu haben.
—
Das ist auch wieder richtig, denn man muss wenn man Unit tests schön einsetzen will nun mal das ganze über die getestete Klasse lösen.
Aus meiner Erfahrung gibt ein paar einfache Hilfsmittel, um festzustellen, was Business Logik ist und wohin sie gehört.
Und in einem kleinen Gedankenbeispiel möchte ich auch mal auf einen weit verbreiteten Irrtum bezüglich Daten und ihrer Validität hinsichtlich der Business Logik hinweisen.
Vorab: so schwer ist es übrigens auch nicht, Business Logik zu definieren.
BL ist einfach alles, auf dem dein Business und dessen Erfolg basiert 😉
Das erste Hilfsmittel ist:
Stelle dir einen beliebigen Client (z.B. eine öffentliche API-Schnittstelle, ein MVC oder auch ein „Äääääpp“) zu deiner BL vor und schon hast du ein Mittel, mit dem du zumindest grob weißt, was deine BL ist und was nicht. Was extern benutzt und gemacht werden darf und was Teil deiner BL ist und eben nicht durch diese Clients erledigt werden kann. TDD hilft da schon sehr, wie von einigen erwähnt.
Aber bleiben wir bei dem Client- bzw. API-Ansatz.
Letztendlich definiert also deine API, was ein Client alles darf, kann und was er beachten, liefern oder nicht tun kann. Und dahinter sitzt die BL. Denn alles, was mit deiner BL arbeiten will, kommt um die API nicht herum.
Was davor passiert, ist nicht Business Logik, sondern Applikationslogik, und das kann dir (als BL-Entwickler) egal sein.
Die Klassiker sind beispielsweise Validierungen oder Authentifizierung, da gibt es häufig folgende Überlegungen:
Baue ich Formulare, will ich die Daten prüfen. Um Code-Duplikation zu vermeiden, denke ich mir schlaue Sachen aus.
Aber: eine API (also dahinter meine BL) prüft sowieso alles, was ihr geliefert wird.
Sie kann auch Methoden zur Prüfung von aussen zur Verfügung stellen. Aber hier wird es interessant: es sind IMMER Vorprüfungen und Annahmen, auf die ich mich aber niemals verlassen kann, dass sie auch bis zur BL durchkommen und das tun, was ich auch wollte.
Ich kann superintelligente Formulargeneratoren und Prüfbibliotheken im Client integrieren, mich 10x vergewissern, dass die geprüften Daten korrekt sind und doch wird die BL alles noch mal prüfen und genehmigen.
Oder authentifiziere ich einen Benutzer, dann darf er etwas Bestimmtes tun. Allerdings bringt mir das gar nichts, wenn meine API der Meinung ist, diese Person ist eine Sekunde später eine Persona non grata und aknn die geplante Aktion doch nicht durchführen.
Denn: Daten sind bereits in dem Moment veraltet, in dem sie erstellt werden!
Wo oder was letztenldich deine API ist, dafür gibt es nur die logische Definition und Abgrenzung: hier ist die Grenze nach außen zu allem, was mit meiner BL etwas tun will.
Es kann auch mehrere Abgrenzungen geben (und sollte es in der Tat auch), man nennt es besser Kontext für die BL.
Die Marketingabteilung kann z.B. ganz andere Anforderungen und Bedürnisse an die BL haben als der Versand. In ihrem Kontext erhalten sie das, was sie brauchen um ihren Job erfolgreich zu meistern.
So kann man sich auch mehrere Applikationen auf einer BL basierend vorstellen, jede für etwas anderes zuständig. So macht es eBAy z.B. mit seinen verschiedenen APIs für Käufer, Verkäufer oder Shopbetreibern.
Hoffe, ich habe ein paar Denkanstösse geliefert.
Cheers!
Eine interessante Frage in dem Zusammenhang ist es auch, ob man innerhalb eines „Haupt-MVC“ (nenne ich jetzt einfach mal so) nicht ggf. noch mehrere Mini-MVCs hat.
Man stelle sich vor, man hat für bestimmte Aufgaben auch spezielle Komponenten, die letztendlich die Hauptkomponente ergeben, aber nicht reine Business-Logik sind?!?
Beispielsweise weil ich bei einem meiner Module auch bereits eine standardmäßige Oberfläche modelliere (view) und das Modul zusätzlich angesteuert werden muss (controller), aber in eine große Anwendung modular eingesetzt werden muss.
Wie geht ihr mit sowas um, oder ist der Ansatz schon falsch soetwas überhaupt in Betracht zu ziehen?
Also meiner Meinung nach gehört in den Controller die gesamte Verarbeitung der Daten, also z.B. die Verarbeitung von Formulardaten und die anschließende Weiterleitung an das Model welche die Daten schließlich speichert.
Unter einer Businesslogik verstehe ich übrigens bisher noch gar nichts, da ich es bisher noch nicht verstanden habe, aber vielleicht ändert sich dies nach diesem Blogartikel ja irgendwann einmal;)
@Julian, ich verstehe nicht ganz was du meinst, könntest du es erläutern, vielleicht an einem Beispiel?
Sorry für den erneuten Post, aber ich bin auf Wikipedia im Artikel über MVC auf den folgenden Satz (okay, es sind zwei Sätze…) aufmerksam geworden:
„[…]Da das MVC-Muster in verschiedenen Programmiersprachen urealisiert werden muss, gibt es selbst keine genaue Definition über die Positionierung der Geschäftslogik innerhalb der MVC-Klassen. Diese kann je nach Anwendungsfall besser im Controller aufgehoben sein oder auch in das Modell verlagert werden.[…]“
Liebe grüße Paloran
@Paloran
Nehmen wir an, du baust ein Frontend für eBay.
Das FE basiert auf einem PHP MVC Framework und du machst lustige Sachen damit, rufst Daten ab, sortierst und filterst und bietest eine schickere UI, als sie eBay bereitstellt, um z.B. Gebote abzugeben.
Innerhalb dieser Applikation kannst du validieren und manipulieren so viel du willst, die gesamte Logik *deiner* Anwendung kannst du in Controller oder in dein Model packen.
Aber sobald du etwas wirklich zu und von eBay machen willst, entscheidest nicht du, deine Controller oder deine (Applikations-)Businesslogik darüber, ob es getan werden kann oder darf.
Sondern nur das Backend von eBay, das dir über seine API sagt, was Sache ist. Ebay verwaltet seine Business Logik selbst, also alle Regeln und Daten, die eBay für elementar für seinen Betrieb und Erfolg erachtet.
Du wirst wohl kaum eBay vorschreiben können, wie es bitte schön die Daten entgegen zu nehmen und zu speichern hat, die du in deinem Controller so mühsam verarbeitet hast. Stell dir vor, jede externe Anwendung der API könnte dies nach Belieben tun…
Das Ganze ist auf jede beliebige Applikation übertragbar.
Stell dir einfach vor, du bist Ebay und beliebige Entwickler und Anwender, entweder interne oder externe, wollen damit arbeiten. Dann weißt du, was *deine* elementare Businesslogik ist.
Nämlich das, worauf deine ganze Unternehmung beruht; das zu tun, was du tun musst und darüber die Kontrolle zu behalten. Und es niemandem zu ermöglichen es anders zu tun, wenn es um kritische Punkte geht.
Das Ganze kannst du auch in einem viel kleineren Scope betrachten, ohne API.
@Julian
Das meinte ich mit unterschiedlichem Kontext für verschiedene Anwendungen basierend auf einem Business Model.
Das was du ansprichst, setze ich in fast jeder Applikation um. Für manche Anwendungen benötigt man noch nicht einmal ein Model (*ein*, weil es mehrere geben kann) sondern vielleicht nur reines Reporting der Daten, die so aufbereitet sind, wie es der Kontext (lies: View) benötigt.
…
Im Prinzip ist der Vorteil des MVC-Hypes nichts anderes, als das viele Entwickler endlich erkennen, das man ernsthafte Anwendungen in logischen Schichten aufbauen muss. Da es aber dafür keine allgemein gültigen Regeln gibt, ist es so schwer, etwas allgemein gültiges und einfach verständliches Etwas zu präsentieren.
Wikipedia wird sowieso zu einer denkbar schlechten Quelle für echte Fakten…
Das Thema der Business Logik ist so komplex, da diese so unterschiedlich ist, so dass man die unterschiedlichen Standpunkte hier in der Diskussion als auch die Wikipedia-Definition nachvollziehen sollte. Hat man selbst an unterschiedlichen Projekten mit unterschiedlicher BL gearbeitet, hat man sicherlich schon selbst festgestellt, dass diese sich erheblich unterscheiden. Es gibt keine Allgemein-Lösung für dieses Thema.
Grundsätzlich bin ich aber ein Freund von Thin-Controllern, da es imo die Wartbarkeit & Wiederverwendbarkeit von Code erhöht. Zugleich bedeutet dies aber auch mehr Logik in der BL / Model wo man wieder ein sinnvolles Naming von Methoden haben muss. Dies ist bei komplexeren Sachen auch nicht wirklich trivial und kann auch zu Problemen führen (Methoden / Funktionalität werden mehrfach implementiert).
Bei komplexeren Anwendungen würde ich zurzeit wohl immer eine Service-Schnittschnelle zwischen Controller und Model implementieren. Dies gewährleistet mir die Kapselung der z.B. Aufbereitung von Daten. Denn eine API soll ja nicht nur insert, update, get können sondern manchmal müssen relationale Daten auch sinnvoll gruppiert werden. Und dies verschiedenartig. Da ist dann nur wieder die Frage: Darf der Controller auch direkt auf das Model zugreifen. Ich glaube das ist dann auch wieder eine Frage von der Komplexität des Systems, den wenn ein Service fast nur delegated, macht er auch nicht wirklich Sinn.
Und ich bin selbst noch ein bißchen am Überlegen ob man DTOs (http://en.wikipedia.org/wiki/Data_transfer_object) in PHP verwenden sollte. Nach anfänglicher Skepsis bin ich immer mehr davon überzeugt, da ich damit die Vorteile des Typehinting und der klaren Schnittschnellen nutzen kann. Zudem vermeide ich Methoden mit 5 und mehr Parametern.
@Ulf
Da dieses Thema so komplex ist, muss man sich halt bewusst sein, was für einen selbst seine BL ist und wo die klaren Grenzen von Applikation und Domain liegen. Und wenn man sich darüber im Klaren ist, ist vieles von der Architektur zumindest logisch klar. Dazwischen kann man dann Servicelayer en masse einbauen, aber die Grenzen sollten klar sein (Stichwort: Bounded Context).
„Denn eine API soll ja nicht nur insert, update, get können sondern manchmal müssen relationale Daten auch sinnvoll gruppiert werden. Und dies verschiedenartig.“
Yo, genau das meinte ich, wenn ich von Reporting rede. Dann gibt es eben eine reine Reporting-BL.
Auch wenn Daten „nur“ gezeigt werden sollen, spielt ja teilweise oder auch oft schon BL mit.
Denn welche Daten wie und wann angeschaut werden dürfen, bestimmt (zumindest bei komplexeren Anwendungen) auch die BL.
Deshalb hat eBay beispielweise auch eine Finding oder eine Best Match API.
Der Erfolg der REST-Apis basiert auf eben nur diesen wenigen Operationen.
@Ulf
„…
Und ich bin selbst noch ein bißchen am Überlegen ob man DTOs … in PHP verwenden sollte.“
DTOs sind sollten primär nicht ein technisches Implementationsdetail, sondern ein logisches sein.
Kurz gesagt braucht man und nützen DTOs vor allem, wenn man System- und Schnittstellengrenzen überschreitet.
Tut es deine Anwendung nicht, brauchst auch keine, zumindest nicht den Overhead, den sie mit sich bringen (können).
Und brauchst du Typehinting hat das primär nichts mit DTOs zu tun.
@Don
Die DTO verwende ich eben gerade wenn meine Applikation mit meiner BL kommuniziert. Da wird – zumindest in meinem Context – ein klare Schnittstelle überschritten. Das schreibst du ja auch selber. Und mit dem Typehinting meinte ich eben, dass ich diese DTO über den entsprechenden Konstruktur erzeugen kann (DI) und somit per se immer in einem gültigen Zustand sind. Und anstatt eben 10 Object per Parameter zu übergeben, übergebe ich ein Objekt mit 10 Properties.
Ansonsten muss man eben aufpassen, dass man die BL auch nicht over-engineered. Für eBay mag es total viel Sinn machen klare Schnittschnellen zwischen den Layern zu haben. Für kleinere bis mittelgroße Webseiten stellt sich diese Frage sicherlich vollkommen anders. Das hängt eben von den Bedürfnissen hab. Eine saubbere OO-BL-Logik kapselt mir auch die heute mittlerweile schrottige DB-Struktur in guter Weise, auch das kann ein sinnvoller Anwendungsfall sein.
@Ulf
Vielleicht kamen die Beispiele mit eBay als oversized rüber.
Aber ersetze eBay durch Client deines Backends, andere Abteilung, anderes System, anderer Entwickler oder anderes Ausgabegerät und du hast die gleichen Voraussetzungen.
Viel wichtiger aber als eine technische Schichtung ist die logische Definition von Zuständigkeiten und Grenzen.
Fragen wie folgende stellen sich häufig:
Ich brauche in meinem MVC Frontend für ein View bestimmte Daten, wo und wie bekomme ich die her?
Wann muss ich was speichern und wohin oder ist das gar nicht meine Baustelle?
Brauche ich eine Bestätigung für eine eben abgefeuerte Methode oder muss ich den Status woanders herbekommen? Interessiert mich überhaupt, ob es erfolgreich war?
usw, usw…
Solche Fragen tauchen auch in wesentlich kleineren und einfacherern Systemen auf. Das Auseinandersetzen damit und die Antworten darauf liefern oft schnell klare Hinweise, wie und wo BL eingebaut werden sollte oder muss.
Leicht bleibt es dennoch nicht…
@Don Danke, jetzt hab ich’s verstanden^^
Ich persönlich hab es nicht so mit strengen Docmen. Ja MVC ist gut und vor allem richtig, aber ich tendiere mehr zu einer MVSC Lösung, was wie bei vielen meiner Vorredner heist das ich meistens noch einen Servicelayer habe der dann sachen wie den DB-Layer, Kalkulatoren wie z.B. für MwSt. beinhaltet, etc..
Ich persönlich bin kein großer Fan von Heavy – Models, da sie in den meisten Fällen gerade in unserem Umfeld (web) zu performance Problemen führen, zu mal es aus meiner Sicht das Model nicht wissen sollte wo die Daten her kommen, und wie Werte berechnet werden, da es sonst exponential zur Größe der Applikation an gewicht zunimmt.
Ich mag allerdings auch keine Heavy-Controller, da sie in den allermeisten Fällen für redundanten Code sorgen, und so schnell sehr unübersichtlich werden. Aus meiner persönlichen Sicht ist der Controller schlicht der der weis wo die Daten herkommen und wie sie darzustellen sind, aber nicht der der die API dafür vorhält.
Diese API ist bei mir der Service-Layer der einfach verschiedene Klassen und APIs vorhält die diesen Job erledigen, und z.B. das Model mit Daten befüllen, Berechnungen durchführen, etc.
Durch diese Modularität ist dann eigentlich immer alles in verschiedenen Varianten zusammenbaubar, gerade in Verbindung mit Dependency Injections,
und z.B. ein Rechner der für Model a gebaut wurde kann auch für b, e & g genutzt werden.
Bin ich der einzige, der unter dem V des MVC was anderes versteht? Meinem Verständnis nach handelt es sich bei einer View nicht um die grafische Darstellung, sondern, wie das Wort eigentlich schon sagen sollte, die Sicht auf die Daten, und nicht die visuelle Darstellung der Daten. Einige werden jetzt vielleicht sagen: „Wie jetzt? Dat is doch dat selbe!“. Ich versuche es mal zu erklären, obwohl ich mir schon diverse Male daran die Zähne ausgebissen habe…
Ein konkretes Model beinhaltet sämtliche Daten, die logisch zu einem Objekt zusammengeführt wurden. Sagen wir mal, es handelt sich um eine Person mit den üblichen personenbezogenen Daten. Da eine Person mehrere Webseiten zugeordnet werden kann, speichert man diese natürlich nicht in der selben Tabelle wie die eindeutig zuweisbaren Daten, sondern in einer separaten Tabelle, in der die die jeweiligen Datensätze über die ID der Personen zugeordnet werden.
In dem Model werden die Daten aus den beiden Tabellen zu einem Objekt zusammengeführt. Nach außen stellt sich das also als eigenständiges Objekt dar, gespeichert werden die einzelnen Teile jedoch ganz anders.
Eine View definiert nun, wer in welcher Situation, welche Daten, wie zu sehen bekommt. Zugrunde liegt immer das selbe Model mit den selben Daten. Aber wie nun auf die Daten geschaut wird, dass ist immer unterschiedlich und wird durch den Controller gesteuert. Der weiß was angefragt wurde, holt sich das entsprechende Model mit seinen Daten und legt die View darüber. Damit ist dann MVC aber auch schon am Ende seiner Aufgaben. Wie den Benutzern nun etwas dargestellt wird, sei es via XML, HTML/CSS oder als formatierter Text auf einer Konsole, dass spielt sich nicht mehr im MVC ab. Und die sogenannte Business Logik passiert nicht innerhalb des MVC oder irgendwie über eine eigene Schicht dazwischen, sonder drumherum.
Ich hoffe, dass ich in etwas rüberbringen konnte, wie ich das MVC-Pattern immer verstanden habe.
Stimmt mir da jemand zu? Oder liege ich damit voll daneben?
Meiner Erfahrung nach wird MVC in der Webentwicklung ständig mit „schönen“ URIs der Form http://www.site.com/$conroller/$view/$id oder http://www.site.com/$conroller/$action/$id gleichgesetzt. Templates (einer Template-Engine o.Ä.) werden immer als View und ORMs als Models deklariert. Aber eigentlich hat das mit dem MVC doch nichts mehr zu tun. Präsentation von Daten ist eben nicht gleich Sicht auf die Daten. MVC muss schließlich auch nicht eine Datenbank im Backend haben. Oder kann man, wenn man seine Daten in Text- oder XML-Dateien Speichert plötzlich kein MVC mehr in seinen Applikationen verwenden?
Eins ist jedenfalls Fakt: MVC wird von SEHR vielen Entwicklern falsch verstanden. Zähle ich dazu? oO
Wieso meinst du, du wärst der Einzige, der unter einem View die Sicht (nicht das Aussehen) auf Daten versteht? Was anderes sage ich ja auch nicht.
Prinzipiell hast du mit allem Gesagtem recht. Aber auch du verwendest bei der Erklärung des Models das Wort „Tabelle“. Das ist IMHO ein großer Fehler aller derjenigen, die einen DB-Background (soll ich sagen laMp?) haben.
Wichtig ist folgendes:
Model = Verhalten und Status
View (und auch Controller) = (statische) Daten
Viel viel wichtiger als Haarspalterei über Views und Controller zu betreiben, ist es also sich den eigentlichen Aufgaben und guten Strukturierung seines Models bzw. der Domain und dem anderen Part, der Lieferung und Darstellung (des Reportings) der Daten zu widmen.
Für einen Anwendungsfall brauche ich ein Model, dass sich eben nur um diesen kümmert, seine eigenen Grenzen kennt und auch nichts von anderen Szenarien und Models weiß. Ein Warenkorb in einem Shop hat eine definierte Aufgabe, nämlich Waren einzusammeln.
Dass sein Inhalt auch versendet werden kann, weiß er gar nicht, das weiß aber mein Versandsystem, da sich der Daten des Warenkorbs bedient.
Artikel eines Shops wissen nichts von einem Kategoriesystem usw, usw.
Und um Daten, die zwar gewisse Beziehungen besitzen und auch einem View aggregiert geliefert werden müssen, herzubekommen, kann ich völlig unterschiedliche Arten der Persistenz haben.
Wie wäre es mit einer denormalisierten Tabelle (wenn wir schon bei DBs sind) pro View?
Wäre das nicht flott und elegant? Denn nur um Daten zu holen, wird keinerlei Logik benötigt, weder vom Model noch vom Controller. Die Daten sind zu just dem Zeitpunkt des Lesens bereits aufbereitet.
Ich brauche nicht zu checken, ob ein Artikel noch verfügbar ist, denn sonst wäre er nicht in diesem Reporting enthalten.
Du hast vollkommen recht, wenn du sagst, dass MVC heutzutage eigentlich nur zur Darstellung von schönen URIs genutzt wird. Zumindest habe ich die Hoffnung nicht aufgegeben, dass sich einige dadurch auch Gedanken über Layering der Applikation machen oder zumindest merken, dass es so etwas geben sollte.
Juchu! Jemand hat mich verstanden und stimmt mir zu! 😀 Danke dafür! 😉
@Don
Wenn ich ehrlich bin, dann habe ich mir nur den Artikel und die ersten Comments durchgelesen und dabei deine Comments überlesen. Mein Eintrag war nicht auf die Kommentare hier bezogen, sondern eher ein Klagelied an die Allgemeinheit, da ich mir echt mittlerweile den Mund (erfolglos und demnach auch sinnlos) fusselig geredet habe, um Kollegen und bekannten Entwicklern zu erklären, was hinter dem MVC-Pattern steht und wo es herkommt, um mal ein paar Dinge richtig zu rücken.
Beim Schreiben meines vorherigen Eintrags habe ich mir auch schon gedacht, dass die Verbindung von Model und Tabelle eher irreführend sein könnte. War wirklich als reines gängiges und verständliches Beispiel gedacht.
Also ich stimme Christian, teilweise auch zu.
Aber es gibt auch noch unterteilungen eines MVC wie man die Paradigma händelt. Deswegen lege ich euch ans Herz nochmal den Artikel zuvertiefen.
Es gibt auch noch CVM, VCM und MVC. Und hier redet Ihr eigendlich eher über ein CVM Model und nicht über ein reines MVC.
http://glossar.hs-augsburg.de/Model-View-Controller-Paradigma