The context
People working in software development share a variety of idiosyncrasies about whatever they do when they are coding: they have very - very - strong opinions and habits about code formatting, naming convention, codebase organizations… and they love to “fight” about them.
It is often a question of development platform and community: for example, Java and C# are very similar languages (each one adding every day features inspired by other’s features…) but Java and C# code tends to be formatted in a slightly different way with regard to placement of braces.
Although I know people who make a war of religion out of braces’ placement, I’m convinced it’s only a matter of aesthetics - so you can imho format your code as you prefer: as long as you are consistent throughout the entire codebase, your choice is the right choice.
The issue
On the other hand, there is a community-related convention habit - or better, a set of similar community-related conventions habits - regarding interfaces naming I really dislike: people living and working in .Net echosystem, Microsoft’s follower, grown on bread and C#, tends to name interfaces starting with I
: IPeopleRepository
, IAuthenticationProvider
, IThis
and IThat
.
It’s just another convention, you can say, as harmless as widespread: as long as you are consistent throughout the entire codebase, you can do as you prefer.
I totally disagree with the last sentence above: I think calling interfaces by I
is not (only) a convention (sure it is!), but is a design error, too.
Some might say: But .Net standard library adopts and promotes this convention. So what? Is it fair because everyone does it? Is it fair because Microsoft does it? I think an error in an error, no matter how many people - nor who - do it. But let me clarify why I think this is a very poor choice of design (naming is design, isn’t it?).
Violating DRY
Code like
1 | public interface IPeopleRepository { |
violates DRY - Don’t Repeat Yourself - principle: indeed, if you change your code moving this architecture component from interface
to class
, you have two things to change: the language keyword and the typename (so you must change type name throughout all its usages, too).
Violating SRP
Code like
1 | public interface IPeopleRepository { |
violates SRS - Single Responsibility Principle: indeed, the type name ha two reasons to change: you need to change it if you change its semantic (say you prefer renaming to [I]PersonRepository
) and you need to change it if you want move from interface
to class
.
Poor modelling
1 | public class List : IList { |
is perhaps the most poor and inadequate naming choice I’ve ever seen in my almost twenty years of experience as a programmer; it communicates never about differences between interface and implementation:
- what is the peculiarity of
List
as an implementation ofIList
? - are there other implementation of
IList
in the .Net standard library? In what are they different fromList
?
The Java way of naming things here is undoubtedly better and full of information: the name of the interface, List
, describes the role in the code of objects refereed by a List
reference; ArrayList
, LinkedList
, and so on describes what’s the implementation flavour the specific class is based on (e.g. giving programmers information about time- and memory-related behaviour of instances).
I think this is the way we should name things in our code: I like name interfaces trying to describe the abstract role played by runtime instances and classes trying to describe what are concrete implementation choices adopted: e.g. I prefer SqlServerPeopleRepository : PeopleRepository
over PeopleRepository : IPeopleRepository
, HttpWeatherForecastGateway : WeatherForecastGateway
over WeatherForecastGateway : IWeatherForecastGateway
, and so on.
Breaking uniformity
So far I discussesed reasons why you shouldn’t name interfaces prefixing them with I
from a design-related point of view.
But conventions are only conventions (I disagree about this specific habit, as I said above, but let’s face it), even when they seem like design errors, and whatever convention you adopt, you should adopt it evenly throughout your codebase: uniformity is a widely accepted best practice, when it comes to formatting convention, naming convention, code organization, …
So: you name interfaces starting with I
and classes starting with C
, isn’t it? And enumerations (wait: you don’t use enum in C#, do you?) starting with E
.
And you name variables starting with prefixes remarking their type: s
for string
s, i
for int
s, d
for double
s…
1 | public class CMyClass : IMyInterface { |
Are you naming things this way? No? Only interfaces starting with I
? Ok, you’re breaking uniformity, adopting a partial convention (and partial conventions aren’t conventions at all).
Conclusion
So: if you think design principles are an important and useful driving force when you’re writing code; if you think names should communicate something to the reader, and differences in names should communicate differences between things, allowing the reader to be able to easily understand moving parts of your code; if you think uniformity is a good quality of a codebase, even when it comes do adopting conventions… you should not use I
as a mandatory, common prefix for interface names.
Bonus track
The same considerations apply for sure to other similar naming convention: many (Java) frameworks suggest you to name your interfaces and implementations with MyService
and MyServiceImpl
; many people are used to name AbstractSomething
their implementation of [I]Something
interface; others like to call asynchronous methods ending with Async
- and so on.
Whenever you include a syntactical detail (I
for interfaces, C
or Impl
for classes, Abstract
for abstract things) in a name you’re facing a variant of the discussed problem: you’re violating DRY (repeating che syntactical detail both in syntax and name), you’re violating SRP (giving at least two responsibilities to the name), you’re likely to adopt an incoherent naming convention, you’re modelling your domain the wrong way.