Do you need an Interface?
Most likely no, and I tell you why
Does this ring a bell to you?
You create a controller for your REST API.
That controller calls your use case to respond to the request.
You create an Interface for that use case, with one method, which receives the DTO, and returns a Domain object (for example).
Finally, you create a new class that implements the Interface you just created; implements the use case.
By the book, this appears to be correct. Why?
You are decoupling your implementation thanks to the Interface.
Tomorrow, when a new implementation is needed, you just need to create a new class that implements the Interface, and your Controller will not change.
At the time of testing, you use that Interface and create a Mock implementation for your tests.
But, is this a good idea?
In todayโs email, I will share with you when and why you should use and avoid Interfaces.
โ๐ผ Before starting, I just wanted to let you know that I have a dedicated newsletter to the AI Native world, where you can learn how to become an AI Native developer and move your engineering organization from Cloud Native to AI Native. Folks are loving it.
Subscribe now ๐๐ป
Now, letโs back to the topic of today.
โ
Do you really have multiple implementations upfront?
If the answer is yes, you definitely have to add an Interface.
For example, if you are using different services to send data to the outside world (Azure Log Analytics API and AWS Firehose), the Interface allows you to define that abstraction, simplifying the API for the user.
If you just have one single implementation, you are just duplicating code between the Interface and the actual implementation. No point in doing this.
โ
Do you have many things behind a boundary?
Interfaces are an excellent way to define a contract when establishing a boundary.
When there are many things behind a specific boundary, the interface defines a โjointโ that is specific to a use case that other components or systems must consume.
In these scenarios, the contract that defines the Interface is fundamental, so that other developers or systems can interact with that complex behavior in a controlled and defined way.
๐ค Do you have one single implementation?
If there is only one concrete implementation, like sending data to AWS Firehose only (from the previous example), the interface is simply a reflection or a โmimicryโ of that concrete implementation.
The abstraction is defined purely by the behaviors of the concrete implementation, creating a one-to-one relationship. In these situations, creating an interface changes nothing in terms of coupling, system fragility, or extensibility.
You say:
Well, itโs cheap to create an Interface for the just in case.
I would answer that saying:
What happened last time you did that? did another implementation came up later?
๐ค Do you want to change the behavior for testing?
Thatโs fair. You plan to implement a class, for testing purposes, that implements that Interface, and you inject it.
But for that, I have for you the Delegation Pattern. With that, you can do exactly the same, and you donโt require an Interface.
๐ค Are you writing code for your internal use?
If you are implementing code for being used by yourself, like an internal component that another internal component will use, and you are creating Interfaces, then you are creating contracts for yourself.
No need to have a contract with no one.
โจ Summary
I donโt want to be the party pooper, or maybe yes, but in todayโs email, I just wanted to share with you my conclusions from many years of writing Interfaces all over the place.
Iโve been there, I feel you, you think that an Interface is the way to go; My 2 cents here:
Think twiceโฆ most likely you donโt need it.
I have much code written over there that, if I read it today, I would refactor it removing Interfaces.
I would love to hear your tales about coding with or without Interfaces. Reply to this email or comment if you are on Substack.
Thanks for your support and feedback, I really appreciate it!
Youโre the best! ๐๐ผ
๐๐ง ๐บ๐ฐ๐ถ ๐ฆ๐ฏ๐ซ๐ฐ๐บ๐ฆ๐ฅ ๐ต๐ฉ๐ช๐ด ๐ฑ๐ฐ๐ด๐ต, ๐ต๐ฉ๐ฆ๐ฏ ๐ค๐ญ๐ช๐ค๐ฌ ๐ต๐ฉ๐ฆ ๐. ๐๐ต ๐ฉ๐ฆ๐ญ๐ฑ๐ด!
๐๐ง ๐บ๐ฐ๐ถ ๐ฌ๐ฏ๐ฐ๐ธ ๐ด๐ฐ๐ฎ๐ฆ๐ฐ๐ฏ๐ฆ ๐ฆ๐ญ๐ด๐ฆ ๐ธ๐ช๐ญ๐ญ ๐ฃ๐ฆ๐ฏ๐ฆ๐ง๐ช๐ต ๐ง๐ณ๐ฐ๐ฎ ๐ต๐ฉ๐ช๐ด, โป๏ธ ๐ด๐ฉ๐ข๐ณ๐ฆ ๐ต๐ฉ๐ช๐ด


