Recently I had a very interesting debate about when to create interfaces for classes and when not to. The debate was specific to DTOs (Data Transfer Objects) but the debate can be generalised a bit further. A web article was referenced which overwhelmingly said “no, you should not create interfaces for DTOs”. When I say overwhelmingly I mean 17 people (the number of ticks the post got), so in reality, less than the average classroom size of a small New Zealand primary school.
So in this post I’ll hopefully systematically set out a whole bunch of reasons on why I (this is my opinion) believe interfacing everything (nearly everything) is indeed plain old good practice.
Argument A: The interface serves no purpose
Rebuttal: The purpose of an interface is always what you think the purpose is, a little bit cyclic but its like saying beauty lies in the eyes of the beholder. I am a unit test aficionado and even if I don’t always write unit tests for everything I go out of my way to make code unit testable. In my experience interfaces allow this to happen with ease. Interfaces also keep code scalable, it may not serve a big purpose now but can you guarantee it won’t serve a purpose a year down the track?
Argument B: I’ll add the interface when the need arises
Rebuttal: Why put off till tomorrow what you can do today. Adding an interface to any class takes under 5 clicks at most with any modern IDE. Doing this in the future may mean that you might have to touch several (already deployed) components. Depending on how complicated your release strategy is this change may not even be allowed by your release manager.
Argument C: The code (without interfaces) meets business requirements
Rebuttal: Some one can potentially write a whole application with a single method which meets business requirements, really…, is this even a fair argument? I’ll entertain it anyway. You are writing code to meet business requirements, agreed but that is not the only concern. Your code should be maintainable and scalable. Maintainable not just by you but by future developers. Adding an interface to a class just adds that extra layer of protection for you in the future to denote that all properties in the class are actually there for a reason. Not to forget it follows the “interface segregation” and “open close principle” of OO.
Interfaces also build that extra flexibility into your code to allow for those pesky requirements to change and believe me they always do. E.g. say if you have a class called Customer with three properties DOB, Name and Title. You have used this class everywhere and I mean EVERYWHERE! A new business requirement has come in to prepend the Title to the Name of the customer in parts of the application where formal communication is required. Easy, all those parts of the application will have Customer.Title + “ “ + Customer.Name. Woah! All of a sudden we have got business logic in parts of the application which only deal with the UI for example. Wouldn’t it be more elegant to use a different type of Customer, e.g. FormalCustomer in those parts of the application? If you had a simple interface, this would be a walk in the park, where all you passed in was a ICustomer and in the parts where formal communication was required, you would pass a factory to create a FormalCustomer implementation. Yes very easily done if your application is written with scalability and maintainability in mind (i.e. IOC).
Now with an interface if you ever decide to move the Customer class to a new namespace you know that you need to move the interface and the FormalCustomer too, this makes refactoring a thought process rather than simply doing it for the sake of it.
Argument D: Do you expect me to go change all classes (DTOs) and add interfaces to them?
Rebuttal: HELL NO!!! Only the ones you touch for your new code. Most times we are dealing with legacy systems where there are hundreds of classes scattered all around the place, I would suggest only touching the ones you are interested in. Sometimes this is also not possible as the classes/DTOs might be auto generated, e.g. EF entities. In that case its an executive decision you need to make and decide whether adding interfaces is truly worth is or not at this juncture in time.
Argument E: Aren’t you saying create a canonical model of the business objects with interfaces?
Rebuttal: In a way yes, unfortunately with modern tools like Entity Framework there is a very grey area where the domain meets the persistence layer. Unfortunately, if things are not designed well at the start to keep the domain (canonical models) away from the persistence layer there is very little advantage in adding an interface late in the application lifecycle.
Argument F: In the article mentioned at the start, they said “no, you should not create interfaces for DTOs”
Rebuttal: Ever heard of the line “If it is on TV it must be true”? Articles online (this one too) are merely a reference point, it is up to you what you do from that point onwards. Actually there are many articles which will strongly agree and some which may agree with me, well, this is my opinion.
Argument G: A DTO like Customer is similar to framework objects like Point and Color, you don’t see the framework interfacing those out
Rebuttal: Comparing a Customer DTO to a trivial property bag such as Point or Color is naive. I agree that some DTOs do exhibit the same attributes as trivial property bags, e.g. if you had a EF entity called CustomerType. Although I don’t think trivialising Customer in the same bucket as a Color object is prudent. In reality it could be argued that say you have a Point and then a TransformedPoint (which given a point transforms it), now you want to store these in the same collection, simple, you can’t! So you could either extend Point or extract an interface, both options may have their pros and cons (beyond the scope of this article). Although you can see how interfaces can be so powerful.
Summary
- Use interfaces as much as possible, they help you become a good abstract programmer
- Once you have felt the power of interfaces and feel that you can successfully decide when best to use them and not, that’s when you can dial them down
- Adding an interface is trivial and takes less than 5 seconds, so why the hell not!
- Don’t write code to last, write code to change, interfaces cater for that change