The Interface Is Owned by the Client

This one is a less known principle, but with great implications. It is related to the Interface Segregation Principle, as well as to the Dependency Inversion Principle. It also dictates where interfaces should live in a multiple assembly architecture.

This is going to be interesting, so hang on to your keyboards.

What Do You Mean?

Well, imagine we have an interface. On one side there is the client – the class which uses the interface. On the other side there is the implementor – the class that implements the interface. Because of which one of these does the interface have the methods that it has? Why those ones and not others?

If you answered the implementor, you’re in for a surprise. Let me elaborate.

Why Would You Think That?

Most of the people I interviewed phrase this something like “The implementor needs the methods declared on the interface”. But how could that be? The implementor doesn’t use those methods.

If we accept that the interface represents a contract, then it must also have contracted parties. One of the parties enforces the contract, and the other should abide by the contract.

Why contracts exist in the first place? Well, contracts represent an agreement between two parties that define what is to be provided as input and what is expected to be returned as output. It manages expectations.

When we use interfaces in C#, we use them because of the functionality they advertise. Notice I did not say provide because interfaces do not provide functionality, they advertise it.

But even the term advertise is not quite correct. It implies that the functionality just happened to be there, exposed by the interface, and we just happened to use it. The situation is more intentional than this. Therefore, the term I think describes best that an interface does is enforce.

Could you use an interface that you have no idea what it offers, or whose types you don’t know how to provide and/or consume? Most likely not. So, you must know in advance what that interface enforces and how to properly consume that functionality.

If an interface enforces a particular functionality and “language” (the types of objects that are passed through that interface; the inputs and outputs), that must mean that someone built that interface in an intentional manner, and the contract it describes serves someone’s purpose.

And who is that someone? The one who needs that functionality provided by the one that implements (submits to) the contract. The client defines the contract, and the service provider provides that functionality. The client cares not who nor how the functionality enforced by the contract is implemented.

Just to confuse the matters further, the analogy with the real-world contracts stops here. Think of the contract you have with your phone provider: they came up with the contract, you had to submit to that contract. Unlike the computer world, in the real world, the service provider is the one that enforces the contract, you had to sign it in its entirety. I think I understand where some of the confusion might come from.

Now, just to sum up: the client is the one that defines the interface, which enforces the functionality and the “language” that the client needs, and the implementors are the ones who submit and “pledge” to implement the contract, the whole contract and sometimes something else besides the contract.

I hope that by now it is clear and makes sense why “the client owns the interface”. And just to test your newly acquired knowledge, let’s imagine another scenario.

In Comes the Library

Let’s imagine that you are using, in your project, a third-party library off the internet. That library defines an interface. Who is the client and who is the implementor in this situation?

Take a minute. Take all the minutes you need. I’ll be here, waiting.

And the answer is…<drum roll 🥁>

Your code is the client of the library, yes, but in the particular case of that interface, the library code is the client, and your class that implements that interface, is the implementor. That interface is defined by the library and that means some code in the library is relying on the contract defined by that interface. The most common scenario is that the library has a default implementation of some functionality (an algorithm or something) that could have injected into it some custom functionality provided by whoever implements that interface. So, the library is the client, and you are the provider.

So that’s why you should never depend directly on abstractions (i.e., interfaces) defined in some library. Those abstractions are not yours and they do not reflect your needs. You should always define your own abstractions and only depend on those. Use someone else’s abstractions as an implementation detail inside classes that you own, and provide functionality described by your own contracts. Never depend on something (especially abstractions) you don’t own.

One Last Note

You could argue that, when using third party services on the web, those expose a set of functionalities, that clearly has not been defined by your software. Those services are out there, ready to be consumed, and you have no say in what their “interfaces” look like.

True, but those are not the interfaces I am referring to. In your code you should have your own interfaces defined, that reflect only the functionality you need access to, and which are implemented by classes (owned by your code, obviously) that make calls only to the subset of functionality needed by your software.

Conclusion

I hope I have convinced you of the fact that interfaces are (and should be) owned by the client. Whatever methods are on those interfaces, are there because the client needs them to be. Without the demand from the clients, there would be no supply from the implementors.

One thought on “The Interface Is Owned by the Client”

Comments are closed.