Layered Application Design (Part 1): Why Should You Care?

We often hear or read about the importance of implementing a layered strategy when designing and developing applications.  Unfortunately, more often than not, when I review applications, I often find a pile of spaghetti code that’s lacking any clear layering strategy.

SpaghettiNow I love a plate of spaghetti as much as the next guy as a meal, but as a project?  Ehhh…not so much.  So what exactly is spaghetti code and why is it such a bad thing?  I think it’s important to answer these questions before we start waving the flag of application layering so that we know why we want this rather than just saying “oh yeah, layering…good stuff”, and then continue with our old spaghetti-fied ways.  We have to realize that most developers are lazy and looking for the shortest and least painful path to getting the project done.  If we can show that a well-layered design actually IS the shortest, easiest path (versus crummy spaghetti code), then we’ll be getting somewhere.

I’m a big fan of examples and pictures.  It worked well for me in kindergarten so why should now be any different?  Consider the following code sample:

protected void AddProduct_Click(object sender, EventArgs e)
{
    SqlConnection con = null;
    SqlDataReader reader = null;

    if (String.IsNullOrEmpty(this.sku.Text))
        // Display error message that SKU is required.
        return;
    if (String.IsNullOrEmpty(this.name.Text))
        // Display error message that Name is required.
        return;
    if (String.IsNullOrEmpty(this.description.Text))
        // Display error message that Description is required.
        return;

    try
    {
        con = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Catalog.mdf;Integrated Security=True;User Instance=True");
        con.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = con;
        cmd.CommandText = @"INSERT INTO PRODUCTS(SKU, Name, Description) SELECT '" + this.sku.Text + "','" + this.name.Text + "', '" + this.description.Text + "'" + @" WHERE NOT EXISTS(SELECT 1 FROM PRODUCTS WHERE SKU=" + this.sku.Text + ")";
        if (cmd.ExecuteNonQuery() != 1)
        {
            // Display an error message that the SKU already exists and cannot be added.
            return;
        }

        // Display a confirmation message.
    }
    finally
    {
        if (reader != null)
            reader.Close();
        if (con != null)
            con.Close();
    }
}

If you’re familiar with ASP.NET, a quick scan will reveal that this code is a click handler for a form submit button on some kind of page for adding new products to a products database table.  This code is a good example of an un-layered design.  All of the logic required for user interface all the way down to storage of the data is here in one place.  Is it spaghetti code?  By itself, probably not, but if you were to have several instances of this type of code repeated throughout an entire application (pretty common), I think you’d quickly find yourself with enough spaghetti for an entire meal.

XBox

Pizza

So what, you ask?  The code works, so why should I care?  Well, if you (or anyone else) will never have to touch that code again for new feature or changes to your environment, maybe you shouldn’t care.  Order a pizza and fire up the Xbox.

But what if some IT guy decides to change the permissions on the database so that user “joe” no longer has access and sets up a new account that is to be used?  Well, we’ll have to find every place in the code where this connection string has been specified and make a change.  That kinda stinks, but not enough to make the lazy programmer improve his approach to application design.  The lazy programmer is not convinced.

LumberghUh oh, here comes the boss man.  He says that same bozo in IT has now decided to switch the company from SQL Server to Oracle.  Boss man: “Isn’t there a flag or something you can set to tell the application to use Oracle instead of SQL Server”?  Lazy programmer: “Uh, I’m going to need two weeks”.  Boss man: “You have two days.”

What just happened here?  What’s the big deal about switching from SQL Server to Oracle?  Well, there’s about 200 places in your code where you’re using SQLConnection and SQLCommand.  Those all have to be changed and tested now.  Oh yeah, and you have to check all of your stored procedures and inline SQL queries to make sure they’ll still fly in Oracle.  The lazy programmer is suddenly working long hours and late nights to make the change.  Hopefully, rather than coding everything to work only with Oracle, he’ll organize things so that he’s ready in case this IT guy decides to switch back to SQL Server again (changing things frequently is a common recipe for job security).

Just when our lazy programmer is feeling recovered from the database switch coding marathon, the boss man wanders back around.  Boss man: “Hey, we need to make sure that the application only allows administrators to add, update, and delete products.  When can you have that done?”  Lazy programmer thinking to himself: “Hmmm, I’m going to have to add some extra logic to the Add page (from our example), the Edit page, and the Delete page.  I’ll just go ahead and add this extra logic right before the code that validates that the name and description fields are populated.”  Lazy programmer: “Two days.”  Boss man: “You have until tomorrow.”

So our lazy programmer scrambles and adds the extra logic to all of the required pages.  As he thinks about it further, he then realizes that non-admins shouldn’t really even have access to these pages at all, so he builds additional logic to hide the menu options for these pages from non-admins.

Call Of DutyBy the time he’s done, he’s implemented this admin-checking logic in the application’s navigation menus (to prevent displaying add/edit/delete links to non-admins) as well as in the add/edit/delete pages (in case someone directly accesses these pages outside of the navigation menus).  Because there’s no central place in the application code to check for admin rights (the admin setting is stored in the database), chances are good that he copied/pasted this new database logic in each place where it’s required, which is messy if management ever changes its mind about how it wants this to work (which is likely…remember how making changes helps with job security?).  Regardless, he got things working and still managed to make it to the Call of Duty: Modern Warfare 2 gaming party on time.

A few weeks goes by and things seem ok, until one Friday afternoon at 4:45 when the president of the company comes by.  President: “Our business partner needs to integrate with our application.  They already have their own Windows-based inventory management system.  They just need to integrate it with our application’s back end.  How long will that take?”  Lazy programmer: “I’m not feeling very well.  I need to go home.”

Now we have a major issue on our hands.  Our business partner needs to access the non-user interface portions of our application.  But wait.  We don’t have any non-user interface portions in our application!  All of our code is in the user interface!  Remember our code sample?  All of the logic for validating data entry, determining privileges, and accessing the database are all right there in a button click handler on a web page.  This is gonna hurt.

Our only solution now is a whole ton of rework and testing to split up this code into layers so that our business partner can integrate with us at the “business logic layer”.  If only we had implemented a layered design from the beginning.

Admittedly, this example is a bit contrived, but I’ve experienced these types of scenarios frequently throughout my career.  I’ve been the lazy programmer that either didn’t want to (or didn’t know how to) spend some time up front at the start of a project to implement a well-layered design.  I can tell you from experience that this important step WILL save time and frustration in the long run as well as create a product that can quickly adapt to any change in requirements.

Is the lazy programmer convinced now?  In the next post in this series we’ll start digging deeper into the specifics of layering by discussing and demonstrating approaches for separating data access, business logic, and user interface code into their own separate layers.

What do you think?   Do you agree?   Do you have horror stories of poor software design that you’d like to share?  I’d love to hear your thoughts.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s