Improving Software Design with Role Interfaces ☕
Tags: oop, programming, architecture, solid
Published: 2021-07-19 10:03:47

---
title: Improving Software Design with Role Interfaces ☕
published: true
date: 2021-07-16 00:00:00 UTC
tags: OOP,programming,architecture,SOLID
canonical_url: https://www.codecraftr.nl/interfaces-defining-roles/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uptpabibk2cvj9kik6c.jpg
---

Role Interfaces offer a different perspective on the Interface in OOP. Learn what benefits this type of interface can bring your software design.

## The purpose of the Interface 🧰

The _interface_, a very important tool in the toolbox of every Object Oriented Programmer. Most programmers will be familiar with it, but I recently learned to look at them in a whole new way…

Let’s first have a look at what I refer to as the “traditional way” of using interfaces.

Interfaces, as we know, are powerful concepts which allow programmers to _abstract_ and _encapsulate_. You use them to define some behaviour any implementor will have to offer. The way it is implemented is left up to the implementor to decide.

Another way to put this is that an interface defines the **what** , not the **how**. This generally translates to an “[Acts Like](https://www.cs.utah.edu/~germain/PPS/Topics/interfaces.html)” type of relationship between the implementor and its interface, which brings us to the traditional view as a “Header Interface”.

## The traditional view: Header Interface 🤵‍♂️

Martin Fowler defines the traditional view I had of interfaces as a _[Header Interface](https://martinfowler.com/bliki/HeaderInterface.html)_. A Header Interface is an interface which defines all public behaviour of a class. Let’s have a look at an example.

![coffeemaker](https://www.codecraftr.nl/assets/images/14-fancy-coffee-machine.jpg)

> A coffeemaker

Say that we are building a Software System for brewing coffee. Part of our model is the coffeemaker, of which we should support different types. A (basic) coffeemaker should be able to:

- Boil water
- Grind beans
- Brew coffee
- Froth milk

A Header Interface for this would like something like fig 1:

![header interface](https://www.codecraftr.nl/assets/images/14-header-interface.svg)  
_fig 1. Coffeemaker as a Header Interface_

This interface defines all public methods of a coffeemaker, a typical Header Interface. I was used to applying interfaces this way, for instance to adhere to the [Dependency Inversion Principle](https://stackify.com/dependency-inversion-principle/), a common example being a [Repository](https://martinfowler.com/eaaCatalog/repository.html) or [Data Access Object](https://www.oracle.com/java/technologies/data-access-object.html).

Recently though, I have learned about using interfaces to define (and abstract) roles in systems, with the so-called _Role Interface_.

## A different view: Role Interface 🧑‍🎤

A [Role Interface](https://martinfowler.com/bliki/RoleInterface.html) abstracts and defines a specific role objects can fulfill in a system. The language construct is exactly the same, the difference resides in the _semantics_. As we’ve seen, a Header Interface abstracts the entire public behaviour of some object, whereas a Role Interface only abstracts some cohesive methods belonging to a role.

Fundamental to this type of interface is the difference between _objects_ and _roles_. A role does not have to be fulfilled by a single object, nor does an object have to fulfill just one role. This shifts the interface more towards a specific interaction a consumer and supplier have.

Sounds a bit fuzzy right? Let’s revisit our coffeemaker example. Previously we extracted one interface, `CoffeeMaker`, defining all public behaviour. If we adapt this to Role Interfaces we end up with fig 2:

![role interfaces](https://www.codecraftr.nl/assets/images/14-role-interfaces.svg)  
_fig 2. Role Interfaces for the coffeemaker model_

You end up with more interfaces this way, but why bother? Time to see what advantages this approach can bring.

## Advantages of the Role Interface 👍

Thankfully the advantages of the Role Interface are plentiful. Amongst others, they give you:

- explicit roles in the model
- simpler consumer code
- increased flexibility

### Explicit Roles 🗣️

Defining interfaces for roles forces you to come up with a name to describe it. I have found that shifting your perspective to think in roles causes you to think about the model differently, which can lead to deeper insights.

Looking at our coffeemaker example, we started out with just a `CoffeeMaker` interface. When we created Role Interfaces for the model, we made the roles of `Boiler`, `Grinder`, `Brewer` and `Frother` explicit. All of which improve the model.

As a [Domain Driven Design](https://martinfowler.com/bliki/DomainDrivenDesign.html) proponent I recognize this as an opportunity to deepen domain knowledge and enrich the [Ubiquitous Language](https://martinfowler.com/bliki/UbiquitousLanguage.html). To top it off explicit roles make the model more granular, which can aid in its comprehensibility.

### Unburden Consumers 😀

Ever hit the autocomplete shortcut in your IDE and felt _overwhelmed_? This can indicate a violation of the [Interface Segregation Principle](https://stackify.com/interface-segregation-principle/). Ideally a suppliers code should offer _precisely_ what consuming code needs. No more, no less.

Imagine that, besides coffee, our model should also support the brewing of tea via a `TeaBrewingService`. You could use the `CoffeeMaker` interface, since it offers the `boil` method, but it also contains three more methods which confuse a client interested in just brewing tea. The Role Interface approach allows that client to use a `Boiler` which offers exactly what it needs!

![roles to adhere to ISP](https://www.codecraftr.nl/assets/images/14-unburden-consumers.svg)_fig 3. Using role interfaces to make to make things simple for consumers_

Role Interfaces are a perfect fit for upholding this principle. Using them you can offer _fine-grained_, _cohesive_ interfaces which prevent clients from being overwhelmed. They won’t have to figure out what to use, and what not to use. It can potentially reduce unwanted coupling too, since clients don’t have to know more than they should.

### Increased Flexibility 🤸

I mentioned earlier that objects do not have to fulfill just one role or that a role should map to just one object. This is the source of increased flexibility when using Role Interfaces. They make shifting responsibility of who fulfills a role easy. Client code does not need to know _who_ fulfills a role.

Let’s revisit the coffeemaker example. Fancier coffeemakers usually work with separate coffee bean grinders. Expressing, and using the role of `Grinder` separately allows the model to support the `FancyCoffeeMaker` and the client doesn’t need to change!

![increased flexibility](https://www.codecraftr.nl/assets/images/14-changing-responsibility.svg)_fig 4. Supporting fancy coffeemakers without breaking client code_

When applied correctly this approach provides better cohesion than Header Interfaces. Role Interfaces enable you to define a more specific _axis of change_, which as we’ve just seen, can simplify maintenance. This is due to the fact that the concepts encapsulated by the roles should change for different reasons.

As always though, not all is sunshine and rainbows. Let’s have a look at some disadvantages of Role Interfaces.

## Disadvantages of the Role Interface 👎

As with any solution there are consequences of using it. The Role Interface is no exception, some of its downsides are:

- they are hard to define
- they give an extra layer of indirection
- level of granularity is hard to get right

### Hard to define 🤔

Role Interfaces are hard to get right. In general, they express concepts which are more abstract than a class, or a Header Interface. You need to truly understand the domain you are working in to give them an appropriate name and _express its intent effectively_.

Don’t expect to get this type of abstractions right the first time. Take advantage of working in an Agile way and incrementally improve on your model. As you learn more about it getting the definition right will become easier.

### Level of Granularity ⚖️

Not just naming this type of interface is hard, getting the _granularity_ right is also a challenge. Just like coffee beans, we want the coarseness to be just right. Get the grind too fine-grained or coarse and the [taste will be subpar](https://goodcoffeeplace.com/size-matters-fine-ground-vs-coarse-ground-coffee/).

![granularity is important](https://www.codecraftr.nl/assets/images/14-granularity.jpg)

> The granularity of Role Interfaces should be just right

If you define Role Interfaces too fine-grained you end up with incohesive interfaces, which don’t tell the whole story and make change harder. Make them too coarse, and you risk losing the benefits altogether.

### Extra Indirection 🤯

Interfaces always give you the _cognitive overhead_ of extra indirection, and the Role Interface is no exception. If you overapply them you could end up with a nonsensical mess where you follow a trail of interfaces before finally finding an implementation. You don’t want to overwhelm or confuse readers of the code.

Always ask yourself if the tradeoff is worth it. If you require multiple implementations the decision is easy to make, though it can be worth the trouble even for one implementation. This might be the case if the role you define makes the model more explicit or abstracts a cohesive concept.

![interface all the things](https://www.codecraftr.nl/assets/images/14-all-the-things.jpg)

> Don’t be like this

It is up to you to weigh the benefits and drawbacks of this solution, that’s the fun part though!

## Conclusion 📝

Interfaces are the _bread and butter_ of a good Object Oriented Programmer. They encapsulate details, removing the burden from their clients.

Many interfaces a developer encounters in the wild resemble _Header Interfaces_. The _Role Interface_ offers a different perspective, defining a clear collaboration between suppliers and consumers and the role something plays.

If you can mitigate some of its downsides, the Role Interface will reward you handsomely. They can make your Domain Model more **expressive** , **simplify clients** and make **refactoring easier**.

So fellow programmer, see if you can capture roles in an interface. Role Interfaces can make all the difference!