views:

224

answers:

10

I often seem to run into the discussion of whether or not to apply some sort of prefix/suffix convention to interface type names, typically adding "I" to the beginning of the name.

Personally I'm in the camp that advocates no prefix, but that's not what this question is about. Rather, it's about one of the arguments I often hear in that discussion:

You can no longer see at-a-glance whether something is an interface or a class.

The question that immediately pops up in my head is: apart from object creation, why should you ever have to care whether an object reference is a class or an interface?

I've tagged this question as language agnostic, but as has been pointed out it may not be. I contend that it is because while specific language implementation details may be interesting, I'd like to keep this on a conceptual level. In other words, I think that, conceptually, you'd never have to care whether an object reference is typed as a class or an interface but I'm not sure, hence the question.

This is not a discussion about IDEs and what they do or don't do when visualizing the different types; caring about the type of an object is certainly a necessity when browsing through code (packages/sources/whatever form). Nor is it a discussion about the pros or cons about either naming convention. I just can't seem to figure out in what scenario, other than object creation, you actually care about wether or not you're referencing a concrete type or an interface.

A: 

Interfaces don't have fields, hence when you use IDisposable (or whatever), you know you're only declaring what you can do. That seems to me the main point of it.

Oren A
But fields should be encapsulated anyway.
Don Roby
@donroby: Sorry, I don't think I get what you mean.. Can you explain? (not what encapsulation is, I understand that, but how it contradicts what I'm saying.) Thanks.
Oren A
It's better to not need to know whether something has fields. I just mean I don't think knowledge of having or not having fields is a good reason for knowing whether something is an interface. I might elaborate in an actual answer...
Don Roby
Like donroby, I don't think this answers why you'd care if your reference is a class or an interface.
macke
+1  A: 

Things that concrete class can have and the interfaces can't:

  1. Constructors
  2. Instance fields
  3. Static methods and static fields

So if you use the convention of starting all interface names with 'I' then it indicates to the user of your library that the particular type will not have any of the above mentioned things.

But personally I feel that this is not a reason enough to start all interface names with 'I'. The modern IDEs are powerful enough to indicate if some type is an interface. Also it hides the true meaning of an interface name: imagine if Runnable and List interfaces were named IRunnable and IList repectively.

abhin4v
In .NET there is an IList.
Jonn
Concrete classes do not necessarily have any of those things. And it's hard to think of any circumstances where you would care about whether a type *had* such things without caring about the details, so either way you have to read the documentation.
Porculus
Java interfaces *can* have "static fields": `public interface MagicNumber { public static final int L_U_E = 42; }` These were common as the "typesafe enum pattern" prior to Java actually having enums.
Stephen P
Constructors are only necessary at object creation (of course) and using DI the object construction is effectively abstracted away, making this point moot. Instance fields is an implementation detail and should be encapsulated. For exposure, use properties. Static fields that are not read-only constants implies global state, which is considered a bad practice. Static methods that modify state is also considered a bad practice for the same reasons. Even still, static methods may be represented using delegates in the languages that support such a feature.
macke
A: 

When a class is used, I can make the assumption that I will get objects from a relatively small and almost well-defined range of subclasses. That's because subclassing is - or at least it should be - a decision that isn't made too easily, especially in languages that don't support multiple inheritance. In contrast, interfaces can be implemented by any class, and the implementation can be added later to any class.

So the information is useful, especially when browsing through code, and trying to get a feeling what the code author intended to do - but I think it should be enough, if the IDE shows interfaces/classes as distinctive icons.

Chris Lercher
Not sure what you mean by "get objects". That sounds like you'd type dependencies to classes, which is just what you shouldn't do in my opinion. You're definitely correct about the necessity of differentiating types when browsing through code but, as implied, any modern IDE should take care of that in the UI. The question is why would you care whether your object reference is typed to a class or an interface? Anyway, thanks for your answer!
macke
@macke: With "get objects", I mean anywhere, looking at any line of code, not just in the signatures of methods. Now, when I look at a line, I can ask myself: The type hierarchy of classes (especially in languages without multiple inheritance) implies a strong categorization, like "it's first and foremost a Person". Whereas an interface just says something like "and by the way, the object also implements these methods". It's like reading a book: We're constantly trying to understand the context and use any hint to ask: What does the author probably mean?
Chris Lercher
+1  A: 

I agree with you (and thereby do not use an "I" prefix for interfaces). We shouldn't have to care whether it is an abstract class or an interface.

Worth noting that Java needs to have a notion of interface solely because it does not support multiple inheritance. Otherwise, "abstract class" concept would suffice (which may be "all" abstract, or partially abstract, or almost concrete and just 1 tiny bit abstract, whatever).

Amrinder Arora
A: 

Distinguishing between interfaces and classes may be useful, anywhere the type is referenced, in the IDE or out, to determine:

  • Can I make a new implementation of this type?
  • Can I implement this interface in a language that does not support multiple inheritance of implementation classes (e.g., Java).
  • Can there be multiple implementations of this type?
  • Can I easily mock this interface in an arbitrary mocking framework?

It is worth noting that UML distinguishes between interfaces and implementation classes. In addition, the "I" prefix is used in the examples in "The Unified Modeling Language User Guide" by the three amigos Booch, Jacobson and Rumbaugh. (Incidentally, this also provides an example why IDE syntax coloring alone is not sufficient to distinguish in all contexts.)

Andy Thomas-Cramer
Is the example you mentioned available anywhere online? I'd love to read it!
macke
+8  A: 

Most of the time, you probably don't care. But here are some instances that I can think of where you would. There are several, and it does vary a little bit by language. Some languages don't mind as much as others.

In the case of inversion of control (where someone PASSES you a parameter) you probably don't care if it's an interface or an object as far as calling its methods etc. But when dealing with types, it definitely can make a difference.

  • In managed languages such as .NET languages, interfaces can usually only inherit one interface, whereas a class can inherit one class but implement many interfaces. The order of classes vs interfaces may also matter in a class or interface declaration. So you need to know which is which when defining a new class or interface.

  • In Delphi / VCL, interfaces are reference counted and automatically collected, whereas classes must be explicitly freed, so lifecyle management on the whole is affected, not just the creation.

  • Interfaces may not be viable sources for class references.

  • Interfaces can be cast to compatible interfaces, but in many languages, they cannot be cast to compatible classes. Classes can be cast to either.

  • Interfaces may be passed to parameters of type IID, or IUnknown, whereas classes cannot (without a cast and a supporting interface).

  • An interface's implementation is unknown. Its input and output are defined, but the implementation which creates the output is abstracted. In general, ones attitude may be that when working with a class, one may know how the class works. But when working with an interface, no such assumption should be made. In a perfect world, it might make no difference. But in reality, this most certainly can have affect your design.

Phil Gilmore
1) In c#, interfaces can definitely inherit multiple interfaces. I'd love to hear the rationale behind such a decision however, any language in particular you had in mind? I'm not sure I understand the note about ordering, if you could elaborate on that I'd be much obliged!
macke
2) Very interesting, I'll have to read up on that. I have no Delphi experience at all so obviously I can't comment further than that.
macke
3) Not sure what you mean by this.
macke
4) Considering the practice of programming to interfaces rather than implementations, isn't that a good thing? Why cast to a class if you can cast to an interface? Not sure still why you'd care about the concrete type in this scenario.
macke
6) I certainly understand and appreciate your pragmatic view about this, but isn't that a sign of code smell or is it just an unfortunate fact of life? :)
macke
It's a bit amusing that we're both having a discussion about a language agnostic concept, from a perspective of our chosen language :) My perspective is from Delphi and yours if from C#, so I'll address these points from a C# perspective.
Phil Gilmore
1) I was referring to Oxygene, but even there, it seems I was mistaken. Oxygene and C# both permit this. Delphi does not.3) Class references, as opposed to object references, are not supported in many languages so you may not care. Since they are a ref to a class, you must know what is a class and what is not.4) Yes, it's a good thing. I don't condone doing it, but pointed it out for insight.6) Consider point 5. You can't pass classes to parameters of this type, so you MUST know if your reference type is an interface or a concrete type. Code smell? Maybe but by coincidence...
Phil Gilmore
... not due purely to this awareness. I don't think it's ideal, but a fact of life. My opinion is that you should code to the interface (whether you have an interface or a concrete type), and it's best that you know as little as possible about the implementation and most of the time it can be done. But actually KNOWING whether you have an interface or not is the question I'm addressing here. My points are for rhetorical insight only. I think you and I mostly agree on the ideal use of interfaces.
Phil Gilmore
A: 

Hi Macke,

among others the GoF advocate Programming to an interface rather than to an implementation. It is often beneficial to introduce a layer of abstraction via an interface and have multiple classes implement the stated functionality in different ways - see the java list interface (apidocs) for example - as opposed to inheritance. A class hierarchy could suffer, if the implementation of the parent class (if chosen over the interface) changes. E.g. modifications in the parent class could ripple through to some child classes, but not to others as some overrode methods, while others didn't.

Kind regards, Benjamin.

benjamin
Unfortunately I think you may have misunderstood the question. It's not about why programming to an interface is a good thing but rather, why should one ever have to care if your object reference is a class or an interface? Seems to me as a consumer of an object (in business logic, not factory logic) you'd never be interested.
macke
A: 

You should care, because :

  1. An interface with capital "I" enables one, namely you or your co-workers to use any implementation which implements the interface. If in the future you figure out a better way to do something, say a better list sorting algorithm, you will be stuck with having the change ALL of the invoking methods as well.

  2. It helps in understanding code - e.g. you don't need to memorize all 10 implementations of say, I_SortableList , you just care that it sorts a list (or something like that). Your code becomes practically self-documenting here.

To complete the discussion, here is a pseudocode example illustrating the above:

//Pseudocode - define implementations of ISortableList
Class SortList1 : ISortableLIst, SortList2:IsortableList, SortList3:IsortableList

//PseudoCode - the interface way
void Populate(ISortableList list, int[] nums)
{
    list.set(nums)
}

//PseudoCode - the "i dont care way"

void Populate2( SortList1 list, int[] nums )
{
    list.set(nums)
}

...
//Pseudocode - create instances

SortList1 list1 = new SortList1();
SortList2 list2 = new SortList2();
SortList3 list3 = new SortList3();

//Invoke Populate() - The "interface way"
Populate(list1,nums);//OK, list1 is ISortableList implementation
Populate(list2,nums);//OK, list2 is ISortableList implementation
Populate(list3,nums);//OK, list3 is ISortableList implementation

//Invoke Populate2() - the "I don't care way"
Populate(list1,nums);//OK, list1 is an instance of SortList1
Populate(list2,nums);//Not OK, list2 is not of required argument type, won't compile
Populate(list3,nums);//the same as above

Hope this helps,

Jas.

Jas
I'm not sure you've understood the question. Programming to an interface is a good practice and I wholeheartedly agree with it. The question is why, as a consumer of an object instance, would you care whether your reference is an interface or a class? Interfaces are still interfaces, no matter if they are prefaced with and 'I' or not and honestly it doesn't matter what the naming convention is as long as it's consistent. I hope this clears things up a bit!
macke
I don't see how it's possible to think about your question without referring back to principles of extendability ("design for change") as well as reuse. Think about extending an object factory. How is anyone in your team going to add support for another implementation of your interface (x50 for reasonably complex commercial systems) if they have to waste time by going back and forth and checking that MyObj is an interface/abstract class and not an implementation? Namely, that's what you will be doing to avoid overusing inheritance (white box reuse). All the best!
Jas
A: 

You want to see at a glance which are the "interfaces" and which are the "concrete classes" so that you can focus your attention to the abstractions in the design instead of the details.

Good designs are based on abstractions - if you know and understand them you understand the system without knowing any of the details. So you know you can skip the classes without the I prefix, and focus on the ones that do have it while you are understanding the code, and you also know to avoid building new code around non-interface classes without having to refer to some other design document.

MadKeithV
I'm not sure this answers the question. Even though you do advocate a good practice of focusing on design rather than concrete details, I don't see how caring whether or not your object reference is an interface or a class makes any difference in this sense.
macke
In my language of choice (C++) there is really no difference between "interfaces" and "concrete classes" - and I have no problem with an interface that has no pure virtual methods. However, I do want to be able to see clearly which classes were intended as "interfaces" (the concept), distinct from classes which are just "concrete implementations".
MadKeithV
+1  A: 

I agree that the I* naming convention is just not appropriate for modern OO languages, but truth is this question isn't really language agnostic. There are legitimate cases where you have an interface not for any architectural reason but because you simply don't have an implementation or have access to an implementation. For these cases you can read I* as *Stub or similar, and, in these cases, it might make sense to have an IBlah and a Blah class

These days, though, you rarely come up against this, and in modern OO languages when you say Interface you actually mean Interface not just I don't have the code for this. So there is no need for the I*, and in fact it encourages really bad OO design as you won't get the natural naming conflicts that would tell you something's gone wrong in your architecture. Say you had a List and an IList... what's the difference? when would you use one over the other? if you wanted to implement IList would you be constrained (conceptually at least) by what List does? I'll tell you what... if I found both an IBlah and a Blah class in any of my codebases I would purge one at random and take away that person's commit privileges.

CurtainDog
Just to continue the rant a little bit more, with dependency injection you don't even need to care at object creation.
CurtainDog
Love the rant, even if it doesn't really answer my question. :)
macke
And you're probably right that the question isn't language agnostic, but I couldn't think of a better tag since I'm discussing the concept of interfaces regardless of language implementation. Certain implementations may obviously impose details that require you to care, like Phil Gilmore's note about Delphi. I *think* that on a conceptual level you'd never care about whether or not your reference is typed as an interface or a class but I'm not *sure*, hence the question.
macke