Shifting mindsets: MVC for .NET applications

Posted by Adrian O'Connor Fri, 04 May 2007 11:25:00 GMT

Change is something that blows gently through the world of computer programming. Old best-practices from years ago remain in use long after new best-practices have been invented.

For example, it might surprise you to learn that the ‘new kid on the block’, Ruby, has been around for over 10 years. That’s over twice as long as .NET! It is only now taking off, and I suspect that is because it is closely aligned with the current thinking of leading programmers.

.NET, as a framework, is slightly exceptional in that it gained quite a lot of traction in just a couple of years. That probably had more to do with Microsoft’s tactics (encouraging people to upgrade), and the strong need to replace ASP and VB6 than any particular special properties of .NET as a whole (after all, it’s little more than Java-in-Disguise).

One of the strange consequense is that we now have a relatively good language (C#), and a rather good technical framework, but that many practices and methods are lagging behind.

DAL & BLL

Let me be clear: DAL and BLL have no future. They are not a good way to structure an application. I want to say that DAL and BLL are dead, but sadly they are not. Developers throughout the Microsoft kingdom are still using BLL and DAL on a daily basis.

DAL and BLL were invented to solve a problem that doesn’t (and never did) exist for most developers. It allows you to run the ‘business’, the ‘data’ and the ‘presentation’ layers on seperate servers. The layers would communicate over COM interop. However, the business layer very rarely needs its own server.

Let me re-phrase that slightly: your application will never actually need to run DAL and BLL components on seperate servers, and you’re jumping through hoops for absolutely no reason whatsoever. (If you are actually running the layers on seperate servers, you could probably get a useful speed boost and save yourselves some major headaches by re-writing the application and consolidating).

What we’re doing when we force an application to use a BLL/DAL split is completely at odds with the natural structure of our programs.

Most often, what we get is something like the simple example below. This code is for an imaginary quotation system:

Presentation layer (the web page):
protected void Page_Load(...)
{
    QuotationManager qm = new QuotationManager(MyConnectionString);

    ActiveQuotationDataSet aqds = qm.GetActiveQuotations(m_txtField.Text);

    ActiveQuotationList.DataSource = aqds;
    ActiveQuotationList.DataBind();
}
Business layer (BLL)
public class QuotationManager
{
    private string _ConnectionString;

    ...

    public ActiveQuotationDataSet GetActiveQuotations(string SearchText)
    {
        QuotationDAL qd = new QuotationDal(_ConnectionString);

        return qd.GetActiveQuotations(SearchText);
    } 
}

I don’t really need to illustrate the data layer because we can assume that it will simply call a stored procedure and return the results to the business layer, which in turn will return the results to the web page, which finally binds the dataset to a list.

I see many applications with hundreds and hundreds of these methods, all of which perform this strange ritual of passing data back and forth while adding no value. Methods that add no value have no right to exist.

Additionally, the methods might as well be static. This is not object oriented programming—and this is especially true if what goes in and comes out of the BLL are nothing more than datasets and basic values.

This is basic procedural programming, a la VB6. It is 15 years out of date. It is time to move on.

You might be looking at the above example and thinking “actually, it’s not that bad, the BLL is just a little redundant”. For lists of data I can see this point, but I see it used for everything – loading a single object – saving that object – creating new objects – deleting objects. Everything.

MVC

MVC is a pattern described by the ‘gang of four’ in their famous book on software design patterns. This pattern is nothing like a Microsoft ‘pattern’ (an article on that to come soon). It is an idea, wrapped up in a concise description. It describes a nice way of using real-objects to create programme structure.

The M in MVC stands for Model. By Model, we mean classes that model your real-world situation, not helper classes or web pages.

V and C stand for View and Controller respectively. While it is difficult to completely seperate V and C in .NET, we can assume, for the time being, that the View is the ASPX pag and the Controller is the code-behind. That distinction is Good Enough.

When writing MVC we create objects (classes) that represent our real-world artifacts (our adjectives). These classes will have methods that describe the verbs we use when talking about the artifact. For example, instead of a Qutation DAL and DLL that have operations like ‘GetListOfQuotations()’, ‘GetSingleQuotation()’, ‘CreateNewQuotation()’, ‘SaveSingleQuotation()’, and so on, we would have a Quotation object:

public class Quotation
{
}

This would have methods analagous to those that we previously had in our BLL and DAL, but considered in relation to the operation it performs directly on or with the object:

Load(int QuotationId)
Save()
Delete()
Find()
static Quotation[] Search(string SearchText)

I’ll produce another article soon that gives examples of the way these classes and methods can be written and structured, and later I’ll also show you how you can express relationships between two such objects.

The upshot is that you can write code like this:

Quotation[] quotations = Quotation.FindAllByConsultant(ActiveConsultant);

Quotation quotation = Quotation.Load(_QuotationId);

Quotation q = new Quotation(ActiveConsultant);
q.Customer = txtCustomerName.Text;
q.Price = txtEstimatedCost.Text;
q.Save();

This is fully compatible with the concept of using relational databases to back the applications. We simply make the object responsible for loading/saving itself to/from the database. For high-performance databases we can use techniques like lazy load and batch fetching of data (with the use of Helper classes) to speed things up.

Finally, to replicate our earlier example:

protected void Page_Load(...)
{
    ActiveQuotationList.DataSource = Quotation.SearchActive(txtSearch.Text);
    ActiveQuotationList.DataBind();
}

It is clear to see that using models correctly is much neater.

What next?

I appreciate that there is much that I have not discussed in this article. For example, it would be good if I gave you an example of such MVC-based classes and web pages. It would also be useful to see how I structure my MVC solutions and projects. I intend to address these matters very soon and shall also provide sample code.

I also appreciate that if you are coming from a background of BLL/DAL it might be difficult to see at first what the difference truly is. Some of the differences are subtle, and you must remember that you are used to working in a certain way. I can, however, guarantee that if you are passionate about the art of programming that you will absolutely prefer this way of writing software once you are used to it.

But but but!

OK, what about heavy-use distributed apps running on server-farms? Don’t they absolutely need DAL/BLL? Well, if you went with Microsoft COM+ instead of one of the significantly better alternatives you either a) made a bad choice, b) employed Microsoft consultants or c) were paid/incentivised by Microsoft to do it that way.

DAL/BLL, even when used for its intended purpose, is just plain wrong.

Comments

Leave a response

Comments