2

I frequently come across projects that strictly define an interface for each and every class. 90% of those interfaces feature only a single implementation. Proponents of these "preemptive interfacs" defend this approach as follows:

  • In Java one should always program to interfaces to minimize refactoring efforts, when an additional implementation is required.
  • Testing is much easier with interfaces, since you can stub or mock objects easily.
  • Frameworks, e.g. Spring make use of Java's proprietary Dynamic Proxies and therefore require interfaces.

While all of those points seem to have some merits, I think they don't justify the massive increase in number of classes the defining interfaces preemptively entails. Also:

  • Factoring out interfaces once multiple implementation are required is a matter of seconds with contemporary IDEs.
  • Mocking classes without interfaces is easy with Mockito or other Unit Testing Frameworks.
  • Frameworks like Spring can use byte code generation libraries like CGLIB or Javaassist instead of Java's proprietary Dynamic Proxy mechanism.

Keeping all this in mind, is there really a compelling reason for "preemptive interface" definition or is it a relict of the past and could even be regarded an anti-pattern?

  • Possible duplicate of The need for adding an interface to every class – gnat Jul 19 '16 at 10:46
  • 3
    Why do people assume the quote refers to Java interfaces when Java didn't even exist yet when the book was written (and the quote is much older than the book, and thus much older than Java, anyway)? – Jörg W Mittag Jul 19 '16 at 11:57
  • 1
    "Mocking classes without interfaces is easy with Mockito or other Unit Testing Frameworks." ... as long as you don't mind the fact that your framework is making non-trivial changes in the type heirarchy of your objects that (at least under some circumstances) could plausibly change behaviour during testing in order to hack around the platform's default behaviour of always calling an object's constructor during creation. I'd much rather just use an interface and be sure that the behaviour being tested is the one the real application will have. – Jules Jul 19 '16 at 12:41
  • 3
    "Program to an interface, not an implementation" is one of two tenets of OO design from the introductory chapter of "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard Helm, Ralph E. Johnson, and John Vlissides. It gets quoted extremely often, and very often it gets interpreted as referring to the interface construct in Java, which is simply impossible because Java didn't yet exist (at least publicly) when that book was written. Plus, it should be clear when you actually read the entire paragraph instead of just the bullet points that that's definitely … – Jörg W Mittag Jul 19 '16 at 23:12
  • 2
    not what is meant. It should also be obvious from the fact that the two languages used in the book, Smalltalk and C++ don't have that construct. If you don't actually bother reading the paragraph, then you end up with such ridiculous things as just copy&pasting the method declarations from a class into an interface and thinking that this act magically creates good OO design, as your colleague seems to do. – Jörg W Mittag Jul 19 '16 at 23:15
3

Interfaces exist (speaking of the interface keyword), so you can define an API for classes, where the implementation does not matter, only the arguments, return types and maybe thrown exceptions.

You should treat classes and their public methods exactly the same, whether they implement an interface or not. Once you realize that, you will see even a class without implementing an interface actually has and in a way is an interface.

Unless a class is defined as final, testing a normal class instead of an interface is just as easy by extending it.

  • 1
    In Smalltalk, it is called "protocol". In Objective-C, it is called "protocol". Java is highly influenced by Objective-C, but for some reason they decided to rename it to "interface", and it has been a common source of confusion with the "program to an interface not a n implementation" quote from the GoF ever since (which people somehow strangely assume refers to Java interfaces even though Java didn't exist yet when the book written, and so that cannot possibly be the case). – Jörg W Mittag Jul 19 '16 at 11:48
  • @JörgWMittag I believe in Swift it's called protocol as well. – Andy Jul 19 '16 at 11:56
  • +1 Now that the difference between interfaces and classes has been blurred, this concept is more important than ever. If you are careful about what is public (e.g only methods are public) generating an interface is trivial. Building an interface initially helps with learning if you are green, though. – JimmyJames Jul 19 '16 at 17:16
3

An old sage once said:

  • You usually don't create an interface for every class, that would be an afterthought.
  • You create interfaces as a design exercise, then you create classes that implement those interfaces.
  • You have to think that what you are creating is always a foundation upon which someone else can built some bigger.
  • Don't create little programs, create designs that can grow in an organic way.
  • We know you are perfectly capable of hacking a quick, smart and efficient solution to a problem. You are over-qualified for that. What you should strive for is creating a design, a foundation, an API, a framework, however humble they may be.
  • Than design part is one of the few funny and edifying things that are still left of this oftentimes impersonal career of ours.

That said, you can always get your IDE to extract an interface of an existing class if you need it, but you get the point.

Bottom line: you don't draw a blueprint after a bulding is built. You draw the blueprint and then you built the building based on that blueprint. But civil enginneer is a mature discipline.

  • 1
    "Bottom line: you don't draw a blueprint after a bulding is built." The "building a house" analogy only makes sense when we take into account: 1. The code is the blueprint; the compiler the builder. 2. The house can be repeatedly built and thrown away hundreds of times a day without incurring massive costs. – David Arno Jul 19 '16 at 15:09
  • @DavidArno One cannot assume that failed software projects and/or technical debt represent no waste of resources. – Tulains Córdova Jul 19 '16 at 15:41
  • Absolutely. Draw rubbish blueprints and you'll get a rubbish house. And due to the nature of software, you'll be forever hacking and budging those blueprints to try and rebuild the house properly. – David Arno Jul 20 '16 at 6:56
-1

You don't need need an interface for every class. What I do is create interfaces for injectables and implement newables without interfaces http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/.

  • 1
    There are so many other uses for interfaces than just injection. – Bent Jul 19 '16 at 11:57
  • @Bent The idea is even if you don't use injection its a good litmus test to identify when you need an interface vs when you don't – Chamindu Jul 19 '16 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.