Idiomatic C# and the “I” Prefix

In a prior blog post (https://jakejgordon.wordpress.com/2014/08/24/to-blog-or-to-code/) I mentioned a for-fun side project I’ve been working on. I also mentioned that I’d share some lessons learned in a subsequent blog posts… so here we are!

I planned on rolling up a number of lessons learned in one post but realized it would be too long. Plus I like Bertrand Le Roy’s idea of applying the Single Responsibility Principle to blog posts so let’s hone in on one specific topic:

Using the “I” Prefix for Interface Names in .NET

In “Clean Code” by Uncle Bob Martin, he recommends not using the “I” prefix for interface names. He contends that if you cannot come up with a descriptive enough implementation name then an “Impl” (for implementation) suffix is still better than an “I” prefix (i.e. ThingDoerImpl is better than IThingDoer). While the book is written primarily from a Java perspective, I thought I’d try it out on a .NET project knowing that this was very much contrary to a long-standing C# convention. After about 5 months of developing without the “I” prefix, below are my takeaways on the good and the bad.

Reasons to Drop The “I” Prefix

Better Implementation Names – Not having the “I” prefix helped force me to come up with better names for my implementations. For example, instead of just having IThingDoer (interface) and ThingDoer (implementation), I would instead try to go with something like ThingDoer (interface) and ThingDoerThatDoesItACertainWay (implementation). If I was really not feeling inspired I would default to ThingDoer and ThingDoerImpl (implementation). While this isn’t great, it at least allowed me to not to have to add the “I” prefix.

Related Files Grouped Together – With the “I” prefix, your interface and implementation are usually not grouped together in Visual Studio’s Solution Explorer. In your IDE you end up with something like the below (alphabetical ordering):
AppleSlicer
BananaSmasher
GraperSquisher
IAppleSlicer
IBananaSmasher
IGrapeSquisher
ILemonSqueezer
LemonSqueezer

At least if you don’t have the “I” prefix you’ll have the slightly more convenient:
AppleSlicer
AppleSlicerImpl
BananaSmasher
BananaSmasherImpl
GrapeSquisher
GrapheSquisherImpl
LemonSqueezer
LemonSqueezerImpl

Reasons To Use the “I” Prefix

Visual Studio Solution Explorer Doesn’t Distinguish Between Classes and Interfaces by Default – While the Class View in Visual Studio clearly calls out interfaces vs. implementations, the Solution Explorer does not — presumably because you can have both classes and implementations in a single .cs file (although I prefer to never do this). This means that a clear naming convention (i.e. the “I” prefix) is the only easy way to tell if a file represents a class or an interface.

Unable To Distinguish Between Implementing Interface and Extending a Base Class – In C# the colon (“:”) is used to denote both implementing interfaces as well as extending base classes. In Java you have the “extends” and “implements” keywords to help distinguish between classes as interfaces when you are defining your inheritence. For example, in java you could have:

public class SomeClass extends SomeBaseClass implements SomeInterface

In C# you would just have:
public class SomeClass : SomeBaseClass, SomeInterface

Without a clear naming convention to call out the base class vs. the interface you might not be able to easily tell which is which. Take for example:public class SomeClass : LemonSlicer, ApplePeeler

Are these interfaces or classes? Or is LemonSlicer a base class and ApplePeeler is an interface?

Long Standing Convention – As much as I don’t like to give this as a reason, one cannot overlook the fact that the “I” prefix is a convention that all C# developers understand and expect. While I was getting pretty comfortable without the “I” prefix in my own code (with which I was obviously very familiar), other developers were confused and frustrated when trying to work with the code. Given that I’d actually like other people to help me with my project this is pretty much the deal-breaker.

Conclusion

Dropping the “I” prefix wasn’t nearly as painful as I thought it would be. It forced me to pick better names for my implementations and I found the grouping of files to be more convenient in the Visual Studio Solution Explorer. However, the simple fact that developers expect the “I” prefix is probably a good enough reason to keep with the status quo — which I’ll be doing from here on out.

What do you think?

Advertisements

3 comments

  1. I’ve gone back and forth on this myself and I’ve come to the conclusion of keeping the I prefix. However, I like to make sure that it reads like a sentence so indicate its intent.

    ISqueezeApples
    ISmashBananas
    IGetConfigurationInfo
    IHashStrings
    IScrapGooglesHomePage

    Then I try to come up with names really based on what they’re doing akin to the “ThingDoerThatDoesItACertainWay”.

    SqueezeApplesByHand : ISqueezeApples
    SmashBananasWithPestile : ISmashBananas

    An interface was made to be able to swap things in. Often enough I’ll be swapping it in for something else.

    GetConfigurationFromAppConfig : IGetConfigurationInfo
    GetConfigurationFromDatabase : IGetConfigurationInfo

    HashStringsWithWinRT : IHashStrings
    HashStringsWithiOS : IHashStrings

    If there really isn’t an obvious name, I even prefer sticking “Default” on front instead of Impl. I think it still reads clearer.

    DefaultGoogleScraper : IScrapGooglesHomePage

    • Interesting idea. How have other developers felt about your breaking the rule of thumb of nouns for classes and nouns or adjectives for interfaces? i.e. IHashStrings vs. IStringHasher? I have to admin IHashStrings reads a lot better.

      I like the idea of a Default prefix. I’ll probably give that one a shot to see how it works.

      • I’ve gotten reactions on both sides. Some like it because it just reads like English. Some people think it’s silly.

        I’ve really only have done this in my personal code projects. I don’t usually do something like that to existing [large] codebases. It’s better to be consistent than start having a dual personality with something as trivial as naming things a particular way.

        I get the idea of “default” from other libraries. MVC has the “DefaultModelBinder” and NancyFX has the “DefaultBootstrapper”.It may however become just as smelly as “Impl” but for now it remains fresh to me.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s