Software Patterns in Web Development

Over the last couple of years I have witnessed thrown together php code that is impossible to understand what is going on without spending hours reading through the code.  I get same response is given every time I ask why not separate into more readable and maintainable way: “It doesn’t matter as long as it works”.  That may be true for small, personal websites but the furthest from the truth when dealing with company websites that may have multiple developers and will get passed on long after the initial developer is gone.  By developing with the attitude as long as it works, it usually leads to more money wasted whenever a new feature or a bug fix needs to get done.  Here are some hints that can be easily done to help improve your site.

DatabaseController

Almost all dynamic and functional websites will connect to some form of a database in one way or another.  It is always a good idea to have a Controller object that deals with all connections to the database.  This subsystem (could be a single file or a group of files) that will act as a single connection point for all database queries that need to be run.  By abstracting out these functions into a separate file will allow for quick changing of database server and name as well as easy modification of all queries (since there will be no searching through all files to find the query).  It also provides aspects of reusability where the result set of one database query can be used in several parts of the web application.

The following is an example of a basic Database Controller written in php 5 (adds object orientation features) with a MySQL database:

<?php
class DatabaseController {
 
 private static $instance;
 private $conn;
 
 private function DatabaseController(){
   $conn = mysql_connect('localhost', 'user', 'password');
   if (!$conn){
     die ('Could not connect: ' . mysql_error());
   }
   mysql_select_db("mydb") or die (mysql_error());
 }
 
 public static function getInstance(){        
   if (!self::$instance instanceof self){            
     self::$instance = new DatabaseController();
   }
   return self::$instance;
 }
 
 public function getRegisteredUsers() {
   $retval;
   $query = "SELECT name, user_id from users";
   $result = mysql_query($query);        
   while ($row = mysql_fetch_array($result)){                
     $retval[$row['user_id']] = $row['name'];
   }
   return $retval;
 }
 
 public function registerUser($name){
   $name = mysql_real_escape_string<code>(</code>$name);
   $query = "INSERT INTO users (name) VALUES ('$name')";
   $result = mysql_query($query);        
 }
}
?>

This is a template that can be used for all database connections.  Obviously it would be smart to group functions together.

Separate Static Content

Another important aspect of web development is having the same look and feel for every page.  This is used heavily in major CMS (such as WordPress), but I am still shocked with the amount of sites where I see copy and paste jobs.  The idea here is to separate all the static content that should appear on all pages away from the actual body of the page.  For example, create files for the header, footer, sidebars, navigation, etc.  The benefits here obviously are maintainability.  Changing one file is much easier than modifying all files within the system.  This will not only save money when these parts need changing, it will also make the code easier to understand for a new employee trying to learn the system.

Error Handling

Error handling is key when developing a reliable and user friendly web application.  Within error handling, you would want to be able to catch errors before it becomes a problem, and have a way of the application to correct itself.  The other key part is to notify the end-user of the error.  Error handling can also include logging of particular errors (having a variety of error levels like low to severe).  Like all the other things talked about so far, abstracting out the error handling allows for quicker modifications for the future.

Database Injection Prevention

This is not a pattern in itself, but just something that I am amazed still happens on live sites.  For those who are unaware of what SQL Injection is, Wikipedia explains it well.  Always double check all input for validity before running an SQL query.  There is a pre-built function for PHP called mysql_real_escape_string which will take the supplied string and make it mysql safe by adding an escape character (‘\’) before certain string combinations including an apostrophe.  By simply calling this function on all input provided, it significantly decreases the chances of an SQL injection attack.

Final Words

The last thing I can provide advice about is to follow the software life cycle (Requirements -> Design -> Implement -> Test -> Maintain) for your web application.  Like all software projects time spent nailing down the specification of what needs to get done, and having a robust design will save more time and money in the future.

13 Comments

  • Keith says:

    Every coder should take special care making sure that they follow some sort of standards, not only for working with other people, but also when working with just themselves. Once you get a coding frame developed, it makes it so much easier to go back through your old work.

    Another thing that I am starting to do is make templates for code that I repeat on multiple projects, and obviously starting each templates using the techniques that you described helps tremendously.

    Btw, I like the organization of your posts.

  • Ryan Knapp says:

    Given your section on abstracting database calls into a controller, how do you feel about JPA style annotations?

    Personally I have mixed feelings. I like the idea of segregating my database calls from those who don’t need to, don’t understand, or otherwise don’t care about them through either DAO (with or without entity beans), or xml a la hibernate. It prevents those who don’t adequately understand the mechanics of said interaction from screwing everything up, and removes elements that might prevent them from getting their own work done. It also makes it easy to change queries in that you don’t need to pick through classes to find a particular one.

    However, JPA is moving towards including annotations for specifying your object relational mapping, which occasionally leaves two to three line methods prefaced with 6 or 7 lines just for some of the more complicated mappings (set or map structures, especially those requiring cascades or transaction modifications), and additionally suppression warnings commonly seen in database interactions, (particularly annoying is the unchecked type conversion suppression, which cannot be removed due to the current implementation of generics).

    So I end up caught between the trend towards annotations and embedding, and my desire to separate my mappings. At least frameworks and session factories make transaction support a lot cleaner code wise.

  • Brian says:

    I have used NHibernate (.NET version of Hibernate) before, and i like how it completely abstracts the conversion of the database model to class representation. With that being said, I noticed that for the more complicated relationships it is much harder, if not impossible, to have it set up and running smoothly. I haven’t worked too much with it (so correct me if there is a way), but I do not like the idea of having to pull down all information for a particular object (essentially calling Select *) whenever you need just one or two fields. I am not a big fan of serializing objects into a database just from the fact when changing technologies, you will have to convert the serialization (i.e. A Java serialization object will be useless if you decide to move to another programming language). I feel it is good practice to design your database language independent just in case either the programming language changes, or you need a new system that will use the same tables that is to be written in a different language (which is really not that uncommon).

    Most of my web development is done using PHP 5, hence the sample code was in php. Since the introduction of object oriented features in php, I have tended to use a DatabaseController that will share class representations with the rest of the system. So basically, the DatabaseController will convert the database results into class representation and return that class representation (or a list), but this also leaves the flexibility where I can return a single field without representing it in a class representation (e.g. if you want a count of groups, etc).

    The idea I was going with the post was to go the extra mile and separate your database connections and queries away from the rest of your system. I have seen many web sites/applications which do all their queries within the code, which makes it rather difficult to make any changes or modifications to the database (you would have to hunt down any queries, instead of knowing exactly where they are).

  • Ryan Knapp says:

    Essentially what happens with Hibernate is that you do either class uml -> db schema, or schema -> classes. I personally prefer schema to classes, as this will a) minimize redundancy (normal forms, etc) and b) leave you with a portable database (like you mentioned). One that you can just as easily perform regular SQL upon, mostly portable (Special features like Sets or Maps do indeed require extra work, but the ROI once you figure out how to do it once is rather high).

    Oh, and not sure if NHibernate behaves this way, but regular hibernate uses lazy initialization, where the actual value isn’t retrieved until it’s actually needed, so you have a tiny bit of overhead in empty allocations for the object, but its not too big a deal. In fact, you can have entire sets that are really just shells, and select a single object from the set and only that object will be retrieved from the database.

    Definitely understood the post was dealing with a different set of requirements, especially with PHP over Java, it just sparked the question as I wasn’t sure I liked annotations that much.

    Based on your bit about preferring to return classes, I’d say you like DAO style transactions, except without the silly java insistence on beans, which thankfully the Play framework (check it out, its far more accessible that struts / spring for personal projects) describes as an antipattern, as its rather pointless to remove the manipulation methods just to make it pure data.

    Oh, and remember PHP5 -> mysqli, its new and shiny!

  • Brian says:

    Thanks for the reply. Just got to keep in mind that there is no silver bullet. There always will be advantages and disadvantages of using one technology over another and these need to be weighed for each project in order to get the most out of the technology being used. Some approaches are practical for certain problems, but at the same time can be completely unreasonable for other problems.

  • Hi there, I just finished reading some of your posts and found you to be quite informative. Thanks.

  • Deangelo Walling says:

    Awesome post thanks! I’m an enormous fan of the weblog.

  • Echo Knapik says:

    cheers very much, I must say your blog is excellent!

  • Reid Orines says:

    Thank you for the entertaining read! Alright playtime is over and back to school work.

  • Rope says:

    Good to see a taenlt at work. I can’t match that.

  • Gabby says:

    Holy cnocsie data batman. Lol!

  • Just about all of the things you point out happens to be supprisingly appropriate and that makes me ponder the reason why I had not looked at this with this light previously. This piece truly did switch the light on for me as far as this topic goes. Nevertheless there is 1 point I am not too comfy with so whilst I try to reconcile that with the actual core idea of the point, permit me see just what the rest of your readers have to point out.Very well done.

  • Homepage says:

    … [Trackback]…

    [...] Find More Informations here: justcallmebrian.com/?p=93 [...]…

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">