Semi Statics

time to read 6 min | 1111 words

I talked about Static pros and cons before. I also promised that I would post my solution to that. To sumrise for those who don't want to read the previous posts:

  • Statics make it easy to access functionality from anywhere in the application.
  • They allow cross cutting concerns to be handled easily by infrastructure code.
  • It is hard to make them safe for multi threading.
  • It is usually hard to test code that uses singletons.

My solution for that is to use a piece from Rhino Commons, the Local.Data hash table. This allow me to put objects that are assured to be local to my current execution, regardless of whatever I am running in a windows or web scenario.

Once I have that, I can create this class:

As you can see, this is a static class* with. The implementation is trivial:

public static class Context

{

       const string DbConnectionKey = "Db.Connection.Key";

 

       public static IDbConnection DbConnection

       {

              get

              {

                     IDbConnection connection = Local.Data[DbConnectionKey] as IDbConnection;

                     if (connection == null)

                           throw new InvalidOperationException("Context was not initialized properly");

                     return connection;

              }

       }

 

       public static IDisposable Initialize(IDbConnection connection)

       {

              LocalData.Data[DbConnectionKey] = connection;

              return new DisposableAction(delegate { Dispose()); }) ;

       }
  . . .

}

The usage is also simple, let us say that I want to do some operation that require the database.  I have some infrastructure code that handles the basic interactions. On the web, I usually use an Http Module that takes care of initializing and disposing the context. On Win Forms, I use the controller in MVC to take care of this (if the application is complex enough to demand this). The simplest scenario is a Windows Service. There I have some sort of coordinator that dispatch work, and it takes care of it, like this:

public void DispatchWork()

{

       IDbConnection connection = GetConnectionFromSomewhere();

       using (Context.Initialize(connection))

       {

              //Do work within this context

                }
}

I initialize the connection, and then I can do the rest of my work (usually by calling other classes who pre-condition is that the context is initialized).  I found that this approach combines both thread safety and the convenience of using static. Because there is only a single thread of execution (even if it is a logical one), there will not be surprises because of this. In the first post about statics, I gave an example of the IDbConnection blowing up because two threads access it in the same time. Using this approach, there is only a single thread, and it is consistent. If it will blow up, it will always blow up.

I may be in the middle of process an IDataReader, and call another method that tries to read from the database, this will fail immediately, since the second method will try to read and that is (generally) not allowed when a data reader is already opened. There are no surprises there, and that is very important thing.

To talk in patterns, it is a Service Locator. Personally, I find that the Context class becomes the speed dial into the rest of the application. I try to keep my context as lightweight as possible, but I put common methods there as well (see the IsAllowed() above for example of that). One thing that I insist on is that everything that the context allow access to will be mockable. Usually this mean returning an interface. When I need to test the code, I simply replace the implementation (either using the initializer or by going directly to Local.Data[] and modifying that entry).

But what about the Is Allowed method? It is a static method, and that can’t be mocked. The Is Allowed method just make a call to the security service in the Context (not shown here), and that can be mocked. In this case, it is just a short cut to make it easier to follow the Law of Demeter and to save repeating code.

There are some disadvantages, you lose the ability to look at a class’ interface and tell what the dependencies are. It may pull stuff from the context to do its work, and you will need to look at the code to understand how / where / what it does with it.

Another approach to this is the use of dependency injection. Castle’s Windsor has some very nice integration facilities for doing this, but without the need for the Context. In this project, it was not applicable because of customer’s demand.

* Just to note, in my own implementation I actually use a normal class, and extend the Context in several ways. It is all static, of course, but it is nice to know that each part of the application uses the same context consistently