LicenseSyndicate This BlogPlanet PHPDPC 2009 Day 1 - Ibuildings Blog
Friday, July 3. 2009 PHP with Oracle RAC - John Lim (PHP Everywhere - By John Lim) Friday, July 3. 2009 PHPNW: Site, Tickets and CfP - Lorna Mitchell Friday, July 3. 2009 nested trees in mysql - handy stored procedures. - Alan Knowles Thursday, July 2. 2009 Ready for PHP & MySQL Week at SitePoint? - SitePoint » PHP Thursday, July 2. 2009 Let me fire up the DeLorean - Adam Harvey Thursday, July 2. 2009 URL Shorteners - Florian Anderiasch Thursday, July 2. 2009 Status Codes for Web Services - Lorna Mitchell Thursday, July 2. 2009 OSS projects at Liip - Lukas Smith Thursday, July 2. 2009 Learn PHP The Easy Way - SitePoint » PHP Thursday, July 2. 2009 StatisticsLast entry: 2009-06-25 20:03
391 entries written
1287 comments have been made
|
Wednesday, December 3. 2008
Posted by Pádraic Brady
in PHP General, PHP Security, Zend Framework
Comments (47) Trackbacks (2) Defined tags for this entry: article, book, design patterns, model, mvc, php, php general, php security, rantings, symfony, xp programming, zend framework Related entries by tags: Wrox Press Respond to "The Art Of Deception Or Publishing PHP6 Books" The Art Of Deception Or Publishing PHP6 Books Volunteer Translators For Zend Framework: Surviving The Deep End Wanted Volunteer Technical Reviewers, Proofreaders and Contributors Wanted It's a bird, it's a plane...no!...it's some guy who vanished months ago! View as PDF: This entry | This month | Full blog The M in MVC: Why Models are Misunderstood and Unappreciated
I've been writing a book about the Zend Framework recently - I'm sure some of you have noticed
By the time I'd finished both chapters I realised I had spent a lot of space explaining the Model, most of it discussing how the Zend Framework does not actually give you one. In fact, no web application framework offers a complete Model (for reasons I'll explain later). However nearly all frameworks manage to avoid making that perfectly obvious. Instead they continually link the concept of a Model to the related, but not identical, concept of data access. This is quite misleading. This side of frameworks never gets a lot of attention. Yet it is a massive contributor to a whole class of problems in applications which attempt to utilise MVC by adopting web application frameworks. Further, I've always found myself better entertained by banging my head against brick walls than by trying to get the idea of a Model across to other developers. I'm not saying all developers are stupid or dumb, or that they don't get the concept in general, but all developers (PHP or not) don't quite link Models to the area of practice which justifies them - Object Oriented Programming principles. In this entry I explore Models in terms of how developers relate them to Controllers and Views in applications and note a few strategies you can employ when using proper Models. Models MisunderstoodThe Model can be explained a few ways. In fact, you can write entire books about just the Model and many people have! The Model generally has two roles broadly defined: 1. The Model is responsible for maintaining state between HTTP requests. Basically any data whether on a database, in a file, stored in the Session, or cached inside APC must be preserved between requests and thus forms part of the state of the application at the time the last request was completed. So always remember that the Model is not just the database. Even the data you get from web services can be expressed as a Model! Yes, even Atom feeds! Frameworks which rattle off introductions to the Model, almost never explain this upfront which only exacerbates misunderstandings. Here's an example, while it's called Zend_Feed_Reader that new component which I'm developing is actually a Model. It reads feeds, manipulates them, interprets data, adds restrictions and rules, and generally creates a usable representation of the underlying data. Without it, you have Zend_Feed (the current top dog in feed reading) which requires lots of additional work to develop it into a viable Model. In other words, where Zend_Feed_Reader is a partial Model, Zend_Feed is pure data access. 2. The Model incorporates all the rules, restraints and behaviour governing and utilising this information. For example, if you wrote business logic for an Order Model in an inventory management application, company internal controls could dictate that purchase orders be subject to a single cash purchase limit of €500. Purchases over €500 would need to be considered illegal actions by your Order Model (unless perhaps authorised by someone with elevated authority). The Model should be capable of enforcing this. This makes incredible sense if you examine the meaning of the word "model". We have climate models in climatology, for example, which define the data, run processes, assume behaviours and calculate probable outcomes from these. The M in MVC is called a Model for a reason. The Model doesn't just represent mere data, it represents the entire system for which that data is useful. Of course any system can be complex enough to require multiple interacting Models but you get the idea. If you read these two points, you may realise something startling. With the exception of the UI, most of any application can be expressed within Models. It's the Model that centers on all the data and underlying behaviour of that data, and sometimes even how to display that data. It's the Model which can understand, interpret and represent that data and provide it with meaningful uses. In Programming, Fat Models Are Preferable To Size Zero ModelsJamis Buck (the author of Capistrano now employed by 37signals) once wrote about a concept called "Skinny Controller, Fat Model" (our own Chris Hartjes wrote a blog entry on the same topic). I've always liked the simplicity of this concept since it illustrates a key facet of MVC. In this concept, it is considered best practice to maintain application logic (like our business logic from above) within the Model as much as possible and not in either of the View or Controller. The View should only be concerned with generating and presenting a UI so users can communicate intent to the Model. Controllers are the orchestrators who translate UI inputs into actions on the Model and pass back output from whatever View has been made aware of the Model(s) its presenting. Controllers must define application behaviour only in the sense that they map user input onto calls in Models, but beyond that role it should be clear all other application logic is contained within the Model. Controllers are lowly creatures with minimal code who just set the stage and let things work in an organised fashion. PHP developers, by and large, don't fully understand what a Model is. Many see the Model as a fancy term for database access and others equate it with various design patterns for database access like Active Record, Data Mapper and Table Data Gateway. This is the misconception frameworks often promote, unintentionally I'm sure, with abandon. By not fully comprehending what a Model is, why it's such a great idea, and how one should be developed and deployed, developers unintentionally kick themselves into a dark path which leads into what can only be described as poor practice. Here's a thought exercise to get you thinking. Imagine you just built the finest web application imaginable using the Zend Framework. Your client is incredibly impressed and their praise (and fees) are most welcome. Unfortunately they forgot to mention that their new CTO is insisting all new applications utilise Symfony and they'll offer you a nice shiny cheque if you'll convert your application over for them. The question is - how easy will that be? Think about it for a moment... If you have your application logic bound up in the Model - then celebrate. Symfony, like many (but not all) frameworks, accepts Models regardless of what they are written on top of. You can port your Model, its unit tests, and its supporting classes with little to no modification into Symfony. If you stuck it all into Controllers, start feeling worried. Do you think Symfony can use Zend Framework controllers? Do you think those functional tests using the Zend Framework PHPUnit plugin will magically keep work? Ta-da. That's why Controllers are not a substitute for Models. They have minimal reuse. Unappreciated, Underestimated, Unloved: Depressed ModelsSince developers often demote Models to mere database access as supplied by default in 99.9% of frameworks, it's no surprise they are unimpressed by the theoretical ideals attached to them. By focusing and obsessing about data access, developers completely miss one important factor: Models are classes which are not coupled to the underlying framework. They have no expensive setup - you simply instantiate and use them. Maybe we can't blame the average developer though. Web applications do have a certain behavioural pattern which makes that crooked path more attractive - lots of them are just big data readers. If there is little data manipulation, only data reading, then any Model will look similar to plain old reliable data access. It's unfortunate in a way, but don't let the simplicity of reading data fool you. Not all applications are going to be read only - some will no doubt have something to do with that data besides displaying it raw and unchanged from the database Models are the underdog in PHP. Views have captured everyone's imagination since the advent of Smarty and it's brethren. Controllers make almost as much sense since they read from databases, and pass any retrieved data into templates (a common interpretation of VC). Yep - Controllers are the logical evolution of the mentally ingrained Page Controller approach every PHP developer and their dog has used since PHP3. At least - that's the obvious conclusion for most. We'll bust the "Controller = Page Controller" myth later. Models though. Models don't have the same ideological attraction or similarity to old habits which is why people pass them over and use "data access" as the underlying meaning. You know, like references in PHP pointing to the same value in memory? But wait...developers do write functioning applications! So if they are not using Models brimming with application logic, what the hell are they using?! Fat Stupid Ugly Controllers: SUC It UpSince Models are so lame to developers, they invented a new concept. Fat Stupid Ugly Controllers (FSUC). I put the SUC in FSUC on purpose. It seemed funny at 10pm after a few drinks The average FSUC reads data from databases (using a data abstraction layer developers like to pretend is a Model), or manipulates, validates and writes it, and passes other data to the View for rendering. It's incredibly popular. I'd say most people using frameworks create them as naturally as they ever did Page Controllers. They are popular because developers have figured out that they can treat Controllers almost like Page Controllers which requires little change from their historical practice using single PHP files for every application "page". Notice something odd? The FSUC is performing all sorts of actions on data. Why? Because without a Model, all the application logic must go into the Controller, which makes the Controller - a type of Mutated Model! I use "Mutated" with reason. FSUCs are big, unwieldy, ugly looking and definitely fat. The quasi programming term that applies is "bloated". They perform roles they were never intended for. They are a complete reversal of everything you are taught to do in applying Object Oriented Programming principles. They are also pointless! Developers, for some mysterious reason, seem to prefer FSUCs to Models despite the fact those Controllers really are just Mutated Models. Remember our thought exercise? If you put everything into Controllers, you will never be able to efficiently migrate an application to another framework. This type of tight coupling is the kind of thing Kent Beck fans are supposed to identify as a "code smell" in Refactoring. But it's not the only smelly artifact of FSUCs. FSUCs are big, with massive methods, multiple roles (one per method usually), massively duplicated code, lacking refactored external extracted classes and...they are a nightmare to test. With many frameworks, you can't even properly apply Test-Driven Design (TDD) on Controllers without writing custom plugins and being forced to manage request objects, sessions, cookies, and Front Controller resets. Even then you have to test the View it creates because Controllers don't have output independent of Views! So keep asking those questions! How do you test a Controller? How do you refactor a Controller? How do you limit the role of a Controller? What is the performance of a Controller? Can I instantiate a Controller outside the application? Can I chain multiple Controllers in a single process and still remain sane? Why am I not just using simpler independent classes and calling them Models? Am I considering these questions at all? Models Are Inevitable (Like Taxes And Death)FSUCs make the classic mistake. By assuming a Model is a silly idea and plain old data access works best, developers unwittingly stick application logic into Controllers. Yes - congratulations. You just created a Model, a butt ugly Mutated Model you insist is a Controller. But this pretend Controller isn't easily portable, testable, maintainable, or refactorable (assuming refactorable is a real word...might be!). The nature of Controllers is such that they are tightly coupled to the underlying framework. You can only make a Controller execute by initialising the entire framework's MVC stack (potentially dozens of other class dependencies!). Either way you try to go - you end up writing the application's logic somewhere. Putting it in a Model, away from the Controller, simply creates lots of classes which are independent of the framework you're using. Now you can test those buggers all day using PHPUnit without ever seeing a Controller or View in sight or having to torture yourself silly trying to make the entire framework stack reset after every test, and by seeing them as real classes with specific roles you can also put yourself in the right mindset to apply proper refactoring and create real maintainable code without duplicating code across multiple classes. Models are inevitable. One can call that FSUC a Controller, but it's really a Controller+Model - an incredibly inefficient Model replacement. Someone just shuffled the source code around while laughing at all the fools talking nonsense about the importance of good independent domain models. Well, laugh back. They're the ones who have to test and maintain their mess. This is really where most web application frameworks let their users down. They are surrounded by a lot of marketing garbage which subtly suggests that they offer a full Model. Have you ever seen a framework say anything different in an obvious way? Afterall, they are MVC frameworks. If they are forced to admit the M is something developers will have to create themselves, it might look bad. So they bury the truth in the documentation scattered throughout their data access feature, if they mention it at all. In reality, they only offer data access classes - the real Model is something that's application specific and must be developed independently by the developer after discussion with clients (you can pick your buzzword practice to achieve that - I'm into eXtreme Programming (XP) personally). It needs to be tested, validated, updated and you face the same probability of failure/success regardless of what framework you use. A bad application in Rails will still make a bad application on Code Igniter. Controllers Should Not Guard DataThe other facet of this lack of Model consideration is that when developers are convinced that Models should be used minimally, it reinforces a reliance on Controllers to take on a new role as Data Gatekeepers (a large reason why they mutate into FSUCs). Want some more opinionated fuel to fire up everyone disagreeing with me right now? A while back when I was writing the proposal (Zend_View Enhanced) that would eventually be adopted into the Zend Framework to create an object oriented approach to generating complex Views, I started moaning about Controllers being used as the sole method of getting data from Models into Views. My own thoughts were that Views could skip the middleman and instead use View Helpers to read data from Models more directly. This would support an architecture where in many read-only page requests, your Controller Action would be...empty. Devoid of all code. Nada. In my mind, the best Controller is a Controller which doesn't need to exist I was immediately treated to a mass of resistance. Few people seemed to understand that an empty Controller, with all Model interaction extracted into simple reusable View Helpers, would reduce code duplication in Controllers (lots of code duplication!) and avoid the necessity of chaining Controller Actions. Instead there was lots of muted puzzled expressions. Most people simply assumed that MVC worked as follows: requests go to Controllers, Controllers get data from Model, Controller gives Model data to View, Controller renders View. In other words: Controller, Controller, Controller, Controller. At one point I remarked that the entire community was obsessed with Controllers Note: Not to sound like a complete pratt - some people did get the idea None of the objections really caught on that this was an old idea. Java coined the term View Helper years ago as a design pattern in J2EE showing how View Helpers could assist Views in accessing Models (only on a read only basis since any writing should go through a Controller!) without the intermediary Controller. In MVC, there is every indication that Views should know about the Models they are presenting. Not just whatever arrays we decide to spoon feed them from Controllers. So go further! How many Views only need one Model? A lot of my Views use several Models, with highly repetitive Model calls. A View Helper is a single class - but adding these repetitive calls to Controllers, means you need to duplicate calls into multiple methods! One crazy solution created to outwit the View Helper, is often to reimagine Controller Actions as reusable commands. Whenever a View needs several Models, you just call several Controllers in sequence. This concept is something I call Controller Chaining - its premise is to create supporting code to make reusing Controllers possible. You can translate that as: reusing every class needed to execute a single Controller Action. Remember - you can't use any Controller without initialising the entire framework Models are Classes, Controllers are ProcessesI'm running thin on quickie ideas, but I mentioned Controller Chaining and it bears further examination. Chaining is used either to access multiple Models, or to merge the results of multiple Views, or both. Usually both - Controllers nearly always access Models and pass data into Views when you are not using View Helpers to shortcut the process. Imagine you create three Controllers, each of which generates a View. To build some new web page, you need to merge all three Views into a single template page (or Layout). This is accomplished by telling Zend_Layout (or some other alternative solution for aggregating Views into common layouts/segments) to call all three Controllers sequentially. Now consider what is happening - three Controllers means you are making three dispatches into the MVC stack. Depending on the application this can pose a significant performance cost. Symfony, to illustrate how real that cost can be, uses "Components" as a specialised Controller type just to offset this performance hit but the Zend Framework has no equivalent. Rails has a similar idea which is rife with complaints about performance hits. The prevailing wisdom across frameworks is that using multiple full Controllers is horribly inefficient and a last resort when no other reuse strategy is available. I'll say it again - Controller Chaining is a code smell. It's inefficient, clunky, and usually unnecessary. The alternative is obviously to just use View Partials (template snippets capable of being merged into a single parent View) which can directly interact with Models using View Helpers. Skip the Controllers entirely - afterall they have no application logic unless translating user input into relevant Model calls (unless FSUCs This highlights that Models are just a collection of loosely coupled classes. You can instantiate and call them from anywhere - other Models, Controllers and even Views! A Controller, on the other hand, is a tightly integrated cog in the machinery of a whole process. You can't reuse a Controller without also dragging in the entire process of setting up request objects, dispatching, applying action helpers, initiating the View, and handling returning response objects. It's expensive and clumsy in comparison. Signing OffThere is a fast paced urgency to this article you'll have noticed. I'm a self confessed nut about applying the principles of elegant Object Oriented Programming to MVC frameworks. It's why I went all out with Zend_View Enhanced and saw it adopted, debated, and adapted with great success, into the Zend Framework. A lot of that is owing to Matthew Weier O'Phinney and Ralph Schindler who joined that parade. If we lose sight of simple OOP practice and principles, and get lost in trying to fight MVC into submission, the plot ss quickly lost. The MVC is a great architectural pattern - but at the end of the day our MVC interpretations and ingrained beliefs are all subservient to OOP principles. If we forget that, we do Bad Things™. Hopefully this torrent of ideas about the Model in Model-View-Controller is somewhat enlightening and makes you think. Thinking should be your goal - question everything, and rebel when you feel something going wrong. If we run around on blind faith than we deserve everything coming to us Trackbacks
Food for thought: utilizing models in MVC
“What is a model” and “Is Zend_Db_Table a model” seem to be asked once in a while on #zftalk. Frameworks say they have a full model available, thus they are MVC frameworks. ORM libraries say they generate models. It seems the A...
Weblog: CodeUtopia
Tracked: Dec 06, 11:15
Das M im MVC-Entwurfsmuster
Ich habe vor einiger Zeit einmal über die nicht vorhandene Komponente Zend_Model geschrieben und dort den Stand der Dinge aus meiner Sicht zusammen gefasst. Das Kapitel zum Thema Models in meinem Zend Framework Buch ist bereits fast 20 Seiten lang und...
Weblog: Ralfs Zend Framework und PHP Blog
Tracked: Dec 09, 20:14 Comments
Display comments as
(Linear | Threaded)
I argued strongly against the action() view helper for many of the very reasons you point out -- it reinforces using the controller as a model, which is a bad idea. When performance benchmarking and profiling for 1.7.0, I confirmed my suspicions: calling action() is just really, really expensive. In fact, another dispatch loop iteration is generally cheaper by comparison. I call it out in the performance appendix as well.
I think one way to demonstrate how poor it is to push logic into the controllers is to have someone refactor an application to make heavy use of XHR calls. You quickly learn with a good, dynamic UI that you want those responses returning as fast as possible -- and going through a full MVC layer is often too expensive. If you can't create a service layer for your XHR requests easily, you've likely delegated too much to your controller. (I did this recently, and was rewarded by my fat models with a relatively simple, painless task. Nice article -- keep preaching it!
I shall preach, and preach, and preach, and...
Hopefully someone will listen
Heh, I'm listening allright. This post, and Doctrine, are reason for me to be doing some heavy refactoring soon (that's going to be some work, but well...).
I'm hoping it will increase performance. However, I'll still (I suppose) will have a lot of controller chaining, even though those controllers will be almost empty. I'm not quite sure whether I'll need to stick to using Zend_Layout or start with the view and dynamically instantiate response segments into a view (which would be a lot of work). Anyway, thanks for the post.
By the way, this post didn't show up in Google Reader...
Make sure you're subscribed to the main feed. At the moment I know mobile browsers (and some auto browsers) have issues with the blog. Serendipity's been having issues for a few months on this site and there was a recent DNS switch might be confusing it.
Hmm, I am subscribed to the main feed (or at least, the one linked to in the address bar), and when I view the feed, the entry's there. However, once you add it to Google Reader it's gone... :S
As a former procedural programmer who is still basking in his recent OOP/MVC epiphany, I have been trying to decide on a best-practice for where to place most of my application logic, and I think the "fat model/skinny controller" concept makes perfect sense, despite the fact that it goes against a lot of other things that I've read on the matter.
Just a couple of questions - 1) You used the example of porting an existing ZF application to another framework and that it would be a lot easier if most of the application logic was in Models because other frameworks obviously can't use ZF-specific classes, but... don't Model classes use ZF-specific classes as well? 2) With regards to Views directly accessing Models via View Helpers, could you give an example (with or without code)? Like most other people, I always thought that Views should be aware of Models as little as possible, so I'm just curious as to what sort of situations it's acceptable. Thanks for a great read - loving this blog more and more each day!!
Just to note that the "lot of other things that I've read on the matter" should be taken with a pinch of salt
ZF Models might use Zend_Db, or Doctrine, or Propel, or [insert random data access solution]. There's no hard and fast rule you must use Zend_Db. Even if you have, it's one of those times you need to fight back against my imaginary CTO. Zend_Db can exist outside the framework (benefits of loose coupled "use at will" architecture) and you might be able to escape transferring everything to another data access solution. Do note, it's a data access solution - the overlaid Model still wouldn't change even if you were forced to swap out the underlying access component and create an Adapter API to make it fit the replacement's API quirks. Nowhere in MVC are Views forbidden to know about Models Glad you enjoyed the read
Thanks for the article, it has helped me understand the model better. I have been utilized this approach somewhat, in that I do all of my db data finessing in the db model before sending it to the View (via the controller). I definitely see the advantage of minimizing the amount of manipulation that the controller does.
From what I understand, though, you are saying that you want to create models that are free from the framework? Is it bad for a framework to provide a base model class that can be extended that provides basic access to the framework registry/variables? Or is it better to develop your own models that only get data that is sent to it (via a controller or view)? Thanks!
Using framework base classes is fine. My definition of framework independent really applies to the Controller architecture (which tends to be hard coupled to everything in the framework).
My article merely highlights that these "base models" are really just data access layers - the actual Model is what you build on top of them. It's characterised by non-framework bound Unit Tests, implementing rules and roles which don't require Controller inputs in order to perform. That's why it's usually so easily portable to other frameworks (within the same programming language obviously The main barrier here is really a mindset. If you look at Models as just "accessing data" you'll only see application logic in terms of getting data from a database. If you view Models as all the logic organising and managing that data, you suddenly realise the Controller (perhaps in other apps) doesn't need to be huge. It only needs to do just enough to get your Models working, and your Views prepped for rendering.
That makes a lot of sense. Thanks Padraic! One thing I love about the PHP community is how much I can learn by wonderful articles such as this one.
Thanks for the straight up, unapologetic explanation (rant?
I partially got it (I still partially get it, but it's closer) but failed to convince the team that it was the right way to go. As a result, FSUCs and duplicate code reign... maybe next time.
Although i'm not a native english speaker, its always an absolute pleasure and inspiration to read your articles...thanks a lot and keep up the good work!
Refactorable is a real word, and You area a real programmer!
More, more...!
This kind of stuff is exactly why people who know what they're doing should be blogging =)
Anyway, the thing with these "doing A,X,C is wrong, you should do A,B,C instead" posts tends to be that it can be difficult to apply the theory to practice - especially if you don't have much experience. So in that regard, it would be good to have examples to clarify your thoughts. Nevertheless, at least I got a lot of ideas on how to make use of the things you talk about in practice. I've been doing thin models myself, but mostly because it's a lot easier and faster than trying to think of a better way. I've been thinking of picking up Java, as from what it seems, there's a lot of this "best practice" stuff there, which could be applied elsewhere.
Part of the reason for the Java oriented thinking people keep meeting is that most of the people behind ideas like refactoring, design patterns and such come from Java/Smalltalk backgrounds. Unfortunately, penetration into PHP has been slow since a lot of those thinkers are still Java, or now squat around Ruby and Python. We should campaign for more PHP developers to blog about best practices...
Yet again I feel the urge to express my love for your articles
While reading I was thinking how you would deal with the very common situation that a certain environment variable leads to instantiation of a certain model. Consider an url like mysite.com/blog/45 1) Would you instantiate a BlogPost with id 45 in your controller, or would you do this inside a view(-helper)? 2) If you instantiate it in a view(-helper), would you explicitly pass the the _get parameter as a variable in your view from your controller, or would you treat it as a global identifier which is readily available to your view?
great posting Padraic. Personally I can only say that even programmers that come from Java background do find the FSUC a perfect way to go. It is like the dark side: The easy and fast way but ultimately evil.
Regarding controller not being good to test, you should really take a look at ezcMvcTools in the newest ezComponents Beta. It perfectly separates view and controllers through a result object that is handed from the one to the other without them knowing that they exist. Its default implementation also (almost) completly prevents controller chaining.
Nice post
View should know Model. That's why MVC pull works
What about using a mediator who can retrieve data from models and handle the view ?
This is the way they do in PureMVC : http://npacemo.com/wordpress/wp-content/uploads/2008/06/puremvc-conceptual-diagram.jpg
I think the fact is that we can have only two of the MVC parts. I mean if the best think is to put everithig is possibile in the model and then the view can access/know the model so the paradigm is MV
@Skyblaze
Without controller how can you handle the request and select corresponding views? Let do a research on MVC pull then you know why it works
MV would be brilliant
Controller's are necessary, but so long as we keep the roles of Model and View tight and leak free, Controllers become the least of your worries since they contain so little of what the application is about. It's a love/hate feeling
Once again an outstanding post.
I am sure there are a few readers who would appreciate a follow up post with a simple example showing the use of Zend_Form pushing the validation rules into the Model (Skinny Controller/Fat Model). I am also scouring the net for the following example, to speed up Zend Framework I want to use nginx rewrite to eliminate Zend_Route, eliminate the controller, simply displaying View and accessing the Model with View Helpers. Thanks..
I agree with most of your statements. Anyway, backing them with some code would ease understanding. That's something I often miss from architecture and software-related posts... show me the code!
I agree completely. Some hard examples would be nice, unfortunately it would also expand the article beyond the 4000 word mark
There are dozens of book out there however, showing how Models can be developed, planned, changed, and tested. Domain Driven Design is one concept everyone could briefly research in the future. It really emphasises how important Models are over the supporting architecture (Controllers/Views) which merely act to present them to the user for interaction. Models are essential and core. VC can be swapped around at will so long as the Model is suitably independent.
Should the model be responsible for validating POST fields or should that logic reside in the controller?
Yes that's a great question. That's also what's my question #7 is about: do we consider get/post params as user input that needs to be processed in the controller and then be passed on? It sounds nice, but it will hinder portability. :+
Everywhere you go, that question will torture all programmers
I'd argue that if the POST data is sufficiently specific to a Model, then the Controller should take a hint and defer validation to the expertise of the Model involved. Something Jani (see this entry's trackbacks above) noted was that this also raised the question of whether Views could be made aware of Request data and delegate validation to Models (i.e. skip the Controller) as part of their anti-Controller activities. I'd say either is acceptable, indeed there's no reason to become polarised and obsessed with only one (use when appropriate) but always be certain the View is not doing so much that it begins taking over the Controller role. There's a balance in these things, and it's not easy to see that always. Keep an open mind, trust your sense of aesthetics, and be wary. Personally, I always measure how much work is needed to translate a user input to a call on a Model. If it's a lot, let the Controller do the translation task (that's its raison d'etre!), if it's a stupidly simple task of passing the raw input into a Model (no intermediary filtering/shuffling/normalisation) then perhaps the View would make a nice logical home since then it's basically acting as a simple proxy. Keep thinking
I wanted to point to this article: http://karwin.blogspot.com/2008/05/activerecord-does-not-suck.html
Bill Karwin states that the relationship between the model and the data access layer (Zend_Db) should be a HAS-A and not an IS-A. Do you agree? Ever since I read the article I made my Models independent from the DAL. This made refactoring efforts (ripping out the data access library and replacing it with another) and testability much easier.
Absolutely - Models are by and large non data access classes which just happen to use data access functionality. You could just as easily have a Model using a web service api, or an Atom parser, or a YAML reader/writer, or....
Since the backend data access functionality should be largely anonymous - the Model would only be aware of its API not it's underlying functionality (that just pollutes the Model with unnecessary functions), the simplest means of inclusion is by composition (has-a) rather than by inheritance (is-a). This means you can swap Zend_Db with Doctrine and in theory the Model remains unchanged.
Hey,
I like the subject. It has bothered me also. When I saw this link yesterday evening in the Zend Mailing list i printed the article straight away. I unfortunately also use FSUC's but that was because of 2 things: 1. A bad understandign of what the model really is 2. A lack of a proper design. You also pointed out in your article that a lot of people think that the model is just database I/O. But I think I know where this comes from and I have the same problem myself. Let me explain: Let's say I have a class Car which deals with the properties of one single car. 1.Sometimes i would like to retrieve a list of cars which is saved in my db. So it's much easier to do someting like "SELECT * from cars". 2.Let's say I am dealing now in my application with 1 single car. If i want to change the color of the car i would straight away update this in the db. Why boter, changing the color property in my class wich on it turn will do the update in the DB. So for this people (including myself) will just end up writing only the queries and skipping the objects in the model. Its a lack of good understanding and practce
You hit the nail on the head
What you could ask is what happens when the Car is being updated several times for colour, engine block, and transmission. The Engine could be another Model completely. Whenever the Model changes, do you immediately run SQL to update, or would you defer any updates until the Model is completely finalised? How do you manage this if the Car itself is being updated by several other processes which are optional (it's impossible to know who would be last in the update chain)? This experiment generally leads to the idea of deferred updates - the Model has no real update() method, instead it might have a destruct method which updates at the last minute. Or another strategy is to let an external object which tracks all Models using observation (whether they are "clean" (unchanged) or "dirty" (changed) and orders each to call update() on it's data access object if appropriate). It's a different way of thinking for sure
A lot of great information, thanks! Looking forward to the book. Any eta on it?
The book is quite a fluid effort. I'll start releasing chapters in January to a few formats but I'm not maintaining a strict schedule (it has to happen around my day job
Great article. Really made me see what models truly are.
Thanks
Padraic, great article!
I'm thinking a lot about this, a i have some questions 1. You said that Model is something that's application specific, but can we say that validators, action helpers, filters, decorators, forms, extended framework classes are part of model? In your tutorial you placed this files to library/ZFBlog, is ZFBlog - model? If it is model, why it doesn't placed in application/models. If it is not model, can we use for example our forms in other applications i think not, they are also part of application, and some specific to application validators etc. Where is border between application files and library? 2. You suggest to call model from View with help of View Helpers, it's good idea for easy helpers, for example last news ets. But if we have data that depends from some parameters in url, For example in index page we must show last 10 news, and in some /page/archive we must show last 20 news, in model we have metod like getLastNews($count), how we can pass parameter to helper, from view? ($this->helperNews(10)) or we must work with request object in helper? 3.My friend instead using of view helpers use plugin, in this plugin he set layout segments, for example lastNews, favourit news, his plugin is somethin like big view helper, how do you think, that's good idea or not? and last question, Matthew suggest to use such helpers http://framework.zend.com/manual/en/performance.view.html#performance.view.action.model, but this is php+html pasta, may be better render some view script in helper and pass data to him. Sorry for my english
Great article, looking forward to read your book. I agree too that ZF is missing a "component" concept like in symfony.
Will searching more about "fat models, skinny controllers" on google, I found those funny videos about MVC http://nagasakti.mervpolis.com/roller/keralunub/entry/mvc_public_service_announcement_complete
If I instantiate a model from a controller, how do I then access this class from inside a view without passing it to the view via the controller?
Can you demonstrate how you'd do this using a view helper? It'd really help me very much as there are so many conflicting methods. Thanks! Jonathan.
There's no other easy way other than assignment from the Controller. Bypassing the Controller is only an option if instantiating the Model in the Controller is not needed or avoidable. If you can't avoid it, might as well assign from there rather than adding another layer.
Thanks for clearing that up, it helps a lot! Great site by the way, it has helped me immensely when learning MVC with ZF. keep up the good work
When will come out the new full updated tutorial/book?
Great article, very good explanation of a common misconception!
Padraic,
this is a marvelous article regarding the important role of Model. Thank you for sharing all this info. I am wondering if there is a working sample project based on these principles, that I could somehow access. The sample can be as simple as an online store. The user a. browses products b. searches for a product c. views the product details d. places an order e. receives purchase confirmation. In case something like this does not exist, I would be more than happy to implement something like this, if someone with your knowledge could provide the right guidance, answers and review of the code being written. Best, Dimitris Software Developer
Let me know if I get this right. Since models must contain behaviour and not data we should have something like:
[code] $user->setFullName('John Doe'); # instead of $user->fullName = 'John Doe'; [/code] The question remains who does the save of the $user after the changes? Do we have $user->save() or $admin->save($user) where $admin is a model of the the logged in user or $domain->save($user) where $domain is the application model?
Thanks for this refreshing article. It has helped me move a step further in my understanding of MVC.
I have recently read the DDD book (Domain Driven Design,by Eric Evans) and have since been struggling to see how Zend Framework ''Modules'' fit into DDD Modules. DDD proposes that the modules be seperated by concerns (e.g (CRM) Customer Relationship Manager Module, Reporting Module, Billing Module ). Then, ZF seems to have the modules so closely tied with the routing and the audienece (for example i am forever seeing examples of Admin Module, Login Module etc). I was stuck beleiving that every model needs a controller. I had been put off from organising the ZF application architecture into DDD-leaning modules for fear of someone accessing it via a typo in the ZF router class...e.g example.com/CRMModule/ShowAllCustomersPersonalDetails I was stuck in that mindset cos i had imagined alot of controller chaining going on because in some way i beleived that one has to 'access a particular module's model via its controller'. I think i learned from your article that organsing the modules according to DDD-leaning principals is OK. Instead of chaining the frontend ZF module controllers, I suppose will start to define the interface to each module's model using some kind of Command Interface that sits at the edge of the model (using a Command Pattern)..i suppose thats a module's 'API'. Any thoughts of the distinction between Commands and Controllers and how modules communicate with each other in the Zend Framework? --- wow big question hey...i hope you read it. -- |
Calendar
QuicksearchCommentsMichael Kimsal about The Art Of Deception Or Publishing PHP6 Books Fri, 03.07.2009 15:40 Interesting to see Wrox's repl y here, and heartening. I can 't remember which publisher ha d this out, but I distin [...] braindumps about Volunteer Translators For Zend Framework: Surviving The Deep End Wanted Sat, 27.06.2009 12:28 Your quality of translation to get from volunteers is at bes t,Best Regards.braindumps Jim Minatel about The Art Of Deception Or Publishing PHP6 Books Fri, 26.06.2009 20:12 Ed's response here (and I have n't had a chance to have a per sonal discussion with Ed or hi s co-author on this sinc [...] Padraic about The Art Of Deception Or Publishing PHP6 Books Fri, 26.06.2009 19:16 Hi Ed, Thanks for your repl y, however I have to question some of these statements. Befo re I do I think it shoul [...] Ariel Arjona about The Art Of Deception Or Publishing PHP6 Books Fri, 26.06.2009 18:34 "The alternative is to wait un til version six is released an d THEN start planning the book . This means you will wa [...] Ed Lecky-Thompson about The Art Of Deception Or Publishing PHP6 Books Fri, 26.06.2009 14:42 Guys, I'm the author of the Pr o PHP 6 book. When we start ed planning it we were working on information we had t [...] Tim Fountain about Wrox Press Respond to "The Art Of Deception Or Publishing PHP6 Books" Fri, 26.06.2009 12:15 Impressive, and a great exampl e of the power of Twitter. Stefan about Wrox Press Respond to "The Art Of Deception Or Publishing PHP6 Books" Fri, 26.06.2009 09:16 Wow, that is indeed an impress ively good response. They're t aking the criticism serious an d picking it up in the o [...] Padraic about The Art Of Deception Or Publishing PHP6 Books Thu, 25.06.2009 23:46 I think the problem in these s orts of episodes is QA. An aut hor can deliver an honest book in their circumstances [...] Michael Kay about The Art Of Deception Or Publishing PHP6 Books Thu, 25.06.2009 23:31 This rather reminds me of the way a magazine with cover date April 2009 will appear in the shops in February. It's [...] Ian McCarthy about Wrox Press Respond to "The Art Of Deception Or Publishing PHP6 Books" Thu, 25.06.2009 22:00 It is nice to see a technical book publisher be so willing t o take steps like this to ensu re accuracy. Admittedly, [...] ronny stalker about The M in MVC: Why Models are Misunderstood and Unappreciated Thu, 25.06.2009 20:04 Thanks for this refreshing art icle. It has helped me move a step further in my understandi ng of MVC. I have rec [...] Jim Minatel about The Art Of Deception Or Publishing PHP6 Books Thu, 25.06.2009 18:50 Pádraic: Thanks for taking the time to discuss this with me on Twitter last night. I’m the Associate Publisher [...] Padraic about The Art Of Deception Or Publishing PHP6 Books Thu, 25.06.2009 17:36 So long as I get the first one ! Jason Sweat about The Art Of Deception Or Publishing PHP6 Books Thu, 25.06.2009 16:29 Probably the next thing to loo k out for is people with/compa nies offering PHP6 Certificati on! CategoriesTop ReferrersShow tagged entries application security astrum futura atom bdd behavior-driven development behaviour-driven development book dependency injection design patterns devnetwork docbook documentation eve online games htmlpurifier inversion of control irish php user group irishisms maugrim microformat mock objects model mutateme mutation testing mvc openid openid and yadis pc gaming pear phing php php game development php games php general php security phpmock phpspec phpunit qgl quantum game library quantum star se rantings rss simpletest snarl solar empire surviving the deep end symfony tdd tutorial unit testing xp programming xrd xrds yadis yaml zend framework zf proposal |
|||||||||||||||||||||||||||||||||||||||||||||||||


