Auditing Framework at Your Disposal

A teaspoon of Mediator with a pinch of Decorator and you got yourself a perfect auditing framework.

Auditing, just like any other cross cutting concerns as logging, validations and exception handling, is what every application need in some form. No matter if you are working on Java or .Net, creating an enterprise application or a mobile app, you would want to keep track of requests and corresponding responses to be able to have an easier life when the application is not on development environment anymore.

There can be different ways of implementing Auditing depending on the type of application and the level of sophistication you want. You may just use the easiest way and write your request and response in log files or you can save blobs in a database or on the cloud.

Despite being such a common functionality, I have rarely seen applications with well-implemented Auditing frameworks. This made me wonder, do most of us actually understand Auditing? Let’s first understand it so that we are on the same page.

Understanding Auditing

In software development, the best way to understand any functionality is by writing clear requirements for it because if we can not state right requirement, we can not design right solution. These are the requirements that a good auditing framework should satisfy.

First thing first, Auditing is a non-functional requirement. Code for auditing can not be mixed with any functional requirements. That means if your application has the traditional n-tier architecture with Controller, Service, and Data Access layers, Auditing fits into none of these layers.

Adding Auditing should not affect any other implementation. Auditing is a pluggable component and not an integral part of the application. It is something that a well-designed application should have, to provide proper traceability to transactions. It should be easily added and removed, like a plug in.

Auditing is also something that the application dictates i.e. it is the application that decides whether or not to audit requests going through a certain layer. The layer itself does not have anything to do with Auditing and should not even know that its request and response are being audited.

Now that we have settled what Auditing is and is not, let’s start designing the framework, keeping in mind that the design addresses all the above requirements.

Design

To implement cross cutting concerns, Mediator Pattern can come in really handy. To be able to make Auditing as pluggable component Decorator Pattern can be the best choice. Dependency Injection can make sure that the existence of the decorated object is not visible to its invoker.

I will briefly explain these three concepts but if you are hearing of any of these concepts for the first time, I would highly recommend reading the corresponding links.

Mediator Pattern

Intent of mediator pattern as described by GOF(Gang of Four) is

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Mediator pattern lets you create a pipeline of loosely coupled objects, performing operations on the request, not directly interacting with each other. It also enforces “one model in, one model out” pattern, which alone can make the design of application extremely simple and robust.

Decorator Pattern

GOF defined intent of Decorator Pattern as

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Decorator pattern utilizes “Open and Close” design principle. It lets you wrap your object with new functionalities without affecting the actual implementation of it.

Dependency Injection

Generally, DI is defined as follows

The application of Inversion of Control(IoC) technique, Dependency Injection is a powerful mechanism for separating construction from use.

In simple words, DI means that you don’t have to worry about initializing the objects every time you need to use them, a dedicated class(IoC container) takes care of it for you.

A lot of good IoC containers have already been implemented. Spring Framework is the best know DI container in Java and StructureMap is my personal favorite for the purpose in .Net.

That’s enough talking. Let’s get implementing!

Implementation

To be able to make sure that you can easily address all the cross cutting concerns, the first step is to design application using mediator pattern instead of the traditional n-tier Controller, Service, Dao layer architecture. You can introduce mediators in between layers.

For example, we can introduce the following mediator between controller and service layer. The controller can delegate the request to this mediator instead of figuring out what service to call for the request. The interface should follow “one model in, one model out” pattern.

public interface IHandler
{
      Response Handle(Request request);
}

You can implement dedicated request handlers for each controller. The mediator will remove service interactions from controller and services and move them to the Handle method. In other words, Handle method is encapsulating interactions between objects.

For example, you can have a concrete implementation of IHandler as

public class MyRequestHandler : IHandler 
{ 
      readonly BussinessService service1; 
      readonly AnotherBussinessService service2; 
      public MyRequestHandler(BussinessService service1, AnotherBussinessService service2) 
      { 
            this.service1 = service1; 
            this.service2 = service2;
      } 
      public Response Handle(Request request) 
      { 
            var service1Response = service1.DoSomething(request);
            Response response = service2.DoSomethingElse(request, service1Response);
            return response; 
      } 
}

Handle method here is mediating the service calls. If it wasn’t there, either controller would have been doing it or one of the services would have been calling the other.

Your controller will look something like

[RoutePrefix("myController)]
public class MyController : ApiController
{
       readonly IHandler myRequestHandler;
       public MyController(IHandler myRequestHandler)
       {
             this.myRequestHandler = myRequestHandler;
       }

       [HttpPost]
       [Route("myPost")]
       public Response MyPost(Request request)
       {
             Response response = myRequestHandler.Handle(request);
             return response;
       }
}

‘myRequestHandler’ will be injected by IoC with an instance of MyRequestHandler. Here, the request will get delegated directly to MyRequestHandler without getting audited.

Now you just have to implement IHandler to handle the cross cutting concern you want to tackle. AuditHandler is defined to handle auditing.

public class AuditHandler : IHandler
{ 
      readonly IAuditor auditor;
      readonly IHandler inner;
      public AuditHandler(IHandler inner, IAuditor auditor) 
      {
            this.auditor = auditor;
            this.inner = inner;
      }

      public Response Handle(Request request) 
      {
            auditor.Audit(request);
            Response response = inner.Handle(request);
            auditor.Audit(response);
            return response;  
      }
}

The constructor parameters ‘inner’ and ‘auditor’ will be injected by IoC container. StructureMap is used in this example but it does not really matter what IoC container you are using. The code may look slightly different but the design will remain same.

Also, make sure to use interface for auditor (IAuditor) instead of using the concrete implementation. This will allow you to be able to inject different kinds of auditors. You can implement LogFileAuditor which may write request and response to a file, you can have an AzureBlobAuditor which can write audits on the Azure cloud. And even if you are sure that you will never need another implementation of your auditor, using interface will satisfy Law of Demeter.

The next step is to decorate the other Handlers with AuditHandler. In this case, MyRequestHandler will be decorated with AuditHandler. A decorator always keeps a reference to the object it is decorating. In AuditHandler, ‘inner’ is a reference to MyRequestHandler. The AuditHandler applies its own code before and after delegating the request to the actual object.

Decorating MyRequestHandler with AuditHandler in its simplest form will look like

IService decoratedMyRequestHandler = new AuditHandler(new MyRequestHandler(), new LogFileAuditor())

where LogFileAuditor is a concrete implementation of IAuditor.

But as there is a high probability that there will be more than one concrete implementation of IHandler, using above method to decorate will introduce a lot of boilerplate.

StructureMap provides very useful API to apply a decorator to a family of objects at once. Following shows how you can decorate all implementations of IHandler in StructureMap Registry file :

For<IHandler>().DecorateAllWith<AuditHandler>();

The idea is to find a way to decorate all the implementation of IHandler at once. The way to do it can vary with the choice of IoC container.

This is it. Your controller will remain exact same. Not even a simple line of code will change in the controller or in MyRequestHandler but now the request will get audited before actually getting processed. Isn’t it cool?

If you can not implement mediator pattern because of legacy code challenges, you can just create decorators for a service you want to audit. But then it will introduce a lot of small decorator classes doing more or less same thing. This is one of the biggest drawbacks of using decorator pattern and using mediator pattern along with helps overcome this.

Why implement your own Auditing Framework?

A lot of different libraries have already been created to provide support for cross cutting concerns. Java developers must be familiar with Spring Framework’s AOP (Aspect Oriented Programming) approach. I have not come across anything as good as Spring APO in .Net yet which does not cost a fortune.

In spite of an abundance of pre implemented libraries, I prefer writing code to tackle cross cutting concerns. These are few of the reasons why

  • Not all programming languages have very reliable third party libraries available to address this. For instance, implementing APO in .Net is very expensive or cumbersome if it’s free.
  • You will have to learn to use different libraries for different languages.
  • Creating your own mediator pipeline can remove dependencies from framework pipeline such as ASP.NET, Web API and so on.
  • Mediator pipeline not only addresses Auditing or other cross cutting concerns, but it also improves and simplifies the overall conceptualization of the application.
  • Last but not least, it is extremely easy to implement your own code and you can use the same design for multiple types applications and in any language.

I have only talked about auditing specifically here for the sake of simplicity, but honestly, everything here applies to any other cross cutting concern and you can implement all of them using this framework. You can implement handlers to handle validation or exception, and just add them as decorators. This will be your very own mediator pipeline!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s