Do I need to use an interface when only one class will ever implement it?

  • Isn't the whole point of an interface that multiple classes adhere to a set of rules and implementations?

    Or to make it easier to unittest.

    Allowing multiple classes to implement Interfaces and having your code depend on the interfaces is ESSENTIAL to isolation for unit testing. If you are doing unit testing, you will have another class implementing that interface.

    The whole point of interfaces is to allow compile-time validation of method calls, preventing occurrences of 'Method not found' exceptions (as long as the run-time environment matches the compile-time environment).

    This why I love dynamically bound languages - Unless you're checking `isinstance()`, all you care about is that whatever came in has the function/method/property you want to look at. Of course that makes good testing a priority... but requiring good practice isn't exactly a criticism...

    Public fields and methods are an "interface" in their own right. If the lack of polymorphism is intentionally planned then there is no reason to use an interface. The unit testing others mentioned is a planned use of polymorphism.

    How about the only class implementing that interface does more than just implement that particular interface and you don't want the code needing only the methods of said interface to have access to the rest of the public methods of the class. For eaxmple classes that implement both "immutable" and "mutable" behavior and you want most of your code to have an extra "insulation" layer between them and the methods that change an instance's state (insulation provided by having to "ask" whether the "mutable" interface is supported) so it is easy to spot the code that messes with state.

    Found a perfect use case for an interface implemented by a single class just now, in this thread: http://programmers.stackexchange.com/questions/281979/is-my-usage-of-explicit-casting-operator-reasonable-or-a-bad-hack

  • yannis

    yannis Correct answer

    8 years ago

    Strictly speaking, no you don't, YAGNI applies. That said, the time you'll spend creating the interface is minimal, especially if you have a handy code generation tool doing most of the job for you. If you are uncertain on whether you are going to need the interface of or not, I'd say it's better to err on the side of towards supporting the definition of an interface.

    Furthermore, using an interface even for a single class will provide you with another mock implementation for unit tests, one that's not on production. Avner Shahar-Kashtan's answer expands on this point.

    +1 testing means you almost always have two implementations anyway

    How does an interface apply to YAGNI? The linked wikipedia entry (to me) errs towards supporting the definition of an interface, rather than against it?

    @Deco YAGNI == Don't build something you ain't going to need. If you are absolutely certain you don't have any use for the contract, why design by it? But of course, if you are _not_ certain, then it's better to err towards supporting the definition of an interface, all you will have wasted is a little bit of time.

    @YannisRizos Disagree with your latter point because of Yagni. Cranking an interface from a classes public methods is trivial after the fact, as is replacing CFoo with IFoo in consuming classes. There's no point in writing it in advance of the need.

    @DanNeely that's assuming you have Resharper.

    @MattDavey Even without Resharper (or its equivalent in other languages) it should only take a minute or two even on large classes. Deleting out anything private and the bodies of public methods isn't a difficult process.

    @DanNeely I've updated the answer.

    I'm still not sure I'm following your reasoning. Since code generation tools make adding it after the fact even cheaper, I see even less of a reason to create the interface before you have an explicit need for it.

    @dan Not every language has handy code generation tools and not every developer likes using code generation tools even if they are available to them.

    I think a missing Interface is not a good example for YAGNI but for a "broken Window" and missing Documentation. The users of the class are practically forced to code against the implementation, instead of the abstraction as they should.

    @YannisRizos, even if they don't, I think I'd agree with Fabio about the non-violation of YAGNI. My personal opinion about developing in a statically bound language is that if you create a class, it probably needs an interface. The *only* exception (I've seen) is if the behavior of the class is actually part of another, interface'd class' API (e.g. a UserControl on a View). Then the tests against the interface should expose errors in the other class.

    This assumes that every class should be mock tested, which is something that I would seriously question.

    @KonradRudolph I'd love to read your answer, if you have the time to write one.

    @YannisRizos I agree pretty much with your answer, but primarily the YAGNI aspect since, as I said, mocking isn’t always required.

    Why would you ever pollute your codebase with meaningless cruft just to satisfy some testing framework? I mean seriously, I'm just a self-taught JavaScript client-side guy trying to sort out WTF is wrong with C# and Java developer OOD implementations I keep encountering in my pursuit of becoming more of a well-rounded generalist but why don't they slap the IDE out of your hands and not let you have it back until you learn how to write clean, legible code when they catch you doing that sort of thing in college? That's just obscene.

    `using an interface even for a single class will provide you with another mock implementation for unit tests, one that's not on production` but mockito allow to create mock for a concrete class. So you shouldn't count it as a second implementation- thus no need for an interface?

    +1 for @DanNeely to post an answer to this question. I strongly endorse his perspective on the subject.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM