Saturday, 2 August 2014

Simple Understanding of Interfaces. Why Interfaces ?


Assumptions:

1. Knowledge of OOPS C#/JAVA
Note : I am assuming that you have already some basic knowledge of Object oriented design

What is Interface ?

An interface is a programming structure that allows to enforce certain properties on an object. For example, say we have a  2 wheeler , 3 wheeler class and a 4 wheeler class. In all three cases you have to have some action like Initiate_Engine() action. Now question is how the engine is  initiated for each type is left up to each particular class, but the fact is that they must have a Initiate_engine action .
So,we can say Interface states “WHAT TO DO", rather than “HOW TO DO?” .Important point here is that interface defines only the members that will be made available by an implementing object. The definition of the interface states nothing about the implementation of the members, only the parameters they take and the types of values they will return. Implementation of an interface is left entirely to the implementing class. It is possible, therefore, for different objects to provide different implementations of the same member
An interface is a  agreement between itself and any class that implements it. This agreement/contract states that any class that implements the interface will implement ALL the interface's properties, methods and/or events.  An interface can contain signatures of methods, properties, indexers & events

When to Use Interface ?
Using interface is good practice but not in each and every case.Sometime using too much of interfaces can result in overhead for developers.I will justify this point in my next series
To make it understand when to use interface is my first consideration.
Let us assume that we have got requirement to design a service/method which will save reports in multiple format like WORD,EXCEL,PDF,CSV.So , we have services.methods like

SavetoWord(Asset objasset)
SavetoExcel(Asset objasset)
SavetoPdf(Asset objasset)
SavetoCsv(Asset objasset) 

and class implementation will go like
public class AssetReportingService {
    public void SavetoWord(Asset objasset) {
        //save to word using service exposed by Repository layer/Database related layer
    }
    public void SavetoExcel(Asset objasset){
        //save to db using service exposed by Repository layer
    }
  public void SavetoPdf(Asset objasset){
        //save to db using service exposed by Repository layer
    }

  public void SavetoCsv(Asset objasset){
        //save to db using service exposed by Repository layer
    }
}

In  above case, the AssetReportingController should be aware of the concrete implementation of these four methods  in AssetReportingService to use them and Controller becomes complicated too when additional features are required like SavetoJson() , SavetoText()...

public class AssetReportingController {
    //Controller should be aware of the implementation when no Interface is used

    AssetReportingService assetReportingService = new  AssetReportingService();
    private void SavetoWord(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }
    private void SavetoExcel(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }

  private void SavetoPdf(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }

  private void SavetoCsv(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }

//new features 
private void SavetoJson(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }

private void SavetoText(Asset objasset) {
        assetReportingService.saveToXml(objasset);
    }
}

If an additional functionality to save the information as JSON,TEXT is required then you will have to add a new function SavetoJson(),SavetoText() in the Service class as well as make changes in the Controller. This adds lots of complication to maintenance of our application with hundreds of controllers and services. simply it becomes tough .

Here INTERFACE can HELP :-

When using interface this becomes much simpler. We define our AssetReportingService like this:
public interface IAssetReportingService {
    public void SaveReport();
}
 
The controller layer is only aware of this interface, which has a SaveReport method.
Let us say we have three implementations like the following:

public class AssetReportingServiceWord implements IAssetReportingService
{ 
@Override public void save(Asset objasset) 
{ 
//save to xml using service exposed 
} 
} 
public class AssetReportingServiceExcel implements IAssetReportingService 
{ 
@Override public void save(Asset objasset) 
{ 
 //save to relational db using service exposed 
} 
} 
public class AssetReportingServicePdf  implements IAssetReportingService 
{ 
@Override public void save(Asset objasset) 
{ 
 //save to relational db using service exposed 
} 
}
 
Here we can choose any of these three implementation(classes) on run time using dependency injection. One may use @Inject or @Resource annotation in JAVA and Unity or StuctMap in C# to mark an implementation is to be injected.
public class AssetReportingController 
{
//choose config /resource file for choosing this session
@Resource(name = "AssetReportingServiceWord")
AssetReportingService assetReportingService;
public void processRequest(Asset objasset)
{
assetReportingService.SaveReport(objasset);
}
public void setAssetReportingService(AssetReportingController assetReportingService)
this.assetReportingService= assetReportingService;

 }
}
Now when we need to add the additional functionality of saving to Json, we just add another implementation and select that implementation to be injected.
 (You may use an IOC{Inversion Of Control} container like Spring to achieve this seamlessly.)

public class AssetReportingServiceJson implements AssetReportingService
 {
@Override public void save()
{
//save to json using service exposed by Repository layer
 }
}
This is what we call loosely coupled system. This highly reduces the software modification and extension cost. As changes in one layer does not effect other layer and new functionalities are made available to other layer immediately. Thus using interface gives you more power over extending and maintaining your application, utilize abstraction and implement good software development practices.
Finally
Interfaces fulfill two goals:
  1. They allow the programmer to be more abstract when referencing objects (for example, var vehicle : Vehicle, can reference any car, truck, etc... anything that is a vehicle (and not care what type it is.) This occurs at "program time".
    When the vehicle.start_engine() function is invoked, the correct function associated with the real object is actually used. This occurs at "run time".
  2. They require the programmer to create specific functions that are expected in an implementing class when it implements an Interface.
    Again, this allows all objects in a "set" of like objects to be treated based on the "high level" type of the set, rather than on the specific type of the individual object.
Hope this helps..

No comments:

Post a Comment

How to Build a Full-Stack Web App with Blazor

  Blazor Stack Overview Important Points: Blazor stack gives you options to create Web Applications without writing JavaScript (doesn't ...