Friday, May 14, 2010

Patterns & Practices

In last two posts, I have been talking about the layered architecture in ASP.NET applications. If you missed them, you might want to read the first part and the second part, just to get a better insight on the topic I am discussing today.

Dividing an application into multiple layers helps to:
  • Keep different concerns of components separate so that there is clear distinction between different parts e.g. keeping presentation and business logic separate rather than making a mess by mixing them up
  • Easy maintenance of the application
  • Enhanced clarity of the application making it easy to understand
  • Keep individual components cohesive and often efficient
  • Loose coupling between layers
  • Increase reusability, of course
Layered approach towards developing applications is not a new concept. Even with the age-old client-server architecture, we followed the two layer approach. Layered approach is often very synonymously used with tiered approach. Microsoft has a different take on this, and what they say is a layered approach is related to maintaining layers in application during the architecture stage while a tiered implementation is the layered approach of implementing the solution. I agree, but will not be discussing it much. We are talking about architecture here than implementation. But if you are interested, you can read Microsoft’s take on deployment patterns.

In the layered approach, what we have noticed so far is that an application is best divided into the presentation layer, the business logic layer and the data access layer. Each layer can further be divided making it an n-tier application, but mostly the basic architecture revolves around the above mentioned three layers. With large applications, you may also choose to create a separate class library for each of these layers. However, with service oriented architecture, things have changed a bit. The service oriented architecture has become very popular today since for applications that need to interact with external system, services are the best solution. If you are not familiar with service oriented architecture, you can refer this article on Windows Communication Foundation to get an insight. Using services, applications can expose themselves to third party applications or the external world the way they want to. This helps in sharing of data, enabling remote access in secure way and makes the application very extensible.

If services are to be used, additional responsibilities can be added by using an extra layer called “service interface” to the required layers. The architecture will somewhat look like below, but again variations are the way.


The diagram is self-explanatory, and I will keep the detailed discussion on this for later. Today, I only want to bring to your attention that there is no standard way about how to design an application, Depending on the requirement of the application, the development environment, the target environment and many other factors, you have multiple choices with architecture. Different solutions are best solutions for different situations. However, over a period of time as the software industry has evolved, there have been some standard solutions that are known to be best suited for certain scenarios. Such solutions or ideas that have evolved with time and provide you simple solutions to complex situations are known as “design patterns”. Microsoft themselves have a series of articles written on suggested patterns and practices they want to share with us when it comes to developing applications in Microsoft technologies. They focus much on the three tiered approach and service interface if required, something that I have briefly talked about above.

In articles to follow, I will talk about more on this topic, mainly on things like Model-View-Controller architecture that Microsoft is so crazy about. This is not a new concept; in fact if you read Erich Gamma and the team’s book Design Patterns: Elements of Reusable Object-Oriented Software, the first chapter talks about MVC and SmallTalk. But MVC has stood the test of time that made Microsoft go gaga over it today. MVC is based on the Observer Pattern, one of the most popular design patterns, that also forms the base of Java. There are concepts like Page Controller and Broker, and then there are concepts like Service Interface and Service Pattern. I will be adding more discussions on architecture in this blog. Stay around!

Wednesday, May 5, 2010

Introducing Business Objects

This is the second part of discussion on layered architecture in ASP.NET applications. I will extend the same examples, so you should read the first part here, or at least glance through the examples.

Let us extend the data access layer class to include a method to update the database.

ProductDataAccessLayer.cs

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class ProductDataAccessLayer
{
    string connectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ToString();

    public DataSet GetProducts()
    {
        SqlConnection conn = new SqlConnection(connectionString);
        DataSet dsProducts = new DataSet();
        SqlDataAdapter adapter = new SqlDataAdapter("SELECT ProductID,ProductName,UnitPrice FROM Products", conn);
        adapter.Fill(dsProducts);
        return dsProducts;
    }

    public int UpdateProduct(int productId, string productName, string quantityPerUnit, double unitPrice, int unitsInStock, int unitsOnOrder, int reorderLevel)
    {
        SqlConnection conn = new SqlConnection(connectionString);
        conn.Open();
        string sql = "UPDATE Products SET ProductName = @productName, QuantityPerUnit = @quantityPerUnit, UnitPrice = @unitPrice, UnitsInStock = @unitsInStock, UnitsOnOrder = @unitsOnOrder, ReorderLevel = @reorderLevel WHERE ProductId = @productId;";
        SqlCommand command = new SqlCommand(sql, conn);
        command.Parameters.AddWithValue("@productName", productName);
        command.Parameters.AddWithValue("@quantityPerUnit", quantityPerUnit);
        command.Parameters.AddWithValue("@unitPrice", unitPrice);
        command.Parameters.AddWithValue("@unitsInStock", unitsInStock);
        command.Parameters.AddWithValue("@unitsOnOrder", unitsOnOrder);
        command.Parameters.AddWithValue("@reorderLevel", reorderLevel);
        command.Parameters.AddWithValue("@productId", productId);
        return command.ExecuteNonQuery();
    }
}
Now in the business logic layer, we will add a wrapper to the update method. You might think that why we do not call the data access layer directly that calling in through the business logic layer. I agree, but when you have to add some business logic to the update method in future, then you will end up messing your code. Little extra effort makes your code more organized and keeps you away from problems in future.

ProductBusinessLogicLayer.cs
using System;
using System.Data;
using System.Data.SqlClient;

public class ProductBusinessLogicLayer
{
    public DataSet GetProducts()
    {
        DataSet dsUpdatedProducts = new DataSet();
        ProductDataAccessLayer productDAL = new ProductDataAccessLayer();
        dsUpdatedProducts = productDAL.GetProducts();
        foreach(DataRow row in dsUpdatedProducts.Tables[0].Rows)
        {
            double unitPrice = Double.Parse(row["UnitPrice"].ToString());
            row["UnitPrice"] = unitPrice + unitPrice * (12.5/100);
        }        return dsUpdatedProducts;
    }

    public int UpdateProduct(int productId, string productName, string quantityPerUnit, double unitPrice, int unitsInStock, int unitsOnOrder, int reorderLevel)
    {
        ProductDataAccessLayer productDAL = new ProductDataAccessLayer();
        return productDAL.UpdateProduct(productId, productName, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel);
    }
}
Now, what I have done in the presentation layer is that a few textboxes and an update button is added just above the grid. To make it easy for you, I have assigned some default values to the textboxes as well. When the update button is clicked, the values from all required textboxes is passed to the business logic layer update method and that in turns fires the update method in the data access layer where the actual update takes place.

Products.aspx
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        .style1
        {
            width: 125px;
        }
        .style2
        {
            width: 144px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table>           
 <tr>
  <th>Column</th>
                <th>Value</th>
        </tr>           
 <tr>
                <td>Id</td>
                <td>
                    <asp:TextBox ID="ProductId" runat="server">10</asp:TextBox>
                </td>
        </tr>
        <tr>
                <td>Name</td>
                <td>
                    <asp:TextBox ID="ProductName" runat="server">Ikura</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td>Quantity</td>
                <td>
                    <asp:TextBox ID="QuantityPerUnit" runat="server">12 - 200 ml jars</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td>Unit Price</td>
                <td>
                    <asp:TextBox ID="UnitPrice" runat="server">31.20</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td>Units in stock</td>
                <td>
                    <asp:TextBox ID="UnitsInStock" runat="server">31</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td>Units on order</td>
                <td>
                    <asp:TextBox ID="UnitsOnOrder" runat="server">0</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td>Reorder level</td>
                <td>
                    <asp:TextBox ID="ReorderLevel" runat="server">0</asp:TextBox>
                </td>
        </tr>
 <tr>
                <td></td>
                <td>
                    <asp:Button ID="btnUpdate" runat="server" Text="Update" onclick="btnUpdate_Click" />
                </td>
        </tr>
        </table>
        <asp:GridView ID="GridView1" runat="server"></asp:GridView>
    </div>
    </form>
</body>
</html>
Products.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Products : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductBusinessLogicLayer productBAL = new ProductBusinessLogicLayer();
        GridView1.DataSource = productBAL.GetProducts();
        GridView1.DataBind();
    }
    protected void btnUpdate_Click(object sender, EventArgs e)
    {
        ProductBusinessLogicLayer productBAL = new ProductBusinessLogicLayer();
        int res = productBAL.UpdateProduct(Int32.Parse(ProductId.Text), ProductName.Text, QuantityPerUnit.Text, Double.Parse(UnitPrice.Text), Int32.Parse(UnitsInStock.Text), Int32.Parse(UnitsOnOrder.Text), Int32.Parse(ReorderLevel.Text));
    }
}
Similarly, we can extend the class to include actions like inserting into or deleting from database.

Seems like we have a perfect architecture in hand, but I feel something is still wrong. You feel the same? Good! Let’s see where the problem is. We have an update method added that updates the fields in the Products table. I have intentionally left many columns of the table and not included them in the example to keep it simple. If the table is really huge with a number of columns, how lengthy our update methods’ parameter list is going to be. Also maintaining the fields by passing them as parameters is a complicated solution. We need a handy solution to maintain these fields.

To find a solution, let us think different. Here, a Product is an entity or say an object for us. All the fields we are talking about are its attributes. What if we create a class called Product that has the fields as its properties! We will be dealing with Product objects instead of a long list of parameters. Sounds better? Lets proceed with creating a Product class.

Product.cs
public class Product
{
    int productId = 0;
    string productName = string.Empty;
    string quantityPerUnit = string.Empty;
    double unitPrice = 0;
    int unitsInStock = 0;
    int unitsOnOrder = 0;
    int reorderLevel = 0;
 
    public int ProductId
    {
        get { return productId; }
        set { productId = value; }
    }
 
    public string ProductName
    {
        get { return productName; }
        set { productName = value; }
    }
 
    public string QuantityPerUnit
    {
        get { return quantityPerUnit; }
        set { quantityPerUnit = value; }
    }
 
    public double UnitPrice
    {
       get { return unitPrice; }
       set { unitPrice = value; }
    }
 
    public int UnitsInStock
    {
       get { return unitsInStock; }
       set { unitsInStock = value; }
    }
 
    public int UnitsOnOrder
    {
       get { return unitsOnOrder; }
       set { unitsOnOrder = value; }
    }
 
    public int ReorderLevel
    {
       get { return reorderLevel; }
       set { reorderLevel = value; }
    }
}
We will change our data access layer so that its update method accepts a Product object than a long list of parameters.

ProductDataAccessLayer.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class ProductDataAccessLayer
{
    string connectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ToString();
 
 public DataSet GetProducts()
    {
       SqlConnection conn = new SqlConnection(connectionString);
       DataSet dsProducts = new DataSet();
       SqlDataAdapter adapter = new SqlDataAdapter("SELECT ProductID,ProductName,UnitPrice FROM Products", conn);
       adapter.Fill(dsProducts);
       return dsProducts;
   }
 
    public int UpdateProduct(Product product)
    {
       SqlConnection conn = new SqlConnection(connectionString);
       conn.Open();
       string sql = "UPDATE Products SET ProductName = @productName, QuantityPerUnit = @quantityPerUnit, UnitPrice = @unitPrice, UnitsInStock = @unitsInStock, UnitsOnOrder = @unitsOnOrder, ReorderLevel = @reorderLevel WHERE ProductId = @productId;";
       SqlCommand command = new SqlCommand(sql, conn);
       command.Parameters.AddWithValue("@productName", product.ProductName);
       command.Parameters.AddWithValue("@quantityPerUnit", product.QuantityPerUnit);
       command.Parameters.AddWithValue("@unitPrice", product.UnitPrice);
       command.Parameters.AddWithValue("@unitsInStock", product.UnitsInStock);
       command.Parameters.AddWithValue("@unitsOnOrder", product.UnitsOnOrder);
       command.Parameters.AddWithValue("@reorderLevel", product.ReorderLevel);
       command.Parameters.AddWithValue("@productId", product.ProductId);
       return command.ExecuteNonQuery();
    }
}
Update the business logic layer also accordingly.

ProductBusinessLogicLayer.cs
using System;
using System.Data;
using System.Data.SqlClient;
public class ProductBusinessLogicLayer
{
    public DataSet GetProducts()
    {
        DataSet dsUpdatedProducts = new DataSet();
        ProductDataAccessLayer productDAL = new ProductDataAccessLayer();
        dsUpdatedProducts = productDAL.GetProducts();
  
       foreach(DataRow row in dsUpdatedProducts.Tables[0].Rows)
       {
          double unitPrice = Double.Parse(row["UnitPrice"].ToString());
          row["UnitPrice"] = unitPrice + unitPrice * (12.5/100);
       }
  
       return dsUpdatedProducts;
    }
 
    public int UpdateProduct(Product product)
    {
       ProductDataAccessLayer productDAL = new ProductDataAccessLayer();
       return productDAL.UpdateProduct(product);
    }
}
And our presentation layer will be where we will create the Product object from the values filled in the form. While the aspx file remains the same, the code-behind will now be:

Products.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Products : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ProductBusinessLogicLayer productBAL = new ProductBusinessLogicLayer();
        GridView1.DataSource = productBAL.GetProducts();
        GridView1.DataBind();
    }
 
    protected void btnUpdate_Click(object sender, EventArgs e)
    {
        Product product = new Product();
        product.ProductId = Int32.Parse(ProductId.Text);
        product.ProductName = ProductName.Text;
        product.QuantityPerUnit = QuantityPerUnit.Text;
        product.UnitPrice = Double.Parse(UnitPrice.Text);
        product.UnitsInStock = Int32.Parse(UnitsInStock.Text);
        product.UnitsOnOrder = Int32.Parse(UnitsOnOrder.Text);
        product.ReorderLevel = Int32.Parse(ReorderLevel.Text);
        ProductBusinessLogicLayer productBAL = new ProductBusinessLogicLayer();
        int res = productBAL.UpdateProduct(product);
    }
}
All we did was to add a new Business Object layer (the Product class), and we introduced a better way to deal with the Product as an object. I know you are excited and you are eagerly waiting for me to say that we have just seen 4-tier architecture with Business Objects coming into picture. We will call it Business Object Layer or better, Business Entities Layer.


The sad news is that not everyone agrees that the above follows 4-tier architecture. Often, the Business Entity Layer is considered as a sub layer of the Business Logic Layer, and hence still considered as 3-tier architecture. It won’t be a surprise if you find many applications that implement the Business Object Layer and the Business Logic Layer in the same class, while there are a number of examples where even the Business Logic Layer is spread over multiple layers of its own. Even with Data Access Layer, it is often a preferred choice to create a separate layer of Helper classes. When it comes to designing a solution, there is never a universal thumb rule!

Now that we have a very clear idea about tiered architecture including 4-tier architecture (let’s say), our next discussion will focus on layered architecture in more depth as we look at different ways of designing applications on Microsoft.NET framework.

By the way, the examples I included in this post and the earlier one, and the ones I will include further, are all meant to be simple and hence can be written in better and organized way. I just focused on defining clear layers and explaining the objectives to you. Writing neat code, managing object references and error handling are a few things that are clearly omitted. I leave them to you when you develop the real applications.

Monday, May 3, 2010

Layered architecture for ASP.NET applications

This is the first post in a series of discussion on using layered architecture in ASP.NET applications. I will start with the basics and try to elaborate concepts gradually so as to help developers who have just begun to understand the concept of layers in an application.

For quite a while, a tiered approach towards developing an application has been in the buzz. We hear people talking 2-tier, 3-tier, n-tier applications! What is a “tier” here? It means a layer. When a civil engineer is designing a building, he works on a blueprint of the building. In the blueprint, there is a clearly defined sketch of each part, viz. the base, the pillars, the first floor, the subsequent floors, electrical plans may be!  How the base is to be built and pillars placed so that the floors will be strong is very important consideration. The same applies to developing software applications. We are talking specifically about web applications here to be developed in ASP.NET and we will choose C# as the language for our examples.

A web application should be developed in layers. Each layer should be defined precisely to meet a distinct purpose. The interactions between each layer should be well thought of. In short,
  • Each layer should be designed for a specific purpose and a distinct objective.
  • Each layer should have a unique responsibility and hence not mess up with any other layer’s duties.
  • The interaction between the layers should be well defined. This is very important, failing which layered architecture will not only be an overhead but become clumsy and a havoc to maintain.
2-tier architecture

Consider a very simple ASP.NET application where there are aspx pages directly interacting with the database. For example, the application has an aspx page with a grid whose datasource is set to a dataset and the code for connecting the dataset and populating it is written in the code behind file. The aspx file and its code-behind file contains the content to be displayed on the browser (the web controls), business logic and code for interaction with database.

Here is an example:

Products.aspx
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:GridView ID="GridView1" runat="server">
                </asp:GridView>
            </div>
        </form>
    </body>
</html>
Products.aspx.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
public partial class Products : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ToString());
        DataSet dsProducts = new DataSet();
        SqlDataAdapter adapter = new SqlDataAdapter("SELECT ProductID,ProductName,UnitPrice FROM Products", conn);
        adapter.Fill(dsProducts);
        GridView1.DataSource = dsProducts;
        GridView1.DataBind();
    }
}
To explain the code in short, all we are doing is to execute a SELECT query against Products table in the Northwind database, and then bind a grid to the dataset. The page when loaded will display all products in the grid.

In this architecture, often to make code less cumbersome and keep things short and clean, you may also opt to write stored procedures that performs multiple tasks at the database end. Now, these stored procedures may also very often include some business logic code. For example, you may maintain transactions within a stored procedure and hence end up implementing a part of application’s business logic in the stored procedure or using constraints and triggers in the database. Here what we have is:

  • Application layer – the aspx page and its code- behind forms the application layer that delivers the presentation of data to the user and also contains the business logic.
  • Data access layer – the underlying database acts as the data access layer here. This means the entire database engine, including the database objects (e.g. tables, views) and the manipulating code (e.g. stored procedures).
It means you are using 2-tier architecture. Many of us think that because .aspx files have a separate code behind files, that counts as two different layers and hence ASP.NET applications are by default 3-tiered. Sorry, that’s not the way we can look at it. There is absolutely no difference in writing all the code behind part in the aspx files itself or separating it into a separate code behind file. Code-behind files only provide you a neater way to maintain your code and make sense out of it. Code-behind files do not contribute as a separate layer, unless you want to believe it that way.

3-tier architecture

In the above architecture, we found that although there was an attempt to make a distinction between the two layers, we could often end up having a part of our business logic implemented at the data access layer. To solve this problem, we can introduce a separate layer in between called “Business Logic Layer” where we will implement all business logic of the application and that will interact with the data access layer. This way, the data access layer keeps itself limited to handling database interaction and providing data to or updating data from the business logic layer.

We will see what I mean by a separate business logic layer. But before that, let us restructure the example code of 2-tier architecture from above. What we will do is put the database interaction code into a separate class. This class will be the actual “data access layer” for us and will be mainly and only used for database interaction purpose. The new class will be as:

ProductDataAccessLayer.cs

Our code-behind file will now look like:

Products.aspx.cs

Looks better? Remember, we still have only two layers: the ProductDataAccessLayer is just a cleanly maintained data access layer. The aspx file with its code behind forms the presentation layer.

Now lets say the unit price that is displayed for each product is without the VAT at present. The actual unit price should be inclusive of 12.5% VAT for each item. It would be a bad idea to place the logic into the data access layer since this class is meant to perform actions like select, insert, update and delete etc. And even if we put it there hardcoded, what if the government decides to change VAT to 13% percent tomorrow? What is the best solution then? Remember, we know that touching the data access layer for business logic changes is a bad idea, and we also know that the aspx and code-behind is best for presentation purpose.

Let us add a new layer, the business logic layer. So, here is the example code updated

This is our old data access layer:

ProductDataAccessLayer.cs

I will add a new class "ProductBusinessLogicLayer".

ProductBusinessLogicLayer.cs

And our aspx code behind will change to:

Products.aspx.cs

Notice that the newly introduced class “ProductBusinessLogicLayer” acts as an interface between the presentation and data access layer and has the business logic code for VAT calculation implemented. Any changes in business logic tomorrow will affect only this class. Yu do not have to be concerned about the data layer or the presentation layer while making changes to the business logic.

What we get is a clear separation of business logic and data interaction. Your application just became easily maintainable and extendable!

What we have here is:
  • Application layer – the aspx page and its code- behind forms the application layer that delivers the presentation of data to the user.
  • Business logic layer – the business logic part is moved into an intermediate layer.
  • Data access layer – the data access layer with the underlying database engine forms the data access layer.
So you have 3-tier architecture.

I will talk about implementing 3-tier architecture in detail in the next post, and also look at various methods to implement a 3-tier or n-tier architecture, with examples. Sometime later, we will also talk about the MVC architecture.