Policy Extension

Background

Last time I wrote about a Repository extension for my Builder library. This time I thought I would write about my Policy extension. The word Policy is a bit overused in software development so let’s just say that my idea for a Policy is an object that works with collections of Strategy objects and performs some sort of logic on those Strategies. I see it applying a Func to a collection, or something simple like that, but probably with some built-in logic as well – something to make it smarter than a simple ForEach extension.

For example, I have an email NUGET package that optionally uses a Policy to decide which email Strategy (or Strategies) to use when sending out an email. That email API can be configured with multiple Strategies for sending each email: SMTP, 3rd party email service, etc, etc. The API can then be setup with a Policy that determines how those Strategies are used, at runtime, to send the email. The policy I use most often is a fallback approach so if the first Strategy fails to send the email, then the second Strategy is tried, then the Third, and so on until the email either sends or we run out of options.

In most cases the logic encapsulated by a Policy isn’t complex at all. That’s not really the point. It’s the flexibility that I’m after – the ability to easily modify the runtime behavior of an API without having to recompile any code. I also see a testing benefit from factoring that simple decision making logic into a Policy.

I haven’t yet used my Policy extension in enough scenarios to know whether the approach is flexible enough, or reusable enough, to warrant it’s use in future projects. In my experience, no idea can really prove it’s worth until it’s been tried in at least three or four different projects. However, so far, I like what I’ve seen.

Design

Here’s how I designed the extension. I decided that it should integrate with the Builder, just like my Strategy and Repository extensions. In fact, I decided to start by leveraging the existing Strategy abstraction as a base, just like I did with the Repository package. That means Policy objects can be served up by Providers that are integrated with Setups and tied to Builders and Products – just like my existing Strategy and Repository abstractions.

If any of these terms, Builder, Provider, Product, Strategy, etc, are new to you then go back a few articles and do some quick reading. These are all terms for abstractions from NUGET packages that I have blogged about recently.

Let’s start by looking at a trimmed down code snippet for my Policy interface:

The first thing to note is that a Policy derives from a Strategy. The second thing to note is that, unlike the empty IStrategy interface, this interface contains two methods which comprise the contract for applying any kind of policy.

I’ve heard that interfaces should expose either Synchronous or Asynchronous methods, but not both. I think the main argument is that exposing both represents code bloat. I have followed that advice in the past but, when I do, I always find myself in need of a synchronous method when I need an asynchronous method, and vice versa. For that reason, I have both version for this interface.

The base class for the IPolicy interface simply derives from StrategyBase and exposes the two apply methods as abstract methods:

Here are the Provider interface, which extends the Strategy interface with a method for getting a Policy:

Here is the corresponding base class for the Provider:

Here is the Setup interface, which simply extends the Strategy interface for type safety:

Here is the corresponding base class:

Concrete Policy

With all those things in place, we can now create our first concrete Policy class. Let’s start with the FallbackPolicy, which is the one I described at the start of this article. Here’s the trimmed down source:

The first thing of note is that the class derives from the PolicyBase class and implements the IPolicy interface. That means there is a synchronous and asynchronous version of the Apply method. I’ll only cover the synchronous version, since the only real difference between the two is that the asynchronous version invokes the delegate in a background task.

Both versions loop through the list of Strategy objects and invoke a delegate for each Strategy. If the return result of that invocation is TRUE then the Policy stops and returns TRUE to the caller. On the other hand, if the return result is FALSE then the Policy continues to loop until one of the Strategy objects either returns TRUE or the Policy runs out of Strategy objects.

Any errors are collected and thrown at the end as a PolicyException with an inner exception that contains the list of errors.

This Policy class is pretty simple, but, keep in mind that more sophisticated Policy classes have all the associated Setup, Provider, and Product information available to them, at runtime. That fact should make the creation of more complex Policy classes a little easier.

Builder Extensions

The fallback Policy shown above is integrated with the builder through the now familiar Setup injection approach. Here’s the trimmed down source for an extension method that will inject a FallbackPolicySetup object into any IBuilder object:

As I always point out, this bit of code doesn’t have to be placed into a dedicated extension method but doing so is a little cleaner. It’s how I like to deal with adding Setups to Builders.

Example

So, using a Policy in a project is no different than using any other Strategy or Repository. Start by creating a Product class:

Notice that the example Product class uses the OnInitalize method, which is called by the Builder, to look for a Policy Provider and them if one is found, get a Policy object. This is a fairly standard way of building out a Product by looking for Providers and then, if they are found, using them to initialize the Product.

Also note that we cleanup the Policy object on the Product’s Dispose override. Even though this particular Policy doesn’t contain any resources to free, that’s a best practice.

So, now that we have the MyProduct class, the next step is to make a Builder for it. Here’s the example code for that class:

Nothing too interesting here, just a standard Builder designed to create MyProduct instances. So, how do we put it all together? Here’s the source for a quick example program:

This code should be fairly familiar by now. We start by creating an instance of the MyBuilder class. Then we add the setup with the extension method. In this case we don’t have any Setup properties but if we did, then we would deal with those as part of calling the extension method to add the Setup to the Builder. After the Builder is created, and the Setup is added, we simply call the Build method and it gives us back a MyProduct instance – complete with the Policy object, thanks to the code in the OnInitialize method of the MyProduct class.

My example doesn’t really do anything with the fallback policy but I’m sure you still get the general idea. If you’d like to see the Policy in action go find my email NUGET package at:

https://www.nuget.org/packages/CG.Email

Or, go look at the source code, which can be downloaded for free at:

https://github.com/CodeGator/CG.Email

 

Wrapup

That’s pretty much it for the Policy extension. Some of the code in this article is part of my NUGET package CG.Builder.Policy, which can be downloaded for free at:

https://github.com/CodeGator/CG.Builder.Policy

The source code for the CG.Builder.Policy package lives on Github and can be obtained for free at

https://www.nuget.org/packages/CG.Builder.Policy

 

I hope this article was helpful. Have fun with the code!