2006-12-02

Onion

An onion has layers...
...Shrek

In the beginning

When I first started writing applications they would typically be a single program editing a single datasource. As time went on this changed because people wanted to share data, so client/server applications appeared.

It didn't stop there though, N-Tier applications became much more common. Applications were typically split up like this:

RDBMS--DAL--Business classes--UI

Due to the fact that I use ECO for my business layer , and that ECO has the DAL built in, the illustration for me would look something like:

RDBMS--Business classes (ECO)--UI

Thinking of business problems as classes instead of tables really helps to simplify your design, so I have been very happy writing applications this way for some time now.


The application layer

In December 2005 I was tasked with the job of writing quite a complicated Compact Framework application. Although this application was going to be complicated it needed to be very simple to use, as the customer's employees were not all computer literate.

I decided to take a wizard-like approach to the application. This had the benefit of guiding the users through their daily tasks in a way that offered them options which were relevant to what they are currently doing instead of overloading them with options in a menu. However, this approach was not only beneficial to my customer's users, it taught me something I think is very valuable. Applications should have an extra layer!

The problem is that many programmers will design their UI to reflect their database layout or their business classes. For example, a developer might create a "Vehicle" form, but when presented with this form what would a user do?
  1. View its service history?
  2. View a planned service schedule?
  3. View purchase + depreciation information?
  4. Hire it out to a customer?
If the developer does not know what the user wants to do with the vehicle in question then the only sensible thing to do is to show all of this information (maybe in tabs) and allow the user to do anything they want isn't it? Can you imagine a person who is non computer literate being shown such a complicated form and being expected to to just "get on with it"? I hope your training and support departments are well staffed! :-)

The solution is to present the user with a task instead of an instance of a business class. So instead of editing information within a complicated Vehicle form the user will enter a few basic details in order to complete a "TransferVehicleOwnershipActivity". The word "Activity" could easily be replaced with something like "Task", "Action", or "Process", but the general idea is that you present the user with something to do rather than presenting them with the object on which their actions will be performed.

Code in the UI

There are some things that simply don't belong in your business classes and this sort of code often gets written into the UI layer. Code in the UI layer should only concern itself with UI related issues, such as enabling/disabling controls. An example of this would be some kind of an email client.

When you open a message in your inbox it is automatically marked as read, but where should this code be written? I'd certainly agree that you should have a method on your IncomingMessage class
void MarkAsRead()
but this method still needs to be invoked! You may find yourself reaching for the Form.Load event, and I really wouldn't blame you if you did.
void IncomingMessageForm_Load(object sender, EventArgs e)
{
this.IncomingMessage.MarkAsRead();
}
but what if in the future you needed to create a web based version of your application? Obviously you'd expect to have to write some code into your WebForms but again this should be code to handle things like enabling/disabling UI controls. To get the same functionality you'd have to copy the code from your WinForms application.

Once you have finished copying all of the logic from your WinForms application and you have a functionally identical WebForms application what next? Someone changes one of the UI applications and forgets to update the other! We should have known better, having code like this causes a bad smell...
void IncomingMessageForm_Load(object sender, EventArgs e)
{
//If you update this code make sure you
//update IncomingMessage.aspx!
this.IncomingMessage.MarkAsRead();
}
This is exactly the sort of scenario that is easily solved by having an application layer!


Onions have layers

Onions have layers. This is why I have decided to name my application framework "Onion". I'll be playing around with Onion in my spare time and blogging about my experiences and decisions, so keep an eye out for part #2!

2 comments:

Dmitriy Nagirnyak said...

Pete, the Framework is going to be very interesting. Do you plan to have some online presentation after you'll have some beta?

Peter Morris said...

Hi Dmitriy

No plans for a presentation at all. As for having a beta, I don't yet know what I will do with the framework (sell, open-source, etc).