And now for something completely different

May 23, 2008 at 9:45 AMAndre Loker

It feels like Monday morning to me, so bear with me.

Found at http://xkcd.com/221/

Posted in: Off topic

Tags:

Why dependency injection rocks

May 19, 2008 at 12:59 PMAndre Loker

Since I started using IoC containers like Castle Windsor or Spring 18 months or so ago the way I write code has changed quite a lot. Let me give an example. Let's assume I am currently writing the code to create a user account that can be used to login into an application. Let us further assume that I am using the following domain driven architecture:

architecture

That is, we have a domain model that is surrounded by a service layer. The latter is accessed by the application. Data moved back and forth between application and service layer comes in the form of data transfer objects. The service layer and domain model have access to the repositories that can be used to access all entities in the domain.

Now that you have an overview of the architecture, let us assume that I am busy writing a class in the service layer that handles account related stuff. Let us call it AccountService. In this case I want to write a method that creates a new account in the system. This method has some additional constraints:

  • Only currently logged in administrators may create an account
  • The username and email must not already be in use
  • The code should run within a single database transaction. This constraint actually is a consequence of the previous one: checking for duplicate user names/email addresses and saving a new account should be atomic.
  • We would like to apply some general exception handling policies

Let's have a look at the method filled with pseudo code comments:

   1: namespace BeautyOfInjection.Service {
   2:     public class AccountService {
   3:         /// <summary>
   4:         /// Creates a new account.
   5:         /// </summary>
   6:         /// <param name="userName">User name for the new account.</param>
   7:         /// <param name="email">E-mail address for the new account.</param>
   8:         /// <remarks>
   9:         ///  Only administrators can create new accounts. 
  10:         /// </remarks>
  11:         public void CreateAccount(string userName, string email) {
  12:             // start transaction
  13:             // check whether current user has permission to create an account
  14:             // check whether user name and email address are unique
  15:             // create a new account instance
  16:             // save instance to db
  17:             // commit transaction
  18:             // on failure: rollback transaction and handle exception
  19:         }
  20:     }
  21: }

This should be straight forward so far. Let us begin to write code. First, we start off with the transaction handling, but let us try to think in terms of dependency injection. Personally I think that the burden of transaction handling should not lie on a single method in the service layer. Maybe we want CreateAccount to run within a larger transaction. What we need is the possibility to declare the requirement of a transaction. All transaction pluming should then be handled externally. This is a good example of separation of concerns. To achieve this, let us define an interface that allows us handle transaction requirements.

   1: using System;
   2:  
   3: namespace BeautyOfInjection.Persistence {
   4:  
   5:     /// <summary>
   6:     /// Allows the client to declare its requirement for a transaction.
   7:     /// </summary>
   8:     public interface ITransactionControl{
   9:         /// <summary>
  10:         /// Opens a new transaction context.
  11:         /// </summary>
  12:         /// <returns>A new transaction context</returns>
  13:         ITransactionContext EnsureTransaction();
  14:     }
  15:  
  16:     /// <summary>
  17:     /// A (possibly nested) transaction scope.
  18:     /// </summary>
  19:     public interface ITransactionContext : IDisposable {
  20:         /// <summary>
  21:         /// Considers this transaction context a success.
  22:         /// </summary>
  23:         /// <remarks>
  24:         /// If <see cref="VoteRollback"/> is not called by this transaction context or 
  25:         /// any parent or child context, the database transaction will be committed.
  26:         /// </remarks>
  27:         void VoteCommit();
  28:  
  29:         /// <summary>
  30:         /// Votes for a rollback on this transaction.
  31:         /// </summary>
  32:         /// <remarks>
  33:         /// Calling this method will finaly cause a rollback of the database transaction.
  34:         /// </remarks>
  35:         void VoteRollback();
  36:     }
  37: }

The actual working of those interfaces is not that important here. Let us just assume that we can declare the requirement for a transaction using EnsureTransaction and the returned ITransactionContext can be used to decide whether the transaction should commit or rollback. This design by the way resembles the Active Record transaction management. So, how do we gain access to a ITransactionControl instance? Remember that we are looking for inversion of control with dependency injection. We should therefore declare the need for an ITransactionControl object somewhere the IoC container recognizes. Two common approaches are Constructor Injection and Setter Injection. I chose for setter injection. With the new C# 3.0 auto property syntax it's a snap to declare the property.

   1: public class AccountService {
   2:     // This dependency will be injected by the container
   3:     public ITransactionControl Transactions { get; set; }
   4:  
   5:     /// <summary>
   6:     /// Creates a new account.
   7:     /// </summary>
   8:     /// <param name="userName">User name for the new account.</param>
   9:     /// <param name="email">E-mail address for the new account.</param>
  10:     /// <remarks>
  11:     ///  Only administrators can create new accounts. 
  12:     /// </remarks>
  13:     public void CreateAccount(string userName, string email) {
  14:         // start transaction
  15:         using (var txn = Transactions.EnsureTransaction()) {
  16:             // check whether current user has permission to create an account
  17:             // check whether user name and email address are unique
  18:             // create a new account instance
  19:             // save instance to db
  20:             // commit transaction
  21:             txn.VoteCommit();
  22:             // on failure: rollback transaction 
  23:             // (will be done automatically if VoteCommit is not called before dispose)
  24:         }
  25:         // ... and handle exception
  26:     }
  27: }

This was easy. We simply do not care about were we get our ITransactionControl instance from. We simply assume that it will be resolved by the IoC container or explicitly set during a unit test.

Next step, check that the current user has the permission to create the account. I like to have this kind of code in a separate class. It simplifies unit testing a lot. So let us define a new dependency interface:

   1: using System.Security;
   2:  
   3: namespace BeautyOfInjection.Security {
   4:     /// <summary>
   5:     /// 
   6:     /// </summary>
   7:     public interface IPermissions {
   8:         /// <summary>
   9:         /// Checks that the current user may create a new account.
  10:         /// </summary>
  11:         /// <exception cref="SecurityException">Permission was not granted.</exception>
  12:         void TryCreateAccount();
  13:     }
  14: }

Before I return to CreateMethod, I'll define another dependency interface, regarding exception handling. Resemblance with the Exception Handling Block is no coincidence:

   1: using System;
   2:  
   3: namespace BeautyOfInjection.Service {
   4:     /// <summary>
   5:     /// Handles exceptions
   6:     /// </summary>
   7:     public interface IExceptionHandler {
   8:         /// <summary>
   9:         /// Handles the exception and returns whether the original exception should be rethrown.
  10:         /// </summary>
  11:         /// <param name="exception">The exception.</param>
  12:         /// <returns></returns>
  13:         bool HandleAndCheckForRethrow(Exception exception);
  14:     }
  15: }

Let us see how far we are with CreateUser:

   1: using System;
   2: using BeautyOfInjection.Persistence;
   3: using BeautyOfInjection.Security;
   4:  
   5: namespace BeautyOfInjection.Service {
   6:     public class AccountService {
   7:  
   8:         #region dependencies
   9:         public ITransactionControl Transactions { get; set; }
  10:         public IPermissions Permissions { get; set; }
  11:         public IExceptionHandler ExceptionHandler { get; set; }
  12:         #endregion
  13:  
  14:         /// <summary>
  15:         /// Creates a new account.
  16:         /// </summary>
  17:         /// <param name="userName">User name for the new account.</param>
  18:         /// <param name="email">E-mail address for the new account.</param>
  19:         /// <remarks>
  20:         ///  Only administrators can create new accounts. 
  21:         /// </remarks>
  22:         public void CreateAccount(string userName, string email) {
  23:             try {
  24:                 // start transaction
  25:                 using (var txn = Transactions.EnsureTransaction()) {
  26:                     // check whether current user has permission to create an account
  27:                     Permissions.TryCreateAccount();
  28:  
  29:                     // check whether user name and email address are unique
  30:                     // create a new account instance
  31:                     // save instance to db
  32:  
  33:                     // commit transaction
  34:                     txn.VoteCommit();
  35:                 }
  36:             } catch (Exception e) {
  37:                 // on error, handle exception
  38:                 if(ExceptionHandler.HandleAndCheckForRethrow(e)) {
  39:                     throw;
  40:                 }
  41:             }
  42:         }
  43:     }
  44: }

Not bad, if you ask me. Throw in some more external depencies: we want to access entities using the repository pattern, so let's define a account repository interface. Furthermore, we want accounts to be created using a factory. I think that the factory would also be a useful place to check for uniqueness of user name and email. I am always a bit struggling on this topic: on the one hand I want the domain model to use the repositories as little as possible. On the other hand I do not like it when business rules (i.e. uniqueness of email and user name) are not checked in the domain model. As I consider the factory to be part of the model, checking those rules in the factory seems reasonable to me. Be aware though that if you support changing a user name/email address you will have to check for uniqueness again and this time not in the factory. So you might as well put the uniqueness check into the model class (and skip the factory altogether). Anyway, this is just an example, so let's stick to the factory/repository pair.

Here are the required interfaces:

   1: namespace BeautyOfInjection.Model {
   2:     /// <summary>
   3:     /// An account
   4:     /// </summary>
   5:     public interface IAccount {
   6:         string UserName { get; }
   7:         string EmailAddress { get; }
   8:     }
   9:  
  10:     /// <summary>
  11:     /// 
  12:     /// </summary>
  13:     public interface IAccountFactory {
  14:         /// <summary>
  15:         /// Creates a new account instance.
  16:         /// </summary>
  17:         /// <param name="userName">Name of the user.</param>
  18:         /// <param name="email">The email.</param>
  19:         /// <returns>
  20:         /// The newly created account.
  21:         /// </returns>
  22:         /// <remarks>
  23:         /// The method validates the user name and email and ensures that both are unique.
  24:         /// </remarks>
  25:         /// <exception cref="ValidationException">
  26:         /// The user name and/or email were not valid or not unique.
  27:         /// </exception>
  28:         IAccount Create(string userName, string email);
  29:     }
  30:  
  31:     /// <summary>
  32:     /// 
  33:     /// </summary>
  34:     public interface IAccountRepository {
  35:         void Save(IAccount account);
  36:         IAccount GetAccountByUserName(string userName);
  37:         IAccount GetAccountByEmail(string email);
  38:     }
  39: }

ValidationException would be a custom exception type that is used for business rule violations.

Now we are ready to present the final version of CreateAccount:

   1: using System;
   2: using BeautyOfInjection.Model;
   3: using BeautyOfInjection.Persistence;
   4: using BeautyOfInjection.Security;
   5:  
   6: namespace BeautyOfInjection.Service {
   7:     public class AccountService {
   8:  
   9:         #region dependencies
  10:         public ITransactionControl Transactions { get; set; }
  11:         public IPermissions Permissions { get; set; }
  12:         public IExceptionHandler ExceptionHandler { get; set; }
  13:         public IAccountFactory Factory   { get; set; }
  14:         public IAccountRepository Repository{ get; set; }
  15:         #endregion
  16:  
  17:         /// <summary>
  18:         /// Creates a new account.
  19:         /// </summary>
  20:         /// <param name="userName">User name for the new account.</param>
  21:         /// <param name="email">E-mail address for the new account.</param>
  22:         /// <remarks>
  23:         ///  Only administrators can create new accounts. 
  24:         /// </remarks>
  25:         public void CreateAccount(string userName, string email) {
  26:             try {
  27:                 // start transaction
  28:                 using (var txn = Transactions.EnsureTransaction()) {
  29:                     // check whether current user has permission to create an account
  30:                     Permissions.TryCreateAccount();
  31:  
  32:                     var account = Factory.Create(userName, email);
  33:                     // the previous line would have thrown an exception
  34:                     // if userName and/or email had been invalid/not unique
  35:  
  36:                     // add instance to repository
  37:                     Repository.Save(account);
  38:  
  39:                     // vote for transaction commit
  40:                     txn.VoteCommit();
  41:                 }
  42:             } catch (Exception e) {
  43:                 // on error, handle exception
  44:                 if(ExceptionHandler.HandleAndCheckForRethrow(e)) {
  45:                     throw;
  46:                 }
  47:             }
  48:         }
  49:     }
  50: }

You see that the service layer class becomes a mediator between all the external dependencies. What are the advantages of this design?

  • Separation of concerns to the max, every aspect is neatly extracted to a separate interface
  • High (unit-) testability. As we can mock/stub any of the external dependencies we have full control over their behavior. In this case we can easily test whether the method correctly requests a transaction, votes commit on success, handles exceptions, checks the required permissions etc. by simply passing mock objects with the right expectations.
  • The code in the service layer gets simplified. We can concentrate on the core functionality of CreateAccount instead of cluttering the code with loads of unrelated code.
  • We do not need to worry about how dependencies get injected. Just add the dependencies as e.g. properties (or constructor arguments) and assume that they will be provided externally. Of course you ultimately have to setup your IoC container or provide mocks/stubs. But while writing AccountService you just don't care.

Note: you will want to extract an interface from AccountService (say: IAccountService). This can then be used to define dependencies on this service in other layers, for example in your controllers (if you use an MVC framework like MonoRail).

Posted in: Snippets | Patterns

Tags: , , , ,

MonoRail and Windsor integration

May 18, 2008 at 9:00 PMAndre Loker

Although the procedure of enabling Windsor Container integration is explained quite well in the documentation, I ran into some trouble today. As required by the Windsor integration I made my HttpApplication instance implement IContainerAccessor, created a WindsorContainer instance in Application_Start and returned that instance in the Container property. Still the MonoRail runtime was complaining:

The container seems to be unavailable in your HttpApplication subclass

What went wrong? The problem was that the IWindsorContainer field in the HttpApplication was not static. As described in my previous post (which I only wrote just because of that problem) multiple instances of HttpApplication can be created by the ASP.NET runtime to serve multiple requests at once. As a consequence only the first instance of HttpApplication that was created had a valid container assigned to its field. The first subsequent request found only a null value and raised the exception mentioned above.

Register IContainerAccessor in Windsor

If you want to register your HttpApplication as a IContainerAccessor in Windsor I'd recommend something along this line:

   1: public class ContainerAccessor : IContainerAccessor {
   2:     public IWindsorContainer Container {
   3:         get {
   4:             // lookup container accessor 
   5:             return WindsorContainerAccessorUtil.ObtainContainer();
   6:         }
   7:     }
   8:  
   9:     public static void RegisterAtContainer(IWindsorContainer container){
  10:         container.AddComponentLifeStyle<IContainerAccessor, ContainerAccessor>(LifestyleType.Singleton);
  11:     }
  12: }

Of course you can always just register the container on itself to have it injected into components.

Posted in: Castle

Tags: , ,

HttpApplication instances

May 18, 2008 at 8:42 PMAndre Loker

I always thought the HttpApplication class defined in global.asax would only be instantiated once for the web application. This is not the case. ASP.NET may instantiate many instances of HttpApplication as required. In fact, it will create an instance of the class for each request that is handled in parallel on the server. That is, seven requests being executed at the same time will result in at least seven instances of the application class.

Important facts:

  • Multiple HttpApplication instances can be created by ASP.NET during runtime
    • At least one for each parallel request
  • Each HttpApplication will handle a single request
    • No two parallel requests will have access to the same HttpApplication instance
    • This means that instance fields on the HttpApplication are thread safe and can be used exclusively for the current HttpRequest
  • HttpApplication instances are reused
    • The same HttpApplication instance is allowed to be used for multiple (consecutive, not concurrent) requests
    • This means that the application instance might be around for quite some time without being garbage collected. If you use instance fields that reference expensive resources you should clean up those instance fields in Application_EndRequest
  • Application_Start and Application_End are called only once per running web application. Of course, each time the application pool is recycled or the webapplication is restarted the two events are called again.
    • The default template for global.asax.cs implements Application_Start and Application_End as instance methods of Global (the class derived from HttpApplication). This is misleading as the programmer might be tempted to initialize instance fields in those event handlers. As the handlers are called only once on the first instance of the HttpApplication class all subsequently created instances of the class won't have their instance fields initialized correctly (i.e. with the semantic as implied by the Application_Start implementation)
    • Conclusion: do not set any instance fields in Application_Start or Application_End unless you don't need them for more then one (i.e. the first) request

Posted in: ASP.NET

Tags: , ,

Haml for MonoRail

May 16, 2008 at 12:20 AMAndre Loker

It would be soooo cool if there was an HAML based view engine for MonoRail. For ASP.NET MVC one is already being made.

The following example is shamelessly ripped off of Andrew Peter's site:

ASPX:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" 
    CodeBehind="List.aspx" Inherits="MvcApplication5.Views.Products.List" Title="Products" %>
<asp:Content ContentPlaceHolderID="MainContentPlaceHolder" runat="server">
  <h2><%= ViewData.CategoryName %></h2>
  <ul>
    <% foreach (var product in ViewData.Products) { %>
      <li>
        <%= product.ProductName %> 
        <div class="editlink">
          (<%= Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID })%>)
        </div>
      </li>
    <% } %>
  </ul>
  <%= Html.ActionLink("Add New Product", new { Action="New" }) %>
</asp:Content>

NHAML:

%h2= ViewData.CategoryName
%ul
  - foreach (var product in ViewData.Products)
    %li
      = product.ProductName 
      .editlink
        = Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID })
= Html.ActionLink("Add New Product", new { Action="New" })

MonoRail deserves this, too!

Update 6/6/2008: cool, there's an upcoming NHAML view engine for MonoRail

Posted in: Castle

Tags: , ,