6

According to some answers to this question, I should not add prefix "i" to interface.

I'm not raising new reasons to support or oppose the prefix "i" on interface. Instead what I don't understand and want to clarify is, why would the post use the tone "I don’t want" in "I don’t want my users knowing that I’m handing them an interface"?

I think the answers like "an interface is not much different from an abstract class" is a bit contradictory compared with "I don’t want my users knowing that I’m handing them an interface.". If interfaces really are not much different to classes, why would I still care if users know whether some type is an interface or not?

Letting users know I'm handing them interfaces may be none of their business, but even if users know something that is none of their business, it also seems to do no harm. Why would there be such severity in "I don’t want my users knowing that I’m handing them an interface" instead of simply saying, "Users don't need to know that I’m handing them an interface."? What bad actions may users take when they know I'm handling interfaces instead of a concrete class? Or what are negative impacts exist when a user knows a type is an interface instead of a concrete class?

Engineer
  • 781

10 Answers10

55

why would the post use the tone "I don’t want" in "I don’t want my users knowing that I’m handing them an interface."

This is a cite from the "Clean Code" book by Robert Martin, a.k.a "Uncle Bob". And though Robert Martin is surely a respectable and experienced software engineer, he is often critized for his tone. Many people think it is too "schoolmasterly", especially in the mentioned book.

In the sentence you asked about, "I don't want my users knowing ..." puts Bob Martin's thought process into the center of the explanation, not the users' point of view. He could have also written "I don't want my software to be designed in a way that my users need to know ...", but that would have been far longer, less striking and less memorable.

My recommendation: just read everything what Robert Martin wrote with a grain of salt, don't take him too literally. His statements and writings are recommendations, not dogmas. Then you can learn a lot from them.

Doc Brown
  • 218,378
25

Are you sure you understood the answer to the question you linked correctly? Because the answers agreed that putting an I in front of interfaces if that is the convention in your language of choice is perfectly fine.

That said, to answer your actual question as asked: Users of anything but an ancient stone age compiler will see the type description in their IDE. If your IDE says type: public interface ThisIsReallyNotAnInterfacePinkyPromiseItsTheRealDeal, does that make anything better? It just looks stupid. It is an interface. The compiler knows.

"I don't want my users to know" is a stupid reason: it doesn't work in practice and it is basically an admission that the code and architecture doesn't work properly, unless you lie to your users.

How about just building the best software you can, using the naming convention people are used to in that language. If they are used to ISomething let them have it, if they are used to Something and SomethingImpl then go for it.

In the end, that I will not make or break software. It's the cupholder in a car. Great if it works as you expect it in that brand of car, crappy if someone lied to you about it. In the end, being lied to by a sleaze salesman about it seems worse than just having no cupholder.

nvoigt
  • 9,230
  • 3
  • 30
  • 31
11

The top answer of "because that's how uncle Bob chose to phrase it" is correct, but I'd like to expand on why we would come up with the I prefix in the first place, before uncle Bob railed against it.

I would like to offer the interpretation here that the origin of the I prefix for interfaces is not because we want consumers to know it's an interface, but rather that it was introduced as a way to avoid needing to come up with two synonyms in the case where there is currently only one implementation of said interface and developers are struggling to describe the interface differently than the implementation.

Let's start from a point of agreement: even if only one implementation currently exists, we should already use an interface as an abstraction on top, so that we can later introduce different implementations of the same interface. If you disagree with this premise, you're not going to agree with anything going forward.

So, we have a class called FooCalculator. What should we name its interface? Now that there's only one possible implementation, it's hard not to describe the interface as one that "calculates Foos". But we can't reuse FooCalculator here (and I'm specifically ignoring namespacing as a solution here, because at the end of the day, while clever, it would still negatively impact readability).

We could come up with a synonym... well, a calculation is also called a computation, to we could use FooComputer as the interface name.

I put good money on it that it won't take long for you to reference the interface when you needed to reference the class and vice versa, because the names are interchangeable and which is which is purely an artifact of which we wrote first and which name we came up with first. That's not a good naming system.

Instead of looking for synonyms, we could instead reuse the name, referring to the interface as "the interface of the Foo calculator", which is actually a very apt way to put it. Well, that's exactly what IFooCalculator tells you: I-Foo-Calculator.

Note that you could also invert this and use the "real" name for the interface. This is why you see some languages sometimes favor FooCalculator for the interface and FooCalculatorImpl for the implementation. It's the same solution, but the other way round.

This would be different if we already had multiple implementations that we wanted to build from the get-go. For example, if we're thinking of implementations of different ways to calculate Foo, e.g. one by a very expensive process, the other by a much easier approximation, a third by asking an external API, ...; then it would be natural for FooCalculator to the be interface and PreciseFooCalculator, ApproximateFooCalculator and OnlineFooCalculator to be the implementation names. No conflict here.

But this is not how most codebases work. We don't start with multiple implementations, we start with one and we prepare for future extension. Annoyingly, we are already forced to come up with a name even though we only have one implementation, and it's really difficult to figure out the link by only observing one thing, plus it might even be the case that we don't even know how we might want to create variant, making it impossible to come up with a correct name before we even know what it is that we're trying to capture and express. Maybe the variation isn't that there's multiple ways of calculating Foo, but that we want to be able to calculate Bar the same way. That's a different scenario that would lead to a different shared interface name.

Flater
  • 58,824
7

I don’t want my users knowing that I’m handing them an interface because I don't want them to break when I change my mind and hand them something else.

Oh sure, in many languages this is a pipe dream. Even if I prefixes weren't giving away what this really is, the byte code does anyway. Java doesn't have the I wart tradition but a switch will still break using code, unless you recompile.

So if it's a pipe dream why should anyone care? Because people are still writing languages and some day they may fix this. In any case it's nice to know the difference between the ideal and what we've learned to live with.

But if you’re stuck in a language where the compile gives it away anyway then forbidding the I isn’t getting you much. So stick to the convention of the language.

candied_orange
  • 119,268
3

An interface, particularly on an incoming parameter, says “I need x,y,z and I don’t care how I get it)”, it’s a declaration made by the recipient (aka function or class).

And it is absolutely the recipient’s responsibility to say what it needs (in languages where that is possible).

So, frankly, both versions are simply dead wrong and ass-backwards. Callers need to know the requirements, and interfaces describe the minimum requirements.

jmoreno
  • 11,238
2

Ideally "I want users not to know" and "Users don't need to know" are aligned.

Any information you pass to users of a library/API etc. needs to be parsed by the users. That costs time, brain power and potentially leads the users into the wrong directions because they assume an intent that was not what drove the decision. Any information that is not necessary for the users to know to successfully interact with your software is at best just a distraction (that might mean they spent a tiny bit more time understanding everything) and at worst something they will incorporate explicitly into how they work with your software and that constrains you in your later choices. As an ideal programmer you want to achieve the optimal product, thus anything that hinders a user's adoption of your software is something you don't want to add. Thus, any information that isn't necessary for the users, you don't want to send their way, because it is not "no harm". Even if it does nothing bad on its own, it likely costs time.

Note that nearly no rule is set in stone and thus there can be exceptions for most rules and arguments, typically they arise from different goals that contradict each other. But "I don't want my users to know" is pretty equivalent to "The users don't need to know" because you should want to provide something that is easy to adopt by users and thus ideally what you want to deliver matches exactly what users need to know. Sometimes there might be other "wants" on the development side that - at least on surface level - contradicts providing the best product for a user, e.g. because a little imperfection for now saves time or makes the software more maintainable etc. Though, ideally there is still a wish from developer side to avoid this, there is just a competing goal that is stronger in that particular case. In this case however, both align anyway.

0

In Swift, there are two ways: Either you pass an arbitrary object that implements the interface. The receiving code knows it’s an instance of some class but doesn’t know which class. And tomorrow I can pass an instance of a different class implementing the interface.

Or you pass an “existential interface”. Actually “existential protocol” because Swift calls interfaces protocols. That is a new object containing an instance of the protocol itself, with the underlying object stashed away somewhere.

In each case, the user knows their method parameter is an interface or an instance implementing the interface because tHat is how the method parameter is declared. But whether it’s an interface or a class instance doesn’t make any difference to you.

gnasher729
  • 49,096
0

I'm in full agreement with Doc Brown but I would like to add that the quoted phrase is pretty confused if you take it at face value. FWIW, I think a much better way to say it would be "it shouldn't matter" to client code (or coder) whether a declaration is in terms interface or a class. I would expect interfaces to be the norm, though.

Assuming "hand" means 'pass or return', the real issue with the quote in question is that you can't 'hand someone an interface'. In mainstream OO languages, you can only "hand" someone an object.

I've always thought the Uncle Bob was a little overrated. This is a good example of why, perhaps. I'm sure he knows that you can't pass or return interfaces. He's just using sloppy language, which is fine until he got a massive following of people who treat his guidance as sacrosanct.

JimmyJames supports Canada
  • 30,578
  • 3
  • 59
  • 108
-1

It's because it's none of their business that you have "I don’t want my users knowing". It isn't harmless.

The harm comes when you want to change between giving them a class and giving them an interface. If you have to change the name to fit a naming convention, then the user has to be changed to match the new name.

Caleth
  • 12,190
-1

In general, the primary reason the author of a type "doesn't want users of the class to know X about it" is the more users know about a type, the more likely they are to use it in a manner that would be incompatible with some later change the original designer would like to make. A decision to reveal certain details about a type should generally only be made after a careful evaluation about compatibility with possible future design changes. Keeping the details private means there is no need to perform such evaluation.

I don't really think that principle applies here in languages which make a distinction between classes and interfaces, since interface types can be used in some ways class types cannot, and vice versa. Given a class type with no exposed fields, it's generally trivial to create an interface type that could be used by someone needing an interface with the same properties and methods, and if the creator of a class would expect some clients might need such an interface, the creator of the class should supply one from the beginning, and should make it obvious which of the two types being defined is the class and which is the interface. Code which passes references should use the interface type, but code which needs to extend functionality of existing methods should inherit from the class type.

supercat
  • 8,629