I understand the principles of Coding to Interfaces - to decouple the implementation from the interface, and to allow implementations of the interface to be swapped in and out.
Should I code to interfaces for every class I write or is that overkill? I don't want to double the number of source files in a project unless it's really worth it.
What factors can I use to decide whether to code by interface or not?
In most cases, a final class is the best thing you can create. If a user doesn't like your class, they can simply choose not to use it. However, if you're building up a hierarchy of objects you should introduce an interface for every class.
If, as a programmer, you code against the implementation then as soon as it changes your code stops working. So think of the benefits of the interface this way: it hides the things you do not need to know making the object simpler to use. it provides the contract of how the object will behave so you can depend on that.
You don't need to create an interface if you are not going to use it. Typically you need an interface when: Your program will provide several implementations for your component. For example, a default implementation which is part of your code, and a mock implementation which is used in a JUnit test.
In general I agree with the other answers: use an interface when you know or anticipate change and/or different implementation, or go for testability.
But it's not always easy to know in advance what may change in the future, especially if you are not so experienced. I think the solution for that problem is refactoring: keep it simple (= no interface) as long as it is not needed. When the need arises simply do an "Introduce/Extract interface" refactoring (supported by almost all decent IDEs).
When you do it extract only those methods that are actually needed by the callers. Don't be afraid to extract more then one separate interfaces (if not all of the extracted methods are really coherent).
One driver of the refactoring might be the testing: if you can't easily test something with classes only consider introducing one/some interface(s). This will also allow you to use mocking which may greatly simplify testing in many cases.
Edit: based on Tarski's comment I've realized one more important scenario/adjustment to the previous statements:
If you provide an external API (for other [sub]projects, or really release it "to the wild") then using interfaces in the API (except for simple value classes) is almost always a good idea.
It will allow you to change the impl if you like without disturbing the client code. You will have a problem only if you also have to change the interface. Not breaking compatibility will be very tricky (if not impossible).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With