Thursday, March 6, 2014

What is an interface and why do we need it?

This is a quite common interview question. Many a time candidates escape this question by giving the definition of an interface. “Interface is a contract which mandates implementation of the contractual methods”. Some also say “Interface is the way by which we can realize multiple inheritances”.
The above said definitions and explanation stands true; but interfaces are not just that. It plays a major role in design of systems.  Let us see what is it capable of.
Interface is a contract
This statement is directly taken from the above mentioned definition. But the question to be asked is “Why should we abide to that contract?” or “Why should we implement an interface.
Let us take an example. We are familiar with the interface “IEnumerable”. We also know that this interface needs to be implemented if a class has to qualify as a custom collection or collection iteratable by “foreach” statement. Thus the contract is enforced by the “foreach” statement and if we have to use foreach against our custom collection; we have to implement IEnumerable.
By this the “foreach” is acting against abstracts and it would look for the methods/properties in the candidate class to go ahead with the “iterate” operation. Thus other functionalities of the custom class is really not a concern for “foreach”.
As an example let us build a simple validation engine. Let us assume that the validation engine runs on multiple rules
The validation Engine will perform the following operations on the rules
  1. Execute validation rules in particular order
  2. Collate all failures and throw error.
Let us define the validation rule contract as follows
  public interface IValidationRule  
   {  
     short Order { get; }  
     string ErrorMessage { get; }  
     bool Validate(Entity subject);  
   }  

And Validation Engine as
 public class ValidationEngine  
   {  
     private readonly IEnumerable<IValidationRule> _validationRules;  
     public ValidationEngine(IEnumerable<IValidationRule> validationRules)  
     {  
       _validationRules = validationRules;  
     }  
     public void Validate(Entity subject)  
     {  
       var failedMessages = new List<string>();  
       foreach (var rule in _validationRules.OrderBy(ru => ru.Order))  
       {  
         var validationResult = rule.Validate(subject);  
         if (validationResult) continue;  
         failedMessages.Add(rule.ErrorMessage);  
       }  
       if (failedMessages.Any())  
       {  
         throw new ValidationFailedException(failedMessages);  
       }  
     }  
   }  

Validation engine expects the rules to be injected as collections and on invoking the Validate method with the “Entity”payload, it iterates through all rules and executes each of them. On failure the message is added to a collection. In the end of iteration, if there are any failure an exception is thrown.
Entity (Validation payload) defined as
  public class Entity  
   {  
     public string Property1 { get; set; }  
     public int NumericProperty { get; set; }  
   }  

Let us define the exception as .
 public class ValidationFailedException:Exception  
   {      
     public ValidationFailedException( IList<string> failedRules)  
     {  
       Failures = failedRules;  
     }  
     public IList<string> Failures { get; private set; }  
     public override string Message  
     {  
       get  
       {  
         return "Validation failed. See Failures property for details";  
       }  
     }  
   }  

Sample rules as
1. A rule to validate Property1
 public class Property1RequiredRule :IValidationRule  
   {  
     public Property1RequiredRule()  
     {  
       Order = 1;  
       ErrorMessage = "Property1 is a required field";  
     }  
     public short Order  
     {  
       get;  
       private set;  
     }  
     public string ErrorMessage  
     {  
       get;  
       private set;  
     }  
     public bool Validate(Entity subject)  
     {        
       return !string.IsNullOrEmpty(subject.Property1);        
     }      
   }  

2. A rule to validate NumericProperty
 public class NumericPropertyShouldBePostiveRule:IValidationRule  
   {  
     public NumericPropertyShouldBePostiveRule()  
     {  
       Order = 2;  
       ErrorMessage = "NumericProperty should be positive";  
     }  
     public short Order  
     {  
       get;  
       private set;  
     }  
     public string ErrorMessage  
     {  
       get;  
       private set;  
     }  
     public bool Validate(Entity subject)  
     {  
       return subject.NumericProperty >= 0;        
     }      
   }  

And we shall invoke the engine as
 class Program  
   {  
     static void Main(string[] args)  
     {  
       var validationRules = new List<IValidationRule> { new Property1RequiredRule(), new NumericPropertyShouldBePostiveRule() };  
       var subjectEntity = new Entity { NumericProperty = -3 };  
       try  
       {  
         var validationEngine = new ValidationEngine(validationRules);  
         validationEngine.Validate(subjectEntity);  
       }  
       catch (ValidationFailedException ex)  
       {  
         Console.WriteLine(ex.Message);  
         foreach (var failureMessage in ex.Failures)  
         {  
           Console.WriteLine(failureMessage);  
         }  
       }  
       Console.Read();  
     }  
   }  

Validation engine works against abstracts which implements IValidationRule. Validation engine or the validation altogether does not change for adding or altering rules. Adding a new rule is as simple as create a new class and make it implement IValidationRule and add the new class to the engine. Thus the validation engine is extensible.
Multiple Inheritances is supported by interfaces.
Let us change the validation engine a bit. We would ask the engine to execute some action before and after validation. There will be only certain rules which would requires either post or pre operations. Some rule may require both these actions implemented.
Let us call these methods as PreAction and PostAction. We cannot add these methods to IValidationRule because only certain rules need these operations. We shall segregate these methods into two different contracts viz; IPreActionRule and IPostActionRule.
 public interface IPreActionRule  
   {  
     void Action();  
   }  
 public interface IPostActionRule  
   {  
     void Action();  
   }  

Validation engine after introducing pre and post action
 public class ValidationEngine  
   {  
     private readonly IEnumerable _validationRules;  
     public ValidationEngine(IEnumerable validationRules)  
     {  
       _validationRules = validationRules;  
     }  
     public void Validate(Entity subject)  
     {  
       var failedMessages = new List<string>();  
       foreach (var rule in _validationRules.OrderBy(ru => ru.Order))  
       {  
         var preActionable = rule as IPreActionRule;          
         if (null != preActionable) preActionable.Action();  

         var validationResult = rule.Validate(subject);  
         var postActionable = rule as IPostActionRule;  

         if (null != postActionable) postActionable.Action();  
         if (validationResult) continue;  
         failedMessages.Add(rule.ErrorMessage);  
       }  
       if (failedMessages.Any())  
       {  
         throw new ValidationFailedException(failedMessages);  
       }  
     }  
   }  

Every rule has to implement IValidationRule and optionally if the rule has to operate Pre/Post action then those rules has to implement IPreActionRule/IPostActionRule.
Let us modify the rules to accommodate pre and post operation.
1. Property1RequiredRule requires only post operation to be performed
 public class Property1RequiredRule :IValidationRule,IPostActionRule  
   {  
     public Property1RequiredRule()  
     {  
       Order = 1;  
       ErrorMessage = "Property1 is a required field";  
     }  
     public short Order  
     {  
       get;  
       private set;  
     }  
     public string ErrorMessage  
     {  
       get;  
       private set;  
     }  
     public bool Validate(Entity subject)  
     {  
       Console.WriteLine("Validating Property1RequiredRule");  
       return !string.IsNullOrEmpty(subject.Property1);        
     }  
     public void PostAction()  
     {  
       Console.WriteLine("Executing Post Action within Property1RequiredRule");  
     }  
   }  

2. NumericPropertyShouldBePositiveRule requires only pre-action
 public class NumericPropertyShouldBePostiveRule:IValidationRule,IPreActionRule  
   {  
     public NumericPropertyShouldBePostiveRule()  
     {  
       Order = 2;  
       ErrorMessage = "NumericProperty should be positive";  
     }  
     public short Order  
     {  
       get;  
       private set;  
     }  
     public string ErrorMessage  
     {  
       get;  
       private set;  
     }  
     public bool Validate(Entity subject)  
     {  
       Console.WriteLine("Validating NumericPropertyShouldBePostiveRule");  
       return subject.NumericProperty >= 0;        
     }  
     public void PreAction()  
     {  
       Console.WriteLine("Executing PreAction with in NumericPropertyShouldBePositiveRule");  
     }  
   }  

In the end Validation engine uses contracts IValidationRule, IPreActionRule and IPostActionRule for validation. Who ever want to use validation engine should abide to those above mentioned contracts.

Hope the post helps in understanding how interfaces are used to program against abstracts and the role it plays in building frameworks.