Software Design Blog

Journey of Rinat Abdullin

What Is an Action Policy?

Action Policy

Simple action policy definition in .NET 3.5 is:

Action<Action>

In old .NET syntax this would look like:

public delegate void Action();
public delegate void ActionPolicy(Action action);

Basically it is just a delegate that can do something with your action.

Simplest example is a policy that would let your calls to retry a couple of times (with Thread.Sleep), should they fail on a database exception.

Your own implementation could be:

void MyRetryPolicy(Action action)    
{
  int counter = 0;
  while (true)
  {
    try 
    {
      action();
      return;
    }
    catch (DbException ex)
    {
      counter+=1;
      if (counter==3)          
      {
        throw;
      }
      Thread.Sleep(1);
    }
  }
}

The policy could be used like:

// Simple calls
MyRetryPolicy(() => LongRunningDbCall());
MyRetryPolicy(() => AnotherFragileCall());

// Code that takes an argument and returns the result
int result = 0;
MyRetryPolicy(() => result = CreateRecords(records));
// .. some more code

Of course, you could have written try-catch-sleep around every breakable code, but this would have been slightly inefficient.

So basically using an action policy approach allows you to:

  • make your code more efficient by dropping repetitive statements
  • apply policies consistently throughout your classes and methods
  • keep policies easily configurable

You could check out the Storage Client in Windows Azure for the sample implementations of this scenario.

Exception Handling Application Policy

The policy used in the sample above is a specific case of Exception Handling Application Policy. It consists of two logical components:

  1. Exception handling block
  2. Action Block

Exception handling block - that’s everything inside the catch statement that deals with the exceptions.

Based on your configuration, different policies could be applied to the exception through the handling:

  • Rethrow by passing out ‘true’ (basically it is the policy that does nothing)
  • Suppress by passing out ‘false’
  • Wrap by throwing exception inside the ‘Handle Exception’ (this could be used to provide additional info about the problem)
  • Replace by throwing completely different exception (really useful for hiding sensitive information about the system, although it is recommended to log the original message first)

Microsoft Exception Handling Application Block is an example of framework that lets you to configure and consistently leverage the first component.

The recommended (by the patterns and practices authors) example of doing that is:

try
{
  SomeFragileCall();      
}
catch (Exception ex)
{
  bool rethrow = ExceptionPolicy
    .HandleException(ex, "Global Policy");
  if (rethrow)
  {
   throw;
  }
}

or, if we decide to use configurable exception handler in our action policy (sleep and retry a couple of times) from above:

void MyRetryPolicy(Action action)    
{
  int counter = 0;
  while (true)
  {
    try 
    {
      action();
      return;
    }
    catch (Exception ex)
    {
      bool rethrow = ExceptionPolicy
        .HandleException(ex, "Global Policy");
      if (rethrow)
      {
        throw;
      }

      counter+=1;
      if (counter==3)          
      {
        throw;
      }
      Thread.Sleep(1);
    }
  }
}

So in the code snippet above we’ve composed exception handling from the Microsoft Enterprise Library with our own hard-coded “sleep-and-retry” Action Block to get some reusable action policy.

Obviously, this sleep-and-retry block is just one example of reusable code that tells us what to do with the problems. It could also:

  • capture performance statistics on the calls
  • write call name and call parameters to the log
  • implement circuit breaker pattern

Summary

In this post we’ve quickly covered the concept of Action Policy and a specific case of Exception Handling Action Policy.

I hope the theory and code snippets didn’t scare you away. All this logic could be expressed in a way that is much more flexible, simple and is already coded somewhere else. Check out the post on the Application Block for defining Action Policies in .NET.

PS: What do you think? Have you employed any reusable exception handling in your solutions? And what about the retry or any other policies?