Latest: buggy behaviour of parent:: in PHP 5.3.3

Content with Style

Web Technique

MVC in smaller web applications

by Matthias Willerich on June 7 2005, 15:57

The real world

Web development is, in many cases, a process where time is a crucial factor. As coding is usually the last step in the process, all things come together and prior mistakes are revealed.

"Build this so it looks the same in all browsers, works better than the IA was ever planned and can fly." Or so we hear.

With a limited amount of time, developers are often tempted to fall for quick fixes and, not only due to last-minute changes, find themselves in a huge ball of code at the end of the project.

"What does that matter, if the site is working nicely, nobody complains and it's nodded off by the client?" I hear you ask.

This attitude is something I've encountered many times, and it usually results in a second-phase disaster, be it an extension of the site, a new face or a server change.

Theory

This is where the MVC comes to the rescue. It's basically an attempt to structure a web application into three components:

  • Model is generally understood as the data-administration component. In the majority of website projects, this is the data retention in a relational database system, but it could also include other persistent business objects, Enterprise Java Beans for example. Model is passive and does not trigger any actions. Data is requested independently of their representation (view); Model does not know anything about the data presentation. Model can work with one (1:1-relation) or several Views and Controllers (1:n-relation).
  • View describes the visual representation of the Model. In the case of many dynamic websites, you would imagine one or two Views on the same Model: in the case of this article, one would be the public View - the way you see this article now, and another one would be where I create and edit. Of course, there are many more possibilities: different user levels, each with a distinctive set of permissions; different representations of the same website for regular users; high contrast for easier reading; a View without head and navigation for printing, and so on.
  • The Controller has the entire application logic implemented. It is an active component. The application receives inquiries, passes it on to the responsible subcomponents in the system and possibly sends answers back to the user. The Controller carries out various manipulations of the Model for the execution of user actions.

So far, so good. Now that the theory is clear, we can look at how it's used in the web development process. Do I actually need it? This seems to be a very sensitive subject. While researching, I've found several approaches, most are somewhere in the triangle of determined, angry and ignorant. I'd like to point out the most obvious reasons to use it, hopefully not stepping on any toes:

  • Match a thought pattern: Putting your code into a programming pattern is difficult when you try doing it while coding, but the idea is to structure the code first, in your head, on a piece of paper or, for large scale projects, with CASE-tools. With the structure documented, your code becomes more manageable, and the number of people that want to see you roast in hell (possibly you yourself in 1 or 2 years time) is decreasing. Every developer that understands MVC will find their way through your stuff quickly, you will both work on the same wavelength, because you both follow the same pattern, in code and thought.
  • Reusability. This goes for any kind of modularisation, but it's an argument not to ignore: Once you have thought through and set up your model, you can reuse it many times with no or only minimal changes.
  • Extendibility: With a strict modularisation, you have a defined field of work when it comes to changes of face, functionality or data storage. Depending on your web applications needs and real-world situation, you can decide which parts need upgrading.

Practice

I discovered that Jakarta Struts is a really good Java-based solution and, more recently, PHP Architect magazine offered a free download of their may 2003 issue, containing a nice introductory article with a solution based on Smarty templates. A very extensive solution incorporating the three-tier architecture (no, they're not the same) also PHP-based, can be found on Tony Marston's website along with tons of information on different design patterns.
I could stop here and leave you with one of the examples, but let me say this: I believe that the size of the project and the probability of exchanging or updating certain components should play as important a role as the reusability of the code.

Over time, Pascal and I have come up with a loose framework of PHP classes, which have saved enormous amounts of time when building medium-scale projects, thanks to their reusable subcomponents.
The Views are set up with CSS and (X)HTML, which is generated with XSL stylesheets (see Pascal's article with his five-layer structure for more detail).
In the backend PHP, classes are structured by their functionality. A db-class manages all lower-level database work: replace it or change the configuration for a database change. This class represents the Model. Your server was hacked and you need to refer to a backup db-server? It's done in 10 seconds.

A base class, meanwhile, carries all of the helper functions that are used across most projects, for things like string and date operations. It is extended by a page class, which is the first class to adapt to the project. Here, the site structure is taken care of (usually dug out of the database in one way or another, as a tree or a flat page model), functions for breadcrumbs and navigation grab the data and return the XML, and global site elements find their data. But not only that: All what's generally called business logic, calculations, workflows and so forth, can be found here as well. The class can then be extended for special purpose pages, to keep it nice and tidy. I group them as Controller. They receive all the requests, they instantiate the Model (the db class) to deliver XML, to be transformed by the View, by XSL.

But this does not strictly fit into the MVC pattern: In a clean approach, no SQL would be found in the page class. A common technique here is to set up a class for each table that contains all queries. This way, you know where to find your SQL and what classes to touch should your db-server change. Alternatively, you can extend the db-class and top it up with higher level of functions that build the SQL for you. On the upside, you only have one file to change (as opposed to one per table); on the downside, solutions tend to be developed in a complicated way, thereby making it difficult for the next developer to get their head around it. Furthermore, it may be too specific to one site and, therefore, not very portable.

With these classes set up as a starter package, you'll have incredibly quick results - and working as a frontend/backend team is a joy. Simply set up an abstract XML file with all the data you need, and each of you can work towards it from both sides: one on the xsl/html/css side, the other in the php/db department.

On several occasions, I left out the table classes as a set-up for medium-sized projects. As an alternative, I either stuck to relational databases (usually sufficient) and coded in pure SQL-92 - although this tends to be awkward and I'm not sure if all common databases follow this standard entirely - or I made sure the db-application stayed the same throughout the lifetime of the site.

As with most things in modern digital life, sites are ever-changing, but the code hardly ever survives three years. Your budget, timeframe and the purpose of the site will determine to what extent you want to follow MVC. But it's always worth considering.

Comments

  • Very interesting article. Would the use of an ADODB toolkit as interface to the database stick to the MVC model, because it qould get U rid of database-specific SQL?

    A common technique here is to set up a class for each table that contains all queries.

    This actually doesn’t sound like a very good idea to me, since I work with joint queries and subselects.

    But then subselects are server-specific … Ohh dear …

    I gotta think about this more thoroughly!

    by Pascal Opitz on June 2 2005, 18:42 - #

  • Looks like a very careful introduction to Design Patterns for Graphic Designers. :) In general, I think that you are right about separation and I wonder how many developers around the world still mess presentation with SQL and logic.

    I would disagree with you, telling that the main benefit of separation of SQL from the page presentation is an easiness of finding the proper statement in a future. While it’s also true, the main aims of design patterns (and we are talking about MVC, Facade and some other patterns) are re-usability and isolation. You have uncovered the re-usability part a bit, but isolation plays a great role too (and it’s not about SQL only).

    When you have a team you can define the classes, their roles and goals. After that spend a while to create stubs and spread the job across the team. Everybody will be building its own part: SQL expert – SQL, designers – presentation, the rest – logic programming. When finished, tested and re-joined together the parts form the application. Because of clear separation no one waits for others and knows clearly from A to Z what his own part should do. It’s just one of possible use-cases.

    I have more to say, but I would better stop here as it’s going to be overloaded. :) Nice article! Keep up doing great job!

    by Aleksey Gureev on June 3 2005, 08:01 - #

  • Aleksey,
    I do agree with you. Thanks for pointing out a nice example for isolation. I know it’s not only about sql, and I think you summed it up very good.

    I guess it slipped my mind, as I wanted to write this up for smaller projects, which hardly ever have more than 2 people developing it. But you’re right nevertheless. Feel free to add more, or drop me a line

    by Matthias on June 3 2005, 11:43 - #

  • This pattern is very cool but if its obviously that you never use benfits like changing the view you. Its not so important.

    by berlinandree on June 3 2005, 13:28 - #

  • Well, OK. Here’s another use-case for that approach… When you are planning to build something, you break it into chunks as I commented before and think about clear separation between things. At this stage you don’t think about how everything will be working specifically, but how the whole thing will be composed of these small reusable parts, having specific roles. A good example, is our favorite SQL layer (I call it Persistence Layer). It isolates database stuff and generally (attention please) PLAYS THE ROLE OF SOURCE OF ALL DATA. It means that if everything is designed well you can replace the layer with some stub, which is returning some test data while you are building the other parts of application and later, when your team-mate or you will implement this layer, you can put it in instead of stub as production version. Why it’s good? Because it allows you to concentrate on the whole project instead of digging into details too early. You plan and measure the interrelations between parts and design everything from bird-sight view.

    The other good thing is that you always can start from writing tests for your future modules to set in stone what EXACTLY they should do (it’s called TDD – Test-Driven Development). You write scenario after scenario (generally using PHPUnit or other XYZUnit, depending on technology you are using). These scenarios should reflect the real-life problems the module is intended to solve. In example with Persistence Layer, it could be “Reading list of posts”, “Adding post”, “Adding Comment”... you got the idea. While writing the tests you add methods to your classes which help to solve your problems, group them, rename them, recognizing patterns and following them (over and over again). By the end of this process you will have the stub for your module, which is having all methods and clearly designed to solve your TODAY’S problems (nothing more, nothing less). After that you just spend some time to put in the implementation and pass all the scenarios you have set in tests. It’s all about modularity, layering and isolation.

    As for me, I always try to work “from the tests” because if not, then I’m always thinking about the module from inside and doing too much assumptions, adding flexibility which is not likely to be necessary and etc. It all takes time.

    Save your time, do it right. :) Some good reading on the subject could be anything about TDD, general articles by Martin Fowler (“Is Design Dead?”, for example) and of course the design patterns material. They aren’t the goal and you shouldn’t aim on using them all the time; they just help you to concentrate on real tasks instead of re-inventing the wheel.

    Hope that it’s interesting and even inspiring to someone. :)

    by Aleksey Gureev on June 3 2005, 14:50 - #

  • it is definetely inspiring to me, and although some of it would be hard work to get into practice at work (there’s always a project manager with a stopwatch, for this and only this project), I appreciate this very much.

    I looked into unit-testing before, but in small/medium-ish companies, with small/medium projects, probably focussed on different things than development, it is hard to get through. But I won’t stop, obviously, and it’s good to have people around with the same opinions.

    Cheers,
    Matthias

    by Matthias on June 3 2005, 18:16 - #

  • Matthias, you can use some of the techniques to increase the precision of your estimates for the project. Having the clear architecture and stubs early, you can significantly more precisely tell when you will be done with the given part of work as you will already know what it going to happen (technically) instead of making weird guesses.

    Anyway, I’m happy that it was useful writing!

    by Aleksey Gureev on June 3 2005, 18:26 - #

  • sure.

    here’s the article Aleksey was refering to:
    is design dead?

    I printed it out and will have a read.

    cheers.

    by Matthias on June 3 2005, 18:50 - #

  • I didn’t see it here, so I figured I’d mention it – if you haven’t already heard of it, check out Ruby on Rails – it makes MVC and Object/Relational mapping really easy – its already there for you – even in the smallest of projects.

    Watch the 10 minute setup video to get the basic idea.

    by Scott Becker on June 3 2005, 21:44 - #

  • Aleksey: I’ve been working with the chap who wrote SimpleTest recently and I’m really coming around to the idea of test driven design. I tried explaining it to Matthias and Pascal a couple of weeks ago but couldn’t think of a good way to really sell it to them. Your suggestion that it helps to modularise and isolate your components is far better than anything I managed to come up with at the time!

    by Mike Stenhouse on June 4 2005, 16:49 - #

  • Hmm, I like the idea of making up the tests before starting to develop, but what happens if you suddenly need to extend the functionallity … That’s why I am still drawn to neat concepts that somehow remain flexible than doing a module that just does EXACTLY what the test does, but may be hard to modify … is that a reasonable concern, Aleksey?

    by Pascal Opitz on June 4 2005, 17:23 - #

  • Mike, thanks, it’s a great pleasure to share and see that your shares make sense and help someone.

    Pascal, of course, the evolution should take place. In most cases, you will add something new, but sometimes you will update existing functionality and very rarely remove.

    When you add you create the tests suite beforehand again and try to pass it in minimum number of strokes.

    When you change, it’s always best if you have a set of short examples of what the functionality does now (your current set of tests as a basis). Basing on this, you update the tests to reflect your required changes. It helps you, right as in the first time, to create a meaningful arch. and experiment with interfaces with stuff beforehand. After that you simply change what you need and you are done.

    When you remove something you just don’t need the tests for that scenario any more. So, kill them.

    The tests help you and your team to feel confidence about the application. When you were working a week on one module and then gave it to the other developer on your team you can be absolutely sure that he hasn’t broken any bit of code with his changes because your tests, reflecting your requirements for module, still pass. Being confident is a great feeling: you finish your working day in a great mood and, what’s also important, you can give your application to the client in a middle of the night, knowing that every piece of it is tested and proved to work.

    From the first glance, it looks like you are wasting the valuable time for writing useless tests which aren’t bringing the value to your clients. It’s not true. (a) The bugs you find are absolutely different from the bugs your clients will find. At least, you will start to ask for excuses, feel sorry and etc. (b) The time you spend on writing tests is nothing against the time you spend on finding the ways to reproduce bugs, track them, fix them, propagate updates and etc. (c) your reputation goes lower and lower with growth of index in your bug tracker. Having less defects is much better than having an excellent skills in bug-fixing.

    So, it’s up to you to make test or no. Just remember two rules (my own experience):

    Do Not Test Everything—test only what can break or you will be really wasting time. Make the tests to be a part of your process and position it as sort of a game or invent something to make them look more natural.

    If Your Tests Never Fail, They Test Nothing—at least make some adjustments to code (if you are writing tests after implementation) to prove to yourself that the tests will fail if anything will go wrong. And… never worry about the failing tests. If test fails, it means that you have caught the bug, which was going to slip into production version if you had no that test. :)

    Sorry, if I sounded like having PhD in Testing. It was just my bit of experience in this are and should be treated this way only.

    by Aleksey Gureev on June 6 2005, 09:31 - #

  • I’ve been using this for sites and had great luck with it on Ruby on Rails. I’ve found that sites that are not updated often, I turn on caching (1 hour or so) within the rails app (for production), thus it don’t have to build the page for each access (this assumes no personalization).

    Caching is super-easy in RoR and can be added to an entire controller with one line…

    MVC is great!

    by Jesse Andrews on June 16 2005, 05:33 - #

  • Increasing the chorus MVC is great, and you should have put on of the 10,000 images that really shows it properly so Graphic Designers can understand really fast ;-p

    And, if in your project the graphic designer is thinking about SQL you have problems…. hehe

    by the way, Aleksey is pretty right about TEST as much as you need, but TEST hehe…

    And… some interesting thing to ask is, do you have a PHP class with the queries of your system? I hope not… not exactly that! you can have many ideas on what to do with your queries and so on….

    cheers

    by Lucas Zingano on April 15 2006, 14:08 - #

  • To be honest, Lucas,
    I have never succeeded to explain anything server side to a graphic designer, then again, I realised fairly quick that there’s no need. But there is a hell lot of chaotic developers out there, and MVC seems to be an easy entry point into patterns. The advantages of the modular approach are just too obvious.

    I’m not sure I understand what you mean by your last paragraph. Do I have a class for sql, as in one, or as in one for every purpose?

    I use a couple of classes that form the abstract use of what I’m going to build, like a list class, which I then extend with the purpose class that I need to build. This class will contain SQL.

    Recently at the PHP conference UK Derek Rethans gave a nice introduction into EZ components, and I quite liked their DB class, it abstracts SQL really nicely; I might give it a try soon.

    by Matthias on April 16 2006, 09:25 - #

  • I must confess that the idea of having a class with all your SQL’s or whatever as a bad thing is based on my experience with Java, as PHP is a scripting language there is no real problem to have this kind of stuff because you don’t need to compile the code before sending it to the client just to fix a misspelling problem, so, don’t worry about that.

    I used to use something like DB Class and it is a very interesting component that override the idea of keeping your SQL in plain string, which can be very dangerous to enable SQL Injection attacks.

    I hope I made myself understood…

    by Lucas Zingano on July 12 2006, 06:58 - #

  • Yes, I got you now.
    I used to do some dynamic websites with Java, mainly JSP and Servlets working together, and the one thing I really needed there more than in PHP is a mirrored development server. That takes the grievance off uploading a compiled class to the live server which then has a typo.
    Using a class that abstracts the whole sql business… I’m not sure about it. Sure, it keeps everything in one place, but at the same time you’ll have all the work to abstract the whole of the SQL language; and that has to look at feel intuitive, too.

    by Matthias on July 26 2006, 02:31 - #

Leave your comment

Comments are moderated.
Tags allowed: a, strong, em, code, ul, ol, li, q, blockquote, br, p

Advertisement
Advertisement