No Sacred Cows: I, Interface

sam_ferree

Sam Ferree

Posted on February 16, 2022

No Sacred Cows: I, Interface

The Argument

Why should we prefix the names of interfaces with I in C#? Here is the full answer given from Microsoft's documentation on C# coding standards. To save you the click, I'll post it here.

When naming an interface, use pascal casing in addition to prefixing the name with an I. This clearly indicates to consumers that it's an interface.

So we need to prefix the name of the type with I so that consumers of the type know that it's an interface. Seems simple and straightforward, but already this rule fails the consistency test. I could not find any suggestions that we preface class names with C and structs with S and records with R in order to indicate these things to consumers.

So the question then is, Why do consumers need to know they are using an interface, and why do consumers not need to know they are using a struct, class, or record?

Do Consumers need to know they are using an interface?

As far as I can tell you will encounter an interface in one of exactly three places:

  1. You are defining the interface
  2. You are implementing the interface
  3. You are working with a variable that is of an interface type

Let's examine, in each of these three scenarios, how helpful it is to know that you are working with an interface, and how valuable that information is.

Defining an interface

public interface Entity
{
  string Id { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Is it clear when defining this type, that it's an interface? Hopefully the word interface preceding the type name is sufficient to communicate that information to us.

Implementing an interface

public class Book : Entity
{
}
Enter fullscreen mode Exit fullscreen mode

Is it clear when implementing the Entity type that it is an interface? Not Just by looking at it. In fact, we won't notice anything at all until we've run the compiler. Once we've run the compiler we will be informed that we've failed to correctly implement the interface.

But how soon after we type this code is a compilation or language service run? In many IDEs very shortly. The editors that I'm familiar with will not only alert me that I need to do something, they will provide a macro or tool tip to do it quickly (ctrl+. in visual studio).

In fact, whether or not Entity is an interface, or an abstract base class my process is the same. Wait for the red squiggles to appear and then using the auto-complete features to stub out the abstract members I need to implement.

So in this way, In the case that your editor settings don't provide color indicators for the information, You don't actually need to know whether or not you've implemented an interface or extended an abstract base class. The compiler knows there are things you have to add to your type definition.

"But Wait!" you say, "What about multiple inheritance?"

Ah yes, well any given type in C# can have any number of interfaces, but only one base type. Without the I how will we know which one is the base type and which one is the interface?

The answer is again, the compiler. If you're using a modern editor you will likely know very quickly if you've extended multiple base classes, whether by color coding, or language features running error checking as you type. In this case, I don't need an I in front of my interface name any more than I need an A in front of abstract class names.

Working with a variable of an interface type

What if you get a variable back from a function, and the type is Entity and you aren't sure whether that type is an interface or a concrete type?

Even if you are not using an editor that can quickly communicate that information, I would argue that it makes no difference. You don't care if that type is an interface. You care what that type tells you about what methods are on it, and what methods it can be passed into as a parameter. That information is not only quickly available to you in most modern editors, but it's also impossible to determine any of it by whether or not there is an I at the beginning of it's name.

Following the convention

Okay, so maybe it's actually not that helpful, but is there any value in following the convention? There very well could be, but that's not the whole question. The question is: "at what cost?"

If Naming things is hard, Why make it harder? We either end up adding I's to everything or you have long descriptive names using I to describe what an object can do, i.e. ISaveBooks

Sometimes it's common to use the I to distinguish The interface from The implementation. These types often come in pairs: IBookRepository, BookRepository. The idea here being that we can code against the interface, not the concrete type. There are many good reasons to do this, and nearly all of them go away if our interface has only one implementation. In such a case, the ceremony is all noise and no signal. The interface defines what the type can do, but the name of the implementation doesn't communicate anything to us. What would be useful to see is a descriptive name of how, such as SqlBookRepository, or InMemoryBookRepository. In this, far more clear, example we no longer need to preface our interface with I. The interface is BookRepository and we have two implementations, one that reads and writes books from a SQL database, and one that keeps them in memory. For this problem, I much more likely to do something like this:

public interface BookWriter
{
  Task Save(Book book)
}

public interface BookReader
{
  Task<Book> Load(string bookId)
}

public class SqlBookRepository : BookWriter, BookReader { ... }
public class InMemoryBookRepository : BookWriter, BookReader { ... }
Enter fullscreen mode Exit fullscreen mode

Aside from the clarity, I no longer need to force a service which only reads books to be bound to the functionality around saving them. If I have any other functionality I might want to insert using decorators, like publishing an event every time a book is created or updated, I can do so without needing to write an empty pass through on the read part of the repository.

For me, I've not found any argument to prefix my interface names with I any more compelling than the idea that I should prefix my class names with C. It's an old convention, a relic of Hungarian notation, something which even other parts of the recommended C# coding conventions have gone away from.

Find this article and more on my substack

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
sam_ferree
Sam Ferree

Posted on February 16, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About