Saturday, April 9, 2011

Exception handling using Actions

This is a brief explanation of a technique we have been employing on the project I'm involved with. It's evolved to address, in a simple fashion, the repetition of 'boiler plate' code for certain behaviours - in this example, handling response object behaviour for WCF services that may experience exceptions during execution (IOW, all web service behaviours!).

The approach is very simple - define a basic implementation in a super type that provides the behaviour of interest, and utilise in sub types. Here is an extant implementation for a method of this type. As is obvious, it taks an Action that perform the 'real work', and wraps the 'worker' execution in a try/catch, and performs some other rudimentary behaviour. The aggressive 'catch all' implementation indicates that we are averse to returning faults to consumers of our web service.

  protected T Execute<T>(Action<T> handler)   
                 where T : BaseResponse, new() {  
       T response = new T { Success = true };  
       try {  
         handler(response);  
       }  
       catch (Exception ex) {  
         LogFacade.LogFatal(this, "CAS failed", ex);  
         response.Success = false;  
       }  
       return response;  
     }  

And the obligatory code that actually uses the 'boiler plate' method:

     public BaseResponse SignOut() {  
       return Execute<BaseResponse>(response => {  
         UnMappedAgent<SecurityAgent>().LogOut();  
         response.Authenticated = false;  
       });  
     }  

This is simple and easy to understand. Although, on reflection, the 'boiler plate' method would seem to represent more of an 'aspect' in execution, and could possibly be expressed in an AOP style (using the Enterprise Library Policy Injection Block is a possibility). It also bears some resemblance to the GOF 'template method' pattern, with the difference that the actual method to execute is passed as an argument, instead of being defined as an abstract or virtual method in the super type that is the sub types responsibility to implement/override.

No comments: