The importance of the interfaces
Tags: python, bestpractices, patterns, solid
Published: 2020-06-30 19:46:22

The interfaces are an important tool in the Object Oriented wolrd, but there are many developers who don't like to use it, and don't see the advantages they offer.

In order to explain the importance of the interfaces, we will follow the integration process between a big smartphone company called Fuwei and its technology provider, Famsung. 

## Fuawei - The smartphone company

Fuawei is one of the biggest technology companies in the world, it produces smartphones and sells them around the globe. 

A few years ago, the direction board decided to externalize the chips production to Famsung, in order to allow the company to increase the production of smartphone.

Famsung has a cool REST API which allows clients to order new components and retrieve the provider specification. Fuawei decided to use this Web Service to ask for the chips needed.

Fuawei had a small technology team, which was in charte to create the technological requirements of the products, it  was the **CORE  TEAM.** As well to ensure the integration with Famsung was successfully, Fuawei created another team called the **Integration TEAM.**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/b4b64d6oy01hb72o67ox.jpg)

Unluckily, The Integration Team  didn't know much about interfaces so the first integration attempt get the following result. 

```python
import requests

from fuawei.fuawei_chip import FuaweiChip

class Fuawei:

    def create_phone(self):
        famsung_chip_data = requests.get('http://famsung/web-service').json()
        famsung_specification_parsed = self.parse_famsung_specification(famsung_chip_data)
        return self.create_fuawei_chip(famsung_specification_parsed)

    def parse_fansung_specification(self, data):
        # Many lines to parse from fansum format to any more friendly format
        return {}

    def create_fuawei_chip(self, data) -> FuaweiChip:
        # Many lines to build from our friendly format to FuaweiChip
        return FuaweiChip()
```

This code is shared between the Core Team, and the Integration Team.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/z2dhg02qynyoqwdvu5gt.jpg)

The core team and the integration team fought many times, because of the many conflicts they suffered between each other, also those issues caused many bugs.

Now, in the present, Famsung and Fuawei relation is uncertain,  the politics from their respective countries are not in good terms, and they have forbidden to work together. Finally, the Fuawei CEO has decided to assume the chip production  in their own factories. 

In order to replace Famsung provider, Fuawei is creating a **Components Team.** They have decided to use [gRPC](https://grpc.io/) technology as the communication method because it is more efficient. 

But the integration team is already using the Famsung REST API, in many parts of the product, refactor the whole product might cost them too much time. 

### What could the integration technology team do?

The Core and Integration teams have decided get a time off in order to get the best solution to this problem. It is going to be hard this time, but they don't want to do twice the same mistake.

### Dangers

- The logic is not isolated
- Too coupled to third party libraries
- The teams are not able to work confident
- So easy to create bugs

For example: Imagine the requests or grpcio library get deprecated, in the first iteration you would have to migrate big part of the project too, in order to replace them to other libraries.

One of the core developers has recently read the [Clean Architecture Book](https://www.amazon.es/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164/), and he would like to apply it to this situation in order to decouple the integration logic from the core logic.

### The importance of the Intefaces

This time, they will create a couple of classes with the specific logic for each integration, they would like to keep the old Famsung Integration in case the necessities change in the future.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6emt079n86n5v9f22kbw.jpg)

The integration team likes the solution proposed by the Core Team. But they they would like to add a few changes in order to work better.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wiljfp6o1oeqop8kvcsy.jpg)

The teams are going to divide the code, isolating the different parts for each team, this way they will avoid conflicts among different teams. 

In order to coordinate both teams, they have decided to create an interface called `TechProvider` with an `order_chip` method, and it would be in charge of the Core Team, to prevent error in the core logic. 

The Core Team will be in charge of the core logic and the provider contract, and the Integration Team will handle the integration logic with the different technology providers, always implementing the `TechProvider` interface.

These changes will add many advantages to the company.

**Advantages**

- The teams will be able work without conflicts
- They can create new integration with new provider without too much effort
- They don't rely on specific technology (which can change and be deprecated)
- The specific business logic is isolated avoiding generating undesired dependencies.

After a few months, they accomplished the task with the following result.

### Code

Core Team Area

```python
from fuawei.phone import Phone
from fuawei.tech_provider import TechProvider

class Fuawei:

    def __init__(self, provider: TechProvider):
        self.provider = provider

    def create_phone(self) -> Phone:
        chip = self.provider.ask_chip()
        return Phone(chip=chip)
```

```python
import abc

from fuawei.fuawei_chip import FuaweiChip

class TechProvider(abc.ABC):

    @abc.abstractmethod
    def ask_chip(self) -> FuaweiChip:
        pass
```

Integration Team

```python
import requests

from fuawei.fuawei_chip import FuaweiChip
from fuawei.tech_provider import TechProvider

class FamsungTechProvider(TechProvider):

    def ask_chip(self) -> FuaweiChip:
        return self._build_fuawei_chip(requests.get('http://fuawei-chips/web-service').json())

    def _build_fuawei_chip(self, data) -> FuaweiChip:
        # On these lines you would have a lot of parse work in order to extract all the necessary information to
        # build your fuawei chip

        return FuaweiChip()
```

```python
import grpc

from fuawei.fuawei_chip import FuaweiChip
from fuawei.tech_provider import TechProvider

class FuaweiTechProvider(TechProvider):

    def ask_chip(self) -> FuaweiChip:
        fuawei_service = grpc.insecure_channel('fuawei/web-service')
        # Communication to the gRPC service of the Fuawei Provider
        return FuaweiChip()
```

Because of they know this code may help other developers, they decided to push the whole repository to [github](https://github.com/juanbenitopr/fuawei).

## Conclusion

Structuring your code is key piece of software development, and the interfaces are an important tool to accomplish it. 

The interfaces will keep your architecture organized and decoupled, they empower you to manage the dependencies you use in your project, and help you to test each part of your software project in a isolated way.

Also, a good architecture will help you to keep the technical debt low, it will avoid conflicts with other team members and even other teams, and it will allow you to work more confident in the features you are developing without being worried about creating bugs.

I have used  another OOP principles in the example, I would recommend check the [SOLID](https://en.wikipedia.org/wiki/SOLID) principles out if you don't know any of them.

## Resources

[https://github.com/juanbenitopr/fuawei](https://github.com/juanbenitopr/fuawei)

[https://www.amazon.es/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164/](https://www.amazon.es/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164/)

[https://en.wikipedia.org/wiki/SOLID](https://en.wikipedia.org/wiki/SOLID)