IInterface Considered Harmful

Mike Mueller

Nice SQL Injection vulnerability in the opening code sample.

Christian

Before someone writes an article or post like this they should educate them selves about the topic. Here is a nice article that described what hungarian notation is and why it is helpful.
https://www.joelonsoftware…

Mike Ober

"Visual Studio already colors the interface type differently from a class type. "

Not true in all situations. If you have to print your code or look at it in a non-language smart editor, then all the color information is lost. Hungarian notation is very useful in these circumstances.

As for the premise that developers don’t understand, or at least correctly use interfaces, I’d have to agree with the author. Interfaces are contracts that specify thou shalt implement these features in your consuming class. Nothing more, nothing less.

Andre Prellwitz

Filed under the same category as “I prefer tabs and will impose it wherever I can”. The major reason so many devs prefer it is that it’s a convention that’s easy to identify–on a print-out, even–and speeds mental ingestion, categorization, and understanding. You know, the same reasons that road signs are different shapes, colors, and locations.

Wieslaw Skarzynski

It’s taking people long enough to understand that Hungarian Notation wasn’t meant to describe type of variables. It was meant to describe purpose or meaning.

Gerardo Orozco

I really like this point of view. “speeds mental ingestion, categorization, and understanding”. I agree with many criticisms raised against Hungarian notation, but at least when coding in C, when I see a variable prefixed with p or pp (double pointer), I don’t even have to think about it, my brain switches to “pointer mode” and knows intuitively when I should manipulate the pointer, and when I should dereference it. If I work with a non-Hungarian codebase using pointers, it is like hitting a road bump every time the pointer is used, I have to pause, check the declaration, reason for correctness. This is certainly a support case for “better mental ingestion, categorization and understanding”. Couldn’t have worded it better myself.

Russ Freeman :eu:

I’m a fan of XfromY style naming. A class implementing an interface is effectively mapping one world into another.
So if you take PersonRepository, you might have PersonRepositoryFromSqlSer er or PersonRepositoryFromMongoDb. It’s the perfect mapping from “Ports and Adapters” from the Onion Architecture.

Dean Goddard

I admit many years ago I wrote Hungarian Notation but not any more. I also agree if you use interfaces to abstract classes, we probably should drop the ‘I’. But surely IDisposable isn’t a class abstraction, but rather a functional abstraction.

I believe the confusing thing for developers is that abstraction isn’t just about some common defining properties, but also common functionality, and code is easier to use, when the two are abstracted separately. A fellow developer on Stack Exchange commented that generally speaking “interfaces are [named] adjectives and classes are nouns”. Well I propose a third option, that defining (class) abstracting interfaces drop the ‘I’ and functional abstractions keep the ‘I’, therefore functional abstractions are adjectives.

You can describe a Person (interface) has a first and last name, you can also describe them as IContactable where they have a Phone Number and Email address for instance. So in this example we have 4 properties, 2 are describe the person and 2 provide functionality for another service. Note too that the Person interface inherits the Phone Number and Email properties, so a PersonDto concrete class with have all 4 properties. A Business (interface) can also be IContactable. You can them pump all IContactable classes into a EmailService and send emails to individuals and businesses.

Tying back into your example, you could have a Person interface being IModifiable, that is it has a DateModified property, so your SqlPersonRepository concrete class can set the Person.DateModified using SQL’s GetDate() statement for instance. However it would make more sense to implement this in a SqlRepository abstract class that could update any IModifiable classes DateModified property for all SQL entities.

Happy to drop the ‘I’ on describing/class interface abstractions but I’m keeping it for the functional abstractions.

John Jacobs

I disagree with this. Technically, using IInterface could be considered Hungarian notation but who cares? Why be dogmatic? Another way to view it is that it’s a .NET-particular convention that has survived because of its utility and because it actually does provide value. Being able to distinguish between classes and interfaces in a source folder without relying on your IDE is invaluable (think browsing source code structure for a particular project on GitHub, etc). I don’t plan to abandon this convention any time soon.

ChadF

That notation has always annoyed me. Not only should it be redundant based on the name (i.e. a generic vs specific), but sometimes I have come across an interface where the “I” sounds like a valid part of the real name, which can be extremely confusing when reading at a glance… I can’t remember an actual name off hand, so I’ll go with IOAuth as an example (is that I/O auth? interface OAuth?). Even back when the world was moving from 16-bit to 32-bit APIs it could potentially hint at erroneous legacy value that were once a 16-bit int and later promoted to 32-bit (if ABI incompatibility wasn’t an issue), yet the variables still use the ‘w’ (word) prefix. It also made it harder, in general, to discourage implementation assumptions, e.g. this “id” argument is a record “identifier”… I shouldn’t care if it is an int (i.e. uId), a long (i.e. dwId), an object [pointer] (i,e, pId) or something else.

DalSoft

I like the post, and as we are discussing anti patterns Repositories are a terrible waste of an abstraction.

ChadF

This is similar to the convention of adding the “Exception” suffix to every exception in some languages. If someone is throwing/raising an object, I can safely assume it is an exception class (at least in languages which require inheriting the base exception/error/throwable type). I don’t really need a FileNotFoundException class when FileNotFound will do.

When I started working on a design for a new language and roughing out its core classes (including exceptions), I started doing the same thing out of habit. But then I asked myself why I was doing that, given I didn’t need to adhere to such conventions for backward compatibility or consistency with any existing language. So I removed the suffix in all but generic cases (e.g. Error, ArithmeticError, IOError - not to be confused with interface OError, of course).

gordysc

Loved the perspective and appreciate how dropping a single prefix “I” can translate to clarity on the implementing classes. Thanks for the post!

Dylan Nicholson

I don’t entirely disagree but given the reverse which I see in Java projects where every interface has a default implementation called {interface}Impl I know which one I prefer. But in fact recently I’ve been experimenting with not bothering with an interface at all in cases where the only reason I’ve used one is to make the code more testable - it’s enough just to have a class with a few public virtual functions that can easily be mocked. Also C# 8 supports default implementations for interfaces so that might be work well in many cases.

Dylan Nicholson

But what would be lost if it was just called ‘Disposable’? I wonder how realistic it would be to come up with an adjective for every case you’ve used an interface - certainly I’m struggling for most of the examples in my current project, yet I don’t believe I’ve misused the concept of an interface.

Dylan Nicholson

But in Java you can’t just create a List or Set. You just specify something about its implementation detail that’s likely irrelevant to you.