linkThe Concise Interface Implementation Pattern

The Concise Interface Implementation Pattern

linkA convenient pattern to always use interfaces where possible but to keep the code-footprint and complexity of relations small

This article recaps why using abstraction is better then concrete implementation and how to minimize the burden of overhead for using it. This is aimed at Java, but is valid in many statically typed languages which support OOP and the concept of contracts and inner classes.

Interfaces are great. They expose a clear API, enhance encapsulation and make clean polymorphism possible. Interfaces encourage you to think about responsibility and therefore the required methods and their signature, as well as nearly invite you to properly document them. Interfaces create the basic blocks of abstraction for a clean architecture.

Now in daily life it can get annoying to use interfaces everywhere. Especially in those instances were you are sure there will only be one implementation or usage in the foreseeable future. In which package should the interface and implementation go? What would be appropriate names? Is the overhead really worth it considering the interface will not be exposed to other modules? For these instance I use the following pattern:

linkThe Concise Interface Implementation

Use this pattern if

The goal is to keep the implementation concise, that means the interface and default implementation can be at the exact same location creating a kind of “mini” module. The implementation doesn’t even need it’s own unique name.

The template looks like this (Java 7+):

1public interface MyInterface {

2

3 void interfaceMethod1();

4

5 void interfaceMethod2();

6

7 final class Default implements MyInterface{

8

9 @Override

10 public void interfaceMethod1() {

11 //impl

12 }

13

14 @Override

15 public void interfaceMethod2() {

16 //impl

17 }

18

19 }

20}

You would define your interface, like any other. Then you add a inner final static (implied) class called Default representing your default implementation. Static inner classes do not have any reference to their outer class, so it behaves just like a normal class defined as top-level class.

And you would use it like this:

1MyInterface m = new MyInterface.Default();

As you can see, the intend and usage is very clear: you instantiate the default implementation of MyInterface.

I believe seeing such a construct also conveys the exact properties described above: single implementation and module private; so developers can treat it accordingly.

linkFuture-proof

If in any point in time you wish to have multiple implementation or expose this interface as an API you just move the Default implementation to it’s own class and give it a proper name (IntelliJ can do this for you). The interface and implementation are not tied to each other, they are just defined in the same location in the source code.

linkAvoid unnecessary Naming

Naming is hard. With this concept we avoid having to invent a synthetic name for the default implementation of a simple interface. Oftentimes if developers get the naming wrong, it can get very confusing and hard to read, like this example:

1TextTransformer t = new StringManager();

linkAvoid Codebase Clutter

No need to create new packages structures that do not match the intended one. No need to search for the implementation (although IDEs like IntelliJ make it very easy).

linkTestable

One of the main benefits of using interfaces is the better testability. By using well-defining contracts mocking becomes easy. You can use either a mocking library like Mockito or you just implement the interface in your test package. Either way you are able to exactly test the behavior you are interested in and mock the rest.

linkConclusion

By abstracting and creating contracts with interfaces we can create better software. Unfortunately in some cases using interfaces can be unnecessary overhead. The proposed concise interface implementation pattern mitigates this issue by defining the name and location of the implementation without removing the flexibility of later using multiple implementations or as an standalone API.

This article was published on 4/11/2018 on medium.com.

The Concise Interface Implementation PatternA convenient pattern to always use interfaces where possible but to keep the code-footprint and complexity of relations smallThe Concise Interface ImplementationFuture-proofAvoid unnecessary NamingAvoid Codebase ClutterTestableConclusion

Home

OpenSourcechevron_right



Patrick Favre-Bulle 2020