Introduction To Specification Pattern

Specification pattern has emerged out of “Domain Driven Design” phenomenon. It is first identified and articulated here by Eric Evans and Martin Fowler. Specification Pattern is based on method chaining technique and beautifully uses fluent interfaces. In method chaining, we get desired results by operating over the object through series of methods which returns the same type of object. One of the examples of method chaining is given below,

var Television = televisionFactory.New()
    .SetColor("blue")
    .SetHeight(1)
    .SetLength(2);

With the help of specification pattern, business logic or business rules management inside the application can be simplified and code becomes more readable and you can remove those ugly “if else” ladders. Specification immensely helps out to refactor the existing code so as to consolidate the business rules of the system. More benefits of specifications are; you can change the business rule either in terms of hard values or also in terms of business rule composition itself.

Let’s take a following code sample inside order class, which is pretty common use

public bool HasDiscountWithoutSpecification()
{
	if (SKUs >= 10000 && ModeOfPayment == PaymentMode.CashOnDelivery && ShippingAddress.Country == "USA" && OrderAmount >= 50000 && IsTaxApplicable == false)
	{
		AllowDiscount = true;
	}

	return AllowDiscount;
}

With Specification pattern we can turn above code into something like

public bool HasDiscountWithSpecification()
{
    var spec = new DiscountSpecification();
    return spec.IsSatisfiedBy(this);
}

With Specification pattern while we are dealing with flow of information business rule complexity is abstracted and code looks pretty simple.

If you explore the code provided with this post (source code pointer at the end of the post) further, you will see the beauty of construction of specification named “DiscountSpecification”. Discount Specification has method called SatisfiedBy method which utilizes other specifications and builds the business rule whether on specified order, discount is applicable or not. Since Discount specification is built on other specifications it’s a “Composite specification”. Sometimes, this terminology is used to indicate the construction of specifications.

Here is the code for IsSatisfiedBy method.

public override bool IsSatisfiedBy(Order candidate)
{
	return domesticOrderSpec
		.And(highValueSpec)
		.And(highStockSpec)
		.And(taxableSpec.Not())
		.IsSatisfiedBy(candidate);
}

The beauty above code is, even in future, if business rules for discount applicability changes, we just need to change the IsSatisfiedBy method in DiscountSpecification and we are done. For e.g. If business has removed Stock requirements of having 1000 SKUs. Then we just need to remove the highstockSpec AND operation”. So the code after High stock rule is removed will be simply

public override bool IsSatisfiedBy(Order candidate)
{
	return domesticOrderSpec
		.And(highValueSpec)
		//.And(highStockSpec)
		.And(taxableSpec.Not())
		.IsSatisfiedBy(candidate);
}

And this business rule change will be reflected across the application. Now, consider that business changed the rule and now discount will be only given to orders having order total more than 50000 USD. Then, we just need to reflect this change inside our HighValueSpecification class.

In similar fashion, we can also add new Specifications to satisfy the new business rules.

The useful scenarios where specification pattern can be used inside the application are as follows:

  1. While Applying Filtering/Search Criteria
  2. Extraction of Business Rules from code
  3. Handling Error logs
  4. Carrying out Unit Testing
  5. Component/specific object selection
  6. Building out some complex Parsing logic

You can find the Code sample for this post on github here. I have not included tests with this sample. The code sample also contains a small specification framework that you can reuse. Please note that, this code is not a production code and posted on github for the explanatory purpose.

(This post was originally posted at http://www.e-zest.net/blog)
Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s