Design Patterns

Published at: 1 October 2010

Avatar

A while ago I started reading a book about Design Patterns. Now I've read it, I thought it was time to summarize the differences between OO and procedural programming in a way most people will understand.

For this example1 I'll use a visitor which is logged in on a website, who wants to read a news item, which is only available for registered members, first the procedural style:

<?php // Connect to the database // ... a pile of HTML for the rest of the page // ... and some code to check if there's a session or cookie if ($_COOKIE['logged_in'] == true) { // Retrieve the item from the database, using the id given with the URL $result = pg_query("SELECT title, author, content FROM news WHERE id = " . $_GET['id']); // Loop through the results, in this case just one row is returned by the database while ($item = pg_fetch_assoc($result)) { // We want to know who posted the item and of course the item itself // HTML and PHP are mixed in the same file echo '<h1>' . $item['title'] . '</h1>'; echo $item['author'] . '<br/>'; echo '<article>' . $item['content'] . '</article>'; } }

For a website which has just one page, the code above will be a perfect solution. However, when one wants to add a second page, the same code has to be used. For example on a photo album, here too it's about a picture only a registered member is allowed to see:

<?php // Connect to the database // ... a pile of HTML for the rest of the page // ... and some code to check if there's a session or cookie if ($_COOKIE['logged_in'] == true) { // Retrieve the item from the database, using the id given with the URL $result = pg_query("SELECT title, author, photo FROM pictures WHERE id = " . $_GET['id']); // Loop through the results, in this case just one row is returned by the database while ($item = pg_fetch_assoc($result)) { // We want to know who posted the item and of course the item itself // HTML and PHP are mixed in the same file echo '<h1>' . $item['title'] . '</h1>'; echo $item['author'] . '<br>'; echo '<img src="' . $item['photo'] . '">'; } }

As you can see, only a small change is needed, the rest of it is duplicate code. With only two pages there's not much damage done, but tomorrow of course there will come another page, and another... If you want to support comments on your website, which are almost equal on every page, this code has to be added on each of the four pages. The copy and pasting won't hurt, but bugs always appear afterwards, so you have to edit this code on the four locations. For websites with hundreds of pages, this just is no option. With OO this problem is solved. In this example I will be using the MVC pattern.

The Model is used to connect to the database. It pulls data from and puts data into this database. It also deals with the logic behind this data. A timestamp is converted to a readable date or time format. And it checks user input, so no strange content can appear on the website and it protects the website against hacks.

The View is used to display the data on screen, this is the only place where HTML and sometimes CSS is used. In most cases the HTML for markup and CSS for styling is separated in different files. Which is a good habit to keep the code clean.

The Controller is in between the Model and View like some sort of negotiator. For example, it makes sure only permitted users can view certain data.

In the example below I'll use this MVC pattern to refactor the procedural code. First the Models, with a class which acts like an interface, with a standard method and an abstract method, this abstract method doesn't do anything, but every class that extends this class, should overrule this method. Every Model has to contain a database connection, so this functionality is put in the constructor. The constructor is automatically called when a class is initialized, or when an object is created.

<?php // All Models 'extend' this class, so all Models automatically contain the connect() method // This one has to be written just once. When the database password changes, this has to be // altered on one location class Model { public function __construct() { // Some code to connect... } public abstract function getData($id); }
<?php class ModelNews extends Model { // The controller picks all variables that are specified in the URL, in this case // the id, and uses them to call this method public function getData($id) { $result = pg_query("SELECT title, author, content FROM news WHERE id = " . $id); // Loop through the results, in this case just one row is returned by the database while ($item = pg_fetch_assoc($result)) { // No HTML needed here. An array is returned that all Views can understand $data[0]['title'] = $item['title']; $data[0]['author'] = $item['author']; $data[0]['content'] = $item['content']; } return $data; } }
<?php class ModelPhotos extends Model { public function getData($id) { $result = pg_query("SELECT title, author, photo FROM pictures WHERE id = " . $id); while ($item = pg_fetch_assoc($result)) { $data[0]['title'] = $item['title']; $data[0]['author'] = $item['author']; $data[0]['photo'] = $item['photo']; } return $data; } }

Looking at the Models, we have pretty much the same code, but the HTML is separated and the Models only have to know how the database is set up. Next we have the Views:

<?php class View { public function __construct() { // A pile of HTML... } // Every View has to have the option to show the output on screen public function show($data) { // First loop through the array while ($data) { // Then make sure every field is displayed, in this case title; author and content while ($data[$i]) { echo '<h1>' . $data[$i][$j] . '</h1>'; echo $data[$i][$j]; echo '<article>' . $data[$i][$j] . '</article>'; } } } }
<?php class ViewNews extends View {}
<?php class ViewPhotos extends View {}

The ViewNews and ViewPhotos classes can be kept small, because they inherit their functionality from the main View class. When one of the Views needs some extra functionality, it can be easily edit by overruling the show() method. Also, other methods can be added. Last but not least, the Controllers:

<?php class Controller { public function run() { // The Model and View are initialized $model = new Model(); $view = new View(); // The data from the Model is passed to the View $view->show($model->getData($_GET['id'])); } }
<?php class ControllerNews extends Controller {}
<?php class ControllerPhotos extends Controller {}

The Controllers also can be kept small, because the run() method is inherited. When initializing the Model and View only the right title has to be passed, so that ModelNews and ViewNews are called when ControllerNieuws is called. The same story goes for the ModelPhotos; ViewPhotos and ControllerPhotos. The Controller class can handle this, so no other code is needed for ControllerNews en ControllerPhotos.

The number of lines is pretty much the same, but with bigger websites one can get lost in the first example. But actually the article is about Design Patterns. Some basic principles of OO from Head First Design Patterns.


OO Principles

Some situations don't allow the use of all principles, so they have to be compromised, that's where Design Patterns come in. These are solutions for these situations, used a lot by other developers, so these patterns are documented a lot. The patterns get a title which allows developers worldwide to use the same vocabulary.

OO Patterns / Design Patterns

Creational patterns

Structural patterns

Behavioral patterns

Concurrency patterns

Footnotes

  1. The examples are solely for illustrational purposes.

  2. These patterns are found in Head First: Design Patterns. 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23