Interface types – what’s the point? why have them?

326 0
Interface types - what's the point? why have them?

In object-oriented languages, the term interface is often used to define an abstract type that contains no data or code, but defines behaviors as method signatures. A class having code and data for all the methods corresponding to that interface is said to implement that interface – Wikipédia

This article aims to deliver a clear explanation about some the benefits of using interface types, targeting C# and Java developers, but not limited to them.

What?

We can define an interface as a programming structure that allows to enforce certain characteristics to an object. An interface defines behavior to be implemented by classes.

Lets see an interface type declaration example in java/C#:

interface Car{

public void startEngine();
public void stopEngine();

}

The interface type declaration above defines two methods: startEngine and stopEngine. Both methods are public and void. Any class that implements such interface, implements both methods.

Lets see an example of a class that implements the Car interface:

class Mustang implements Car{

public void startEngine(){

//implementation

}

public void stopEngine(){

//implementation

}

}

The class declaration above implements the Car interface we declared previously, but You might be like “Why is any of this important to a productive programmer?”. Its not! The important part is WHY, and that’s what we will discuss next.

Why declare and use interfaces?

Multiple Inheritance

When a Type B extends a Type A we say B is an A. Remember the interface and class declarations we made before? Car and Mustang? Mustang is a Car, this a pretty straightforward statement and you don’t actually need an interface to do what we have done so far. You could have an abstract class Car with two abstract methods and then make the Mustang class extend it. The problem is when you have a Type B that is an A and is also an C, WHERE C is not hierarchically nor Conceptually related to A. I guess you need some help on this, then, let the imagine speak for itself:

The imagine above, represents a Restaurant Car. A car that is also a restaurant. Lets name it “AustralianRestaurant“. The AustralianRestraurant is a Car and is also a Restaurant, but a Restaurant is not hierarchically nor Conceptually related to a Car. The AustralianRestaurant inherits characteristics from Both, a Car and a Restaurant, which makes it the perfect example of multiple inheritance. We say multiple inheritance because it has multiple parent types (Car and Restaurant).

Without interfaces we would have two different classes: Car and Restaurant, each with its own members (properties and behavior). The problem would be: How do we create a third class that extends both classes?

Car class:

public abstract class Car{
    public abstract void startEngine();
    public abstract void stopEngine();
}

Restaurant class:

public class Restaurant{

private int openingHour;
private int closingHour;

//Assessor methods or properties come here

public void order(Order order){
//implementation comes here
}

public int getOpeningHour(){
//implementation comes here
}

public int getClosingHour(){
//implementation comes here
}
}

AustralianRestaurant class:

public class AustralianRestaurant extends Car, Restaurant{

//Implementations come here

}

Wait! Did we just create the AustralianRestaurant class? The answer is no.

The class declaration above is impossible and incorrect in both Java and C#.

You can’t create a class that extends more than one class, because Neither Java nor C# support multiple inheritance of state, they both only support multiple inheritance of behavior, which is achieved with interfaces. One class can’t extend multiple classes, but it can implement multiple interfaces and this how java and C# implement multiple inheritance, which means, we wouldn’t be able to solve the problem above in Java or C# without interfaces. Got it? Great! (Assuming you said yes). How would we model such scenario then? All we would have to do is: create two interfaces: Car and Restaurant and create an AustralianRestaurant interface that extends both of previous interfaces or create an AustralianRestaurant class that implements both Car and Restaurant interface.

Contracts oriented design (abstraction and low coupling)

In real-life, contracts are used to define expectations from a relation or action. In software, contracts are used exactly for the same purpose. When we define a contract, we focus on defining what we want and we never question how its going to be delivered or done. The ignorance regarding how a service is delivered has already been given a name in the software industry: abstraction. The question here was never how we name it. The question was always why does it matter because that’s the only thing that can make you go for it.

The abstraction through contracts (interfaces) has a particular advantage: it enforces a logical separation between the code that uses the services described by the contract and the code that implements such services. The logical separation can easily be extended to a physical separation. The services consumer code is not coupled to the services implementation, this allows us to easily switch the contract implementation at any time without affecting the services consumer code, as long as the services are implemented as described in the contract and, as expected by the consumer code.

Think about how easy can this turn collaboration. You could split the work among your team mates based in contracts without worrying about how they do it, focusing on putting the pieces together and having the software up and running.

A contracts oriented approach also reduces the number of “what does this code do” questions, as the service provided by the code is documented by the contract. The code refactoring process also gets boosted because, once again, the contract already expresses what the code must do, we can quickly spot the code intention and change it, yet, fulfilling its intentions.

Easy faking for unit testing

When we do unit testing, we must focus on a single code unit, which can be defined as a small piece of code, a method. The unit testing process can be a nightmare if the small piece of code which we want to test, depends on different objects, each encapsulating a service required to reach the goals of the code unit.

I personally consider unit testing, an isolation process, more like the scenes we watch in movies, where suspects and witnesses are trapped in isolated rooms and asked tens of questions, simply to assert that they are telling the truth.

Well, in unit testing, we are not chasing the guilty mind, or a criminal, but our intention is to assert that our small piece of code (code unit) is actually doing what is supposed to do, it is reacting as expected and to do so, we must isolate the code: test it apart from the other components of the system. Sometimes isolating is easier, sometimes it is like a said before: a nightmare. But why do we isolate the code in the first place? Because only this way we make can be sure we control all the environment our code executes on, otherwise, we might “find our code guilty”, while, the fault is actually not in our code, but, in another which our code unit is depending on. The bug in another code unit might compromise our unit test. If for example, we are testing a method that depends on an object that performs operation in the database over the network, we are no longer doing a unit test, we are already performing integration tests. Unit tests are supposed to run completely in memory and also to be repeatable and executable in any machine without any other configuration except the runtime environment itself. Installing a database is not covered here, so if you are going to need to install the database on the computer you intend to execute the tests, or even configure the firewall to open a specific port so that a connection to a remote database can be stablished, I’m sorry, but that’s not a unit test anymore.

But you still want to write a unit test for the code that depends on the object that is dealing with the database communication. How do you do it? You Fake the dependency object. You simply create an object that provides the services your code depends on (implement the methods), defining how each method responds/reacts to the calls made from your code. Why would you fake the dependency object? To make sure its not going to the database (still a unit test) and most importantly: to make sure it is going to react/respond as expected to the calls made from the code you are testing.

Wait! We haven’t related the faking process to the interfaces yet! What’s the glue point here? The glue point is that if your code is actually referencing a dependency object based on its interface, you can easily create an object that implements such interface in runtime (proxy object), in both C# and Java. The great part if the story is that, you don’t even have to create the proxy objects yourself, there tons of frameworks that can help you create Fake objects in runtime. In C# you can start by FakeItEasy, while in java you can start by Mockito. Both frameworks allow you to create Fake objects in seconds to respond accordingly to the needs of your code. Create the Fake object and inject straight directly into your code and have fun unit testing.

One thing i would like to clarify before i put an end to this article, is the difference between abstract classes and interfaces: Interfaces are more like This is what I want, then find a way to do it. Abstract classes are like: This is what I want and this is how you are going to do it.

You know its always a pleasure right?

Happy week and please, leave your contribution in the comment box below.

(Visited 617 times, 1 visits today)

Mário Júnior

Mário Francisco Júnior is the Head Of Software Development at Vodacom Mozambique.