[OOP] MVC-pattern
Op dit moment ben ik me een beetje aan het verdiepen in het MVC pattern en zodoende heb ik een 'overzichtje' gemaakt van de verschillende 'lagen'. Dit heb ik in een diagram gezet en ik vroeg me af of het zo goed was. Daarom wil ik graag jullie commentaar hebben op het volgende diagram:
http://www.agenebbes.nl/MVC-pattern.png
Opmerkingen en (opbouwende) kritiek zijn altijd welkom!
Groetjes!
Gewijzigd op 01/01/1970 01:00:00 door Tim
Tim schreef op 07.02.2009 16:50:
Heey allemaal,
Op dit moment ben ik me een beetje aan het verdiepen in het MVC pattern en zodoende heb ik een 'overzichtje' gemaakt van de verschillende 'lagen'. Dit heb ik in een diagram gezet en ik vroeg me af of het zo goed was. Daarom wil ik graag jullie commentaar hebben op het volgende diagram:
www.agenebbes.nl/MVC-pattern.doc
Opmerkingen en (opbouwende) kritiek zijn altijd welkom!
Groetjes!
Op dit moment ben ik me een beetje aan het verdiepen in het MVC pattern en zodoende heb ik een 'overzichtje' gemaakt van de verschillende 'lagen'. Dit heb ik in een diagram gezet en ik vroeg me af of het zo goed was. Daarom wil ik graag jullie commentaar hebben op het volgende diagram:
www.agenebbes.nl/MVC-pattern.doc
Opmerkingen en (opbouwende) kritiek zijn altijd welkom!
Groetjes!
Moet het per se in doc? Ik heb al zeven andere documenten open staan, daar raak ik al af en toe de weg in kwijt. Kan je het niet in een ander formaat doen? Of gewoon een webpagina? (Desnoods exporteer je het...)
Alleen de controller moet volgens mij nog ietsjes dikker. Het model doet slechts de business logic, niet alle logica. Topics ophalen, beslissen of een bepaalde post een geldige post is en eventueel of een bepaalde gebruiker het recht heeft een bepaalde post op te slaan zou ik onder het model laten vallen. Maar het inloggen, welke methods van het model aangeroepen moeten worden wanneer er een formuliertje is gepost, en welke views moeten worden gebruikt zou ik in de controller onderbrengen. Dat is meer specifiek voor de applicatie, en kan je waarschijnlijk niet hergebruiken in een andere applicatie.
Het model daarentegen zou zo algemeen moeten zijn dat iedere applicatie die die bepaalde data aanspreekt er gebruik van zou moeten kunnen maken. Of die applicatie nu een daemon, of een cli programmaatje, of een GTK programmaatje, een webservice of een website is. Als al die verschillende interfaces (applicaties is een beetje ambigu hier. Applicatie in de zin van programma, of in de zin van groep programma's en services die samen een bepaalde dataset beheren) gebruik kunnen maken van dezelfde implementantie van het model, dezelfde implementatie van je business logic... volgens mij is dat ideaal. Minder kans op fouten, minder dubbele code, business logic maar op 1 plek hoeven aanpassen en maar één implementatie ervan te hoeven testen.
Zo gezien heb je eigenlijk meer een scheiding tussen Model en Controller+View dan tussen de drie apart. Controller + View zorgt voor de weergave, en Model voor de data.
http://www.agenebbes.nl/MVC-pattern.png
Bedankt voor je opmerkingen!
Gewijzigd op 01/01/1970 01:00:00 door Tim
http://www.sitemasters.be/tutorials/4/1/509/nieuw/MVC_pattern_uitgelegd), dus zodoende...
Toch bedankt voor je opmerking!
De naam router had ik gekozen naar aanleiding van een 'tutorial' op sitemasters.be (Toch bedankt voor je opmerking!
Gewijzigd op 01/01/1970 01:00:00 door Tim
Bij mij is het zo dat iedere controller een view teruggeeft, en binnen de view kan je weer andere controllers uitvoeren en daarmee andere views binnen die view inladen. De meeste views die ik heb zijn dan ook maar kleine dingetjes, zoals een lijst van alle contactpersonen, een detail-overzicht van één contactpersoon.
Bij mij is het dus zo dat de controller en de view heen en weer met elkaar communiceren (al kan de view alleen maar een andere controller aanroepen, en ook die aanroep loopt dan weer via de frontcontroller, maar buiten de router om)
Maar het model kan niet bij de controller of de view, en is zich ook niet bewust van het bestaan van die twee. Ik denk dat het pijltje van View naar Model omgedraaid zou moeten worden. View doet wel aanroepen naar Model, maar andersom niet.
Vraagje: Waar zou jij de authentificatie (het inloggen en ingelogd blijven) en de autorisatie (gebruiker mag a wel, b niet) doen?
Waarschijnlijk een stomme / simpele vraag van mijn kant: Wat moet je nou eigenlijk aanroepen en doen in je index.php? Is dat dan alleen de frontend-controller / router en die regelt de rest van het werk? Of moet daar ook weer een algemene view aangeroepen worden die het weergeven van de specifieke views via een eventuele templateparser doet? Of kijk ik nou helemaal de verkeerde kant uit :-P ?
Gewijzigd op 01/01/1970 01:00:00 door Tim
Aan die laag kon je dan een gebruiker toekennen, en van ieder object dat het model in ging (om op te slaan) of uit kwam (wanneer het werd opgevraagd) werd gecontroleerd of de toegekende gebruiker het mocht lezen of wijzigen.
Het leuke was dat je hele specifieke regels aan deze laag kon toekennen. "Gebruiker a mag alleen objecten waarvan gebruiker_id gelijk is aan dat van zichzelf aanpassen." En omdat alle data via de model laag werd opgehaald, was het gewoon niet mogelijk om voorbij de autorisatie laag te komen. Ook leuk is dat je er in de rest van je controller en view niet meer naar om hoeft te kijken. Hoogstens een extra exception verwachten.
Probleem was dan weer bijvoorbeeld het inloggen zelf. Gasten mogen niet gebruiker-objecten bekijken, maar om in te loggen moet ik toch een gebruiker-object uit het model halen.
edit: Ik heb in mijn index.php de configuratie staan. Ik definieer de routes van de router, instantiëer de front-controller (die dan weer de router slikt als argument) en start de front-controller zodat die aan de router gaat vragen welke controller hij moet uitvoeren. Daarna geeft de front-controller uiteindelijk een view terug, en die "draw" ik dan waarna de HTML (of PDF, ligt eraan wat voor view er eigenlijk is teruggekomen) dus naar de gebruiker terug wordt gestuurd.
Je kan er nog voor kiezen om in je front-controller een extra view-laag te maken, waarbij de front-controller dus de view die hij terug krijgt van de controller die hij van de router moet uitvoeren binnenin zijn eigen view gaat tekenen. Die view van de front-controller kan dan bijvoorbeeld de layout-laag zijn. Hoofdnavigatie, breadcrumbs, footer, etc. Zo doe ik het zelf.
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Toch nog even een vraagje: Hoe gebruik je die view dan, instantieer je die in de controller, of geef je die al mee als argument?
Voordeel van deze aanpak is dat je allemaal kleine views kan maken voor bepaalde stukjes, en die dan weer overal kan hergebruiken. Het nadeel is dat het soms best chaotisch kan worden, en in de situatie waarin er een view is die niet samen gaat met de anderen.
Denk bijvoorbeeld een een view die met gd een grafiek tekent. Deze kan je niet mixen met views die HTML produceren. Op een of andere manier zal de grafiek-view omhoog in de hiërarchie van views en subviews bekend moeten maken dat hij alleen, zonder anderen om zich heen, weergegeven wil worden.
Gewoon een algemeen view-object in je applicatie hebben is ook niet vreemd. Je controller vertelt die view dan welk template hij in moet laden, welke variabelen hij eraan moet koppelen. Zend Framework onder andere doet het zo volgens mij. Het voordeel hierbij is de simpelheid, maar ik weet niet hoe het gaat wanneer je je applicatie zo maakt dat iedere controller z'n eigen kleine dingetje doet, en je meerdere controllers per pageview nodig hebt. Ik kan me voorstellen dat dat vrijwel onmogelijk wordt, omdat je de nauwe band tussen controller en view kwijt bent. Ik gebruik zelf altijd de eerste manier die ik had beschreven, en tot op heden is me dat redelijk goed bevallen (al is het niet ideaal)
Duidelijke uitleg, dank je! Ik zal ze snel allebei eens uit gaan proberen!
Mijn model vereist van ieder object dat het zichzelf geldig verklaart. Met andere woorden, voordat $object->save() doet wat het moet doen, roept het intern eerst $object->is_valid() aan, wat al de properties van het object naloopt, en al dan niet een array met foute properties en hun "meldingen" teruggeeft. Die array gebruik ik dan weer in m'n formulier om eventuele foutmeldingen weer te geven bij de velden die die properties verzorgen.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
try {
$object->property = $_POST['property'];
$object->save() {
// binnen save()
$object->_validate() -> array()
if array# > 0 then throw Exception(array)
else $object->_insert()
}
$view->success = true;
} catch(Exception $e) {
$view->error = $e;
}
$object->property = $_POST['property'];
$object->save() {
// binnen save()
$object->_validate() -> array()
if array# > 0 then throw Exception(array)
else $object->_insert()
}
$view->success = true;
} catch(Exception $e) {
$view->error = $e;
}
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -