Saturday, June 4, 2011

ASP.NET MVC Framework

This is the first post of ASP.NET MVC series, as promised a while earlier. There is enough information on the Internet already by now, that ASP.NET MVC 3 is already released. The posts will contain links to the required sites and of course a step by step guide to develop applications using MVC.

ASP.NET MVC Framework site is the central place where (mostly) all the information regarding installing and using MVC framework is available. The current release MVC3 can also be downloaded from here.

What is MVC? MVC stands for Model-View-Controller. In my earlier posts on framework, I detailed the 3-tiered architecture of software development and explained the service-oriented concepts too. MVC is a different story altogether. It is a new way to developing applications, but a better way than the rest. I personally, like MVC the most (since I read about it in the the Design Patterns book by Erich Gamma and team although it was a short introduction in SmallTalk there). In MVC pattern, there are obvious three components (call them layers):
  1. Models are components of application that maintain state. Think of them as a combination of data access layer that provides data from the server to the interface and stores them back and business logic layer consisting of some business logic to manipulate data.
  2. Views are components of application that display the user interface. Think of them as the presentation layer consisting HTML output renders.
  3. Controllers are components of application that handle events and act as the communication bridge between Models and Views. They are responsible of handling user interaction and resulting in rendered views.
Although, I tried to relate these layers to the 3-tiered architecture, to help those familiar with 3-tiered pattern to correlate, there is a huge difference in practice. To understand MVC, however, one must keep aside the other classic patterns that I discussed earlier aside. MVC is a new adventure.

To start with, you need to have the usual Visual Studio development environment. Get Visual Studio Express and SQL Server 2008 Express for the experiments, if you do not have them already. MVC is not going to change anything existing. The code will be written in C# or VB.NET, the ASPX, ASCX and master pages will remain; so nothing scary. MVC is an addition to the already charming bouquet of development tools and frameworks Microsoft provides. And by far it is the best (personal opinion).

Install MVC from the ASP.NET MVC site. To install MVC 2, .NET Framework 3.5 is required and for MVC 3, .NET Framework 4.0 is required.


Once the MVC framework is installed, a new project templates are installed, that can be used to develop MVC applications. For this post, I will choose MVC 2 template (and not choosing the option to create unit test project for now). In next posts, I will discuss MVC 3 and Razor view as well. On choosing the MVC 2 template, Visual Studio creates a solution with the project. What we notice is that a few files are already existing in the project.

Note the folders Controllers, Models and Views. As described above, these three folders contain their respective classes, i.e. all controller classes are placed in Controllers folder and so on. When the project is run, it opens the home page. But this should come as a surprise and a question to many who are new to MVC. First, there is no default.aspx page. Second, the Index.aspx page is inside Views folder, not in the root directory. How is the page even fetched? And why does not the URL show the page name that is being called!

Welcome to the first MVC culture shock! I said earlier, MVC is a completely new adventure. The most important thing to notice in MVC is that the URL does not map to a physical file (e.g. an aspx page). Instead, the URL maps to a controller class. So instead of a URL like http://localhost/Library/Book.aspx which would open the Book.aspx file, the URL in MVC looks like http://localhost/Library/Book and it maps to BookController class. We will talk about URL mapping again later.

Now, about the question on how does the server know which page to open as the default page. The secret lies in Global.asax file.
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }
The Global.asax.cs file has a method named RegisterRoutes. This is the location where the URL mapping is listed out. We will talk about routes again when we talk about URL routing, but for now, refer the section where a MapRoute method is called mentioning the Default route should be the "Home" controller and the action (the view action) should be Index. This is why the first time the site runs, the HomeController class is called and its method Index is called (since action was specified as Index). The Index action actually returns a type ActionResult which is nothing but a view named Index which should exists in Views/Home/Index.aspx. This should give a glimpse on how the folders are structured.

To summarize, the Controllers are the entry point of an application. The URL maps to a Controller class. A controller class contains action methods. For each controller, a folder is created in Views folder and in this folder, the views for each action specified is placed. So, if HomeController class has two action Index and About, the folder Views/Home should contain Index.aspx and About.aspx. If the URL provides an action to be called, then the specific action of the controller is called, otherwise the Index action is called by default. So a typical URL would be of the following format:

/Controller/Action/Parameters

Lets try this by creating a new controller. To add a new controller, right click on Controllers folder in solution explorer and choose Add > Controller. A new controller class is added.
namespace Library.Controllers
{
    public class BookController : Controller
    {
        //
        // GET: /Book/

        public ActionResult Index()
        {
            return View();
        }
    }
}
Notice a few things. The controllers belong to the ProjectName.Controllers namespace by default. Each controller class inherits from the Controller base class. And an action Index is added by default.

The controller gets data from Model and feeds it to the View. So, lets add a model class. Right click on Models folder in solution explorer and choose "Add > Class". Notice the namespace Projectname.Models.
namespace Library.Models
{
    public class Book
    {
        public int bookID;
        public string bookName;
        public string authorName;

        public Book(int ID, string name, string author)
        {
            bookID = ID;
            bookName = name;
            authorName = author;
        }
    }
        
    public class BookCollection
    {
        List<Book> booksCollection = new List<Book> { };

        public void AddBook(int bookID, string bookName, string author)
        {
            booksCollection.Add(new Book(bookID, bookName, author));
        }

        public List<Book> List()
        {
            return booksCollection;
        }
    }
}
Let me explain what we have here. In the namespace Library.Models (where Library is my project name), I have created two classes: Book and BooksCollection. The Book class is a simple entity structure holder with a constructor. The BookCollection class has methods to add books to a local list and to return the list. To start with, we have no books! ;).

For this example (since we do not have a database), I will fill the data through controller. Practically, data should flow from database into model and then controller should pass the model to view. So now our Index method in BookController class should be like:
public ActionResult Index()
{
    Models.BookCollection books = new Models.BookCollection();

    books.AddBook(1, "Five point someone", "Chetan Bhagat");
    books.AddBook(2, "2 states", "Chetan Bhagat");
            
    return View(books);
}
Simple enough. The model is populated with two book details and passed to the view. Now, lets add a view for the Index action. The easiest way to do this is to right click on the Index method in the code window of HomeController class and choose "Add view", choosing the default master page for now. A folder for the new controller is added in Views folder and an Index.aspx file is created. Lets use the message to display it in the content section.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Library.Models.BookCollection>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 Index
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Book List</h2>

    <div>
        <% foreach (Library.Models.Book book in Model.List())
            { %>
            <li><%: book.bookID.ToString() + ": \"" + book.bookName + "\" by " + book.authorName + "." %></li>
        <% } %>
    </div>

</asp:Content>
Notice in the page directive that I used Library.Models.BookCollection to be the model that the view will be dealing with. (so now a reference to Model in the view page refers to BookCollection model instance passed from controller).

Run the project and use the URL http://localhost:[port]/Library/Book to invoke the BookController's default Index action. There you go! A simple example to use Model-View-Controller.

Lets look at few noticeworthy points before I close this post. The controller class imports from "System.Web.Mvc" which is important because this is the namespace that contains classes to support MVC framework. e.g. ViewData is a dictionary object that is defined in this namespace.Also, the use of "<%:" is new in the view page. This syntax was introduced in .NET framework 4 and it encodes the HTML output before it is sent to output buffer, in contrast to "<%=" that did not encode the HTML before buffering the output.

Keeping it simple for the first post, I will close it here today. ASP.NET MVC has matured and is in its 3rd version now. And there is lots can be done with MVC that I will post subsequently.

Saturday, April 16, 2011

Code Metrics

Well, back again. Microsoft has been using FxCop for its own code analysis purposes for long. With Visual Studio 2008, the code analysis rules were integrated into the IDE itself under the new "Analyze" menu. I will leave static code analysis for some other day. Right now, I am interested in the "Code Metrics" option under Analyze.

Code metrics is a set of measures that helps you to analyze your code and indicates the complexity or maintainability of the code. There are a number of measures out there that you can use to analyze our code. Microsoft uses the best few and provides statistics about your code. Visual Studio provides you statistics on the lines of code, class coupling, depth of inheritance and most importantly, the cyclomatic complexity. Open a project in Visual Studio, go to "Analyze" and select "Calculate Code Metrics..." option.


When the code metrics is calculated for the project, the results are displayed in a window. The result window contains the metrics for each and each of their methods (functions).

 
Against each class/method, what we can see is a numeric value as Maintainability Index, Cyclomatic Complexity, Depth of Inheritance, Class Coupling and Lines of Code. So what these terms really mean?

  • Cyclomatic Complexity
                  Cyclomatic complexity is defined at the method level. It indicates the structural complexity of the method. The cyclomatic complexity of a method is the count of the total number of independent paths in the method. So, each branch (if, else, select etc.) and each loop (for, while etc.) counts towards the cyclomatic complexity of the method. The more number of branches and loops within a method, the higher the complexity. The cyclomatic complexity of a method has a direct impact on the maintainability and testability of the code, and it has been one of the successful and useful measures of code complexity.

                 The following table explains the range of values and the associated risk.

Cyclomatic Complexity Risk Evaluation
1-10 simple module, not risky
11-20 moderately complex, moderate risk
21-50 complex method, high risk
>50 a very complex and unstable method, very high risk

Further details on how to calculate cyclomatic complexity can be found here.

  • Depth of Inheritance
                 The depth of inheritance is defined at the class level. It is the number of classes that the current class extends till the root of the class hierarchy. The deeper the hierarchy, he higher is the complexity of code.

                 A class hierarchy up to depth 6 is acceptable. Anything higher should be subjected to a revision of the class hierarchy.

  • Class Coupling
                 Class Coupling is defined at the class level. It is the number of classes the current class is coupled with (interacts with). The interaction can be in any form e.g. function calls, returning parameters etc. A class is considered more stable if it is less coupled (i.e. it is more cohesive in nature). Less coupling means there are lesser chances of the class breaking other classes or getting broken by a change in other classes.

                 Although it highly depends on the design and architecture followed, a coupling indicator above 30-40 should be subjected to revision.

  • Lines of Code
                 Lines of code indicate the number of lines of code in a method or a class. Visual Studio counts the number of lines in the IL code and can differ from the lines of code in the source file. This is an old measure of code complexity and can be highly misleading. However, it must be accepted that a method or a class of a huge size is not easily maintainable.

                 While there is no hard and fast rule on the range of lines of code a method or a class should have, it is advised to limit a method below 60 lines of code and a class below 1500 lines of code.

  • Maintainability Index
                 Maintainability Index is a calculated measure based on the above measures that Visual Studio uses to indicate whether method or a class is maintainable. Maintainability Index per module is calculated using the following formula:

Maintainbility Index = 171 - 5.2 * avg (Halstead Volume) - 0.23 * (Cyclomatic Complexity) - 16.2 * avg(Lines of Code)

, where Halstead volume is a measure calculated from the number of operators and operands in the module.

                 A module is considered maintainable if its maintainability index is in a higher range. The index is calculated in a range of 0-100, where 0 being the least maintainable and 100 being the most maintainable. The following table explains the range of values and their meaning.

Maintainability Index Maintainability of Code
20-100 Code is very maintainable (indicated as green)
10-19 Code is moderately maintainable (indicated as yellow)
0-9 Code has poor maintainability (indicated as red)

Although an index above 20 is considered maintainable, it is advised to keep the maintainability index higher than 50 for well maintainable code.

Code metrics is is available only in Visual Studio Team System editions, not in Professional or Standard Editions. However, there are other utilities available including the command line based Code Metrics PowerTool from Microsoft itself that can serve the purpose if you do not have the Team System editions. I will write another post on how to use the PowerTool, but hope this post helps you to understand and get familiar with code metrics in Visual Studio.