Designing a proper architecture of a database-driven application is not an easy task. I have tried many architecture concepts but
I've never been fully satisified. When it comes to write an application from scratch it's not a big deal if a design is bad, because
you don't have to worry about deep modifications in a code. But when a customer changes his mind, or the application is growing then suddenly appears a
need to modify it - if you have a wrong architecture it will require a lot of work to adapt to the new requirements (not to mention bugs that
happen when applying such modifications).
When I've started writing web applications I used to write so called "spaghetti code". This was long time ago, when I was learning PHP. It was terrible.
It required a lot of job to modify the code, there were a lot of code repetitions etc. I knew that I need to change it somehow. So I have learned CakePHP -
very good MVC framework, which forced a programmer to apply a proper architecture. When I've switched to the ASP.NET MVC, I've realized that M letter
is a very general concept here, and that there are many ways to design a business layer.
I've started by writing a general Model layer, which was responsible for all business related operations. For example, when I had a "clients" table
in a database then I had created ClientModel class, which was responsible for all operations on a "clients" table. Unfortunately it wasn't a good choice.
Given class contained a huge amount of code and was really difficult to manage. After that i had tried many other options of an application design,
but still with no luck.
Finally, after reading couple of blogs, i have found the architecture that, in my opinion, is a best choice for many data driven applications.
The core concept is so called service layer and repository layer. Take a look at the following diagram:
Follow the directions to see step-by-step through which layer the flow of an application is being realized.
Controller layer has a direct access only to the service layer. The repository layer is hidden for it. Only service classes have an access to the repositories.
Same rule applies to the ORM layer (which is optional).
Only repositiories have access to it. Models and ViewModels, are plain POCO classes that are used to transfer informations between layers.
What is the difference between them? Models are exact mappings of a tables in a database.
For example if we have a "clients" table, then we will have a POCO class that represents a single client:
namespace SampleApplication.Models
{
public class Client
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Item> ItemsBought { get; set; }
}
}
It's an example of a model that represents table "Clients" with columns "Id", "FirstName", "LastName" and is referenced in a One-To-Many related
table "Items" (each item belongs to one client). What about a ViewModel?
ViewModels are the extension of models. Let's say that we want to provide a user with some sort of statistics about clients. We have to create
another class (in ViewModel space) that will contain a total number of clients, total amount of money they have spent etc.:
namespace SampleApplication.ViewModels
{
public class ClientStatistics
{
public int TotalItemsBought { get; set; }
public int TotalMoneySpent { get; set; }
public List<Client> Clients { get; set; }
}
}
It's a plain class that represents statistics about clients. Models and ViewModels are being transfered through layers, and modified by them if
necessary. Finally they are pushed into a View layer and presented to the user.
I have created a sample project to demonstrate this architecture
The project is absolutely basic. I have created there an abstract layer for services and repositories, but since there are no IoC container they
are useless. Anyway it's important to provide some sort of abstraction, because it allows to easily mock up objects and implement unit tests of a service layer.
I'm not a fan of writing tests of every piece of code, but the most crucial parts of a system should be well tested before they are being uploaded to
the repository. Such an architecture allows to do it easily and provides a programmer with a well maintainable code.
There are also drawbacks of such solution. The biggest one is the increase of a time needed to implement an application. However, in my opinion it
doesn't really matter, because such architecture guarantees a high quality of an application. Of course every developer needs to implement classes
from each layer in such way that the code is as consistent as possible. Once he had done it - the application becomes easily scalable and maintainable.
In my next post I will write some of the most common solutions that I'm applying in my projects. After that I will upload a sample project with a proper
architecture, IoC container (Ninject for sure) and base classes for controllers and view pages. Stay tuned.