107

I have been reading "Clean Code" by Robert Martin to hopefully, become a better programmer. While none of it so far has been really ground breaking it has made me think differently about the way I design applications and write code.

There is one part of the book that I not only don't agree with, but doesn't make sense to me, specifically in regards to interface naming conventions. Here's the text, taken directly from the book. I have bolded the aspect of this I find confusing and would like clarification on.

I prefer to leave interfaces unadorned. The preceding I, so common in today’s legacy wads, is a distraction at best and too much information at worst. I don’t want my users knowing that I’m handing them an interface.

Perhaps it is because I'm only a student, or maybe because I have never done any professional or team based programming but I would want the user to know it is an interface. There's a big difference between implementing an interface and extending a class.

So, my question boils down to, "Why should we hide the fact that some part of the code is expecting an interface?"

Edit

In response to an answer:

If your type is an interface or a class is your business, not the business of someone using your code. So you shouldn't leak details of your code in this thrid party code.

Why should I not "leak" the details of whether a given type is an interface or a class to third-party code? Isn't it important to the third-party developer using my code to know whether they will be implementing an interface or extending a class? Are the differences simply not as important as I'm making them out to be in my mind?

Aaronaught
  • 44,523

9 Answers9

100

If you stop to think about it, you'll see that an interface really isn't semantically much different from an abstract class:

  • Both have methods and/or properties (behaviour);
  • Neither should have non-private fields (data);
  • Neither can be instantiated directly;
  • Deriving from one means implementing any abstract methods it has, unless the derived type is also abstract.

In fact, the most important distinctions between classes and interfaces are:

  • Interfaces cannot have private data;
  • Interface members cannot have access modifiers (all members are "public");
  • A class can implement multiple interfaces (as opposed to generally being able to inherit from only one base class).

Since the only particularly meaningful distinctions between classes and interfaces revolve around (a) private data and (b) type hierarchy - neither of which make the slightest bit of difference to a caller - it's generally not necessary to know if a type is an interface or a class. You certainly don't need the visual indication.

However, there are certain corner cases to be aware of. In particular, if you're using reflection, interception, dynamic proxies/mixins, bytecode weaving, code generation, or anything that involves messing directly with the environment's typing system or code itself - then it's very helpful and sometimes necessary to know right off the bat whether you're dealing with an interface or a class. You clearly don't want your code to mysteriously fail because you tried to add a class, rather than an interface, as a mixin.

For typical, vanilla, run-of-the-mill business logic code, though, the distinctions between abstract classes and interfaces do not need to be advertised because they'll never come into play.

All of this being said, I tend to prefix my C# interfaces with I anyway because that is the .NET convention used and advocated by Microsoft. And when I'm explaining coding conventions to a new developer, it's far less hassle to just use Microsoft's rules than to explain why we have our own "special" rules.

Aaronaught
  • 44,523
27

In many ways, consistency is more important than convention. As long as you're consistent in your naming schemes, they won't be hard to work with. Prefix interfaces with an I if you like, or just leave the name unadorned, it doesn't matter to me as long as you pick a style and stick with it!

Jim Nutt
  • 557
14

Well this is not about implementing the interface or extending a class. In thoses cases, you know anyway what you are doing.

However, when third party code (another module of the application for exemple) manipulates you data, this code should not care if you are presenting an interface or a class.

This is the whole point of abstraction. You are presenting to this third party code an object of a given type. This given type has some member function you can call. That's enough.

If your type is an interface or a class is your business, not the business of someone using your code. So you shouldn't leak details of your code to this third party code.

By the way, interfaces and classes are reference types at the end. And this is what matters. So this is what your naming convention must emphasize.

user
  • 2,703
deadalnix
  • 6,023
13

The book is full of good stuff, but I would still add "I" to the interface name.

Imagine you have public interface ILog with a default implementation public class Log.

Now, if you decide to have public interface Log, all of a sudden you have to change Log class to public class LogDefault or something on those lines. You went from having one extra character to seven - surely that's wasteful.

There is often a fine line between theory and practice. In theory this is a really good idea, but in practice it's not so good.

CodeART
  • 4,060
  • 1
  • 22
  • 23
11

Most answers seem to assume that the programming language is either Java or C# where there is a concept (or keyword) for interfaces / abstract classes. In these cases, in a decent IDE, it is immediately visible with which type of class one deals and writing public interface IMyClass is unnecessary duplication. It is like you wouldn't write public final FinalMyClass - imagine putting every keyword in the classes name.

However, in my opinion in C++ the situation is a little different as one has to dive into the header file and see if the class has any virtual methods to find out if it is an abstract class. In that case, I can clearly see an argument for writing class AbstractMyClass.

So my answer would be: It depends on the programming language.

Updated 2016: 2 years of C++ experience later I would now probably consider it bad practice to prefix class names with Abstract, though I'd say there are probably code bases that are so complex that it might make sense.

Christophe
  • 81,699
Ela782
  • 211
8

Follow the idioms of the language you are using.

Each language has its own idioms and coding guidelines. For example, in C#, it is idiomatic to prefix interfaces with I. In Go, it is not.

Pete
  • 9,016
3

The answer to your question in the title:

Should interface names begin with an "I" prefix?

is simply: No.

The response to the two "why" questions, one being a rewording of the other

  1. "Why should we hide the fact that some part of the code is expecting an interface?"
  2. Why should I not "leak" the details of whether a given type is an interface or a class to third-party code?

is that we don't need to hide anything. Client code, should not know or care if it is consuming an interface or using a concrete class. It must always be possible to replace the interface with an implementation of that interface whithout altering the correctness of the program. This is the Liskov Substitution Principle.

Conversely, if the code is using a concrete implementation, it is possible to refactor that and hide the implementation behind an interface.

Conformity, is the reason some give to stick with the "I" prefix, mostly in the context of C#. That is of course never a good reason. Don't go blindly do something because others do it, without questioning their rationale. People make mistakes. For the designers of the C# library, who are so old they've worked most of their career on monochrome screens, using the "I" prefix may seemed like a good idea at the time, but turned out to be a mistake.

Why interfaces must not have an "I" prefix

  • Good code is all about communication. Names must be clear and meaningful. Interface names are spread around the code base. The name of the implementing class is only visible on one line; there where the object is constructed. Therefore interface names must be kept clean and may not have an "I" prefix.

  • The I is very ugly and obnoxious. It gets even worse when the real typename starts with an I as well.

      interface IIrInstrument : IInstrument
    

    class Instrument : IIrInstrument

    Nobody wants abominations like this in their code base.

  • Refactoring becomes much easier when type names don't distinguish between interface and implementation. Imagine a large code base is using a concrete class called Connection. If one day a new kind of Connection comes around, one might want to use an interface instead. If that were called IConnection, this must be renamed in all the files where a Connection is used. It is much cleaner to just change the existing Connection class into the interface, and add implementations with meaningful names such as HttpConnection and DatabaseConnection. Only the lines where a connection is constructed need to change.

    For the opposite refactoring, removing the IConnection interface and replacing it with a single concrete implementation, things are even worse. One must choose between two evils of either renaming every occurrence or calling the concrete implementation IConnection which is just wrong.

  • Abstractions are difficult and choosing a clear meaningful name for them is difficult. The I prefix naming convention dictates a name that is often wrong. For example, it leads to the definition of an "IDollar" interface for a "Dollar" class, where the correct name for this concept should simply be "Currency". 1

  • The "I" prefix also leads to misinterpretation and other issues. Consider the problems with this:

      interface ISomething
      class Something : ISomething
      class MockSomething : ISomething
    
    • Something is only one implementation of ISomething, yet it is the one with the generic name, as if it was somehow special.
    • MockSomething seems to derive from Something, but it doesn't, it implements ISomething. 2

The worst that can happen is that you end up with mix in your code base with some interfaces with and some without the prefix. If that's your situation it is time to show true ownership of your code. Have trust in your compiler and unit tests and refactor those prefixes away.

MathKid
  • 139
1

In my (Java) code, I tend to have this convention in the APIs I expose to callers:

  • Functionality is provided through interfaces, and never by classes.
  • Non-functional parts are classes.

By non-functional, I mean things like pure data structures (such as classes that act as bridges to XML serialization or the ORM), enumerations and exceptions, all of which can't be interfaces (well, you can for the pure data classes, but it's a lot of work for very little gain as there's nothing that those classes do except hold data).

In terms of naming conventions, interfaces tend to map to either actor nouns (e.g., FooBarWatcher) or adjectives (e.g., FooBarWatchable) and both pure data classes and enumerations map to non-active nouns (e.g., FooBarStatus); the IDE can guide the API consumer without special naming conventions. Exceptions follow usual Java conventions (FooBarException, FooBarError, FooBarFault) of course.

I'll also often put the interfaces in their own package or even in their own library, just to ensure that I'm not tempted to break my own rules. (This also helps me manage the build when I'm deriving the code from external sources such as WSDL documents.)

0

Lots of answers address following the local/language convention’s, but none seem to touch on the cross language practice of “Accept interfaces return concrete types”. The convention of using the prefix both makes it easy to verify that this is being done, and serves as a reminder to do so.

The reason for the practice is grounded in encapsulation (the receiving function knows exactly what it needs, and shouldn’t require the sender to expose more than is necessary, while it doesn’t know what the caller needs and thus should, in general, return what it has).

So, in languages with this convention, one should definitely follow it and use the prefix.

jmoreno
  • 11,238