Fluent API – Improvements

Please read my earlier article on Fluent API before reading this post. I wrote my old article to get you started with Fluent API design. There are few essential improvement that we should do in that implementation.

In our Fluent interface all methods were returning similar type of object, IFluentPolicyEngine

public interface IFluentPolicyEngine
{
IFluentPolicyEngine CreatePolicy(string name, string description);

IFluentPolicyEngine PerformsOperationOnData(string operation);

IFluentPolicyEngine HavingDataFilter(string type);

IFluentPolicyEngine Where(string filter);

IFluentPolicyEngine Validate();

void Save();
}

This makes it very easy to chain methods but in real world applications this will not work well. There should be a predefined way of chaining methods. Above interface let’s you chain methods in any order. There will be some business rules that should be used while creating these chains. Designing your fluent API based on business rules helps in:

  • Business rule driven data validation
    Suppose our policy has a business rule, a policy can have filter statements added via Where(…) only if data filter is added to the policy via HavingDataFilter(…). It is not possible to restrict chaining using our above interface. Only possible solution is to do a check in API method and throw exception. Nahhh :(, we should strive for compile time safety rather than runtime.
  • Improving code readability
    If API is designed carefully based on business rules then rather than sprinkling validation code in all methods we can have far better data validation routines

Let’s modify our fluent API to support following business rules:

  • Client can only add policy filter after adding business operation
  • Client can only add filter statements via Where(…) after data filter is added via AddDataFilter(…)
  • Client can only validate policy when an operation and at least one filter statement is added to the policy
  • Validation can only be performed after adding operation and filter to the policy
  • Save can only be called on a validated policy

New interface design looks like this:

public interface IFluentPolicyEngine
{
IFluentPolicyEngine CreatePolicy(string name, string description);

IFluentPolicyWithOperation PerformOperationOnData(string operation);
}

public interface IFluentPolicyWithOperation
{
IFluentPolicyWithFilter HavingDataFilter(string type);
}
public interface IFluentPolicyWithFilter
{
IFluentPolicyWithFilter Where(string filter);

IValidatedPolicy Validate();
}

public interface IValidatedPolicy
{
void Save();
}

Modify the class where old single interface was implemented by implementing all new interfaces and changing method return types. Client code remains the same.

Now you can only write client code with proper business rule driven method chaining. Ad hoc chaining will result in compile time issues. Download the code and try changing things.

Download Code : http://1drv.ms/1o3lnyC
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