Interface Naming Conventions

At an earlier crossing on my development journey, many moons ago, it was considered best practice to use the “Hungarian Notation” for variables. You basically prefixed every variable name with a code denoting the data type that variable contained. This resulted in variable names like strName (a string) or u32Number (a 32-bit unsigned integer).

The reason why this was considered best practice was that you were dealing with low-level languages that were pretty literal when given commands by the developer. So, if you had a 32-bit variable, 32 bits of memory were reserved to contain the contents of that variable. If you copied the contents of a different 64-bit variable into that first one, the language would just allow you to do that… writing 32 bits of information into your variable and the remaining 32 bits into whatever happened to be stored immediately behind that allocated spot in the memory. You can be sure that that often resulted in very random bugs, being anything from spectacular to completely undetected until shipped. Take a look at the list of Types of Memory Errors for a nice catalog of memory abuse options.

So, with these languages, it was pretty much necessary to be aware of the exact technical implementations of what you were dealing with, to avoid greater harm. Clean, semantic code was of low priority if it made your computer explode in regular intervals.

Rise Of The Garbage (Collector)

Nowadays, most people will agree that the benefit of doing so is gone, as we have runtime checks, garbage collectors, and whatnot. That’s why Hungarian Notation is pretty much gone from modern OOP development. You will generally hear that you should code against interfaces, and not against implementations. Your code should not need to know implementation details, as that just causes unwanted coupling.

In a dynamically typed language like PHP, you are even encouraged to just ignore the type and let the PHP runtime figure it out (with varying degrees of success). So, surprisingly, trying to paint three dozen eggs with the following code will just work:

for( $egg = 1; $egg <= "12 eggs" * "3 dozen"; $egg ++) {
   echo "Painting egg number ${egg}", PHP_EOL;
}

As you can see, PHP is very “flexible” with its typing system, so there’s no point in distinguishing between a 32-bit and a 64-bit unsigned integer anymore.

Code Against Interfaces, Not Implementations

One of the most important principles in software development (and one that takes years to properly assimilate) is to always “code against interfaces, not implementations“, with interfaces not referring to the PHP interface language construct, but rather to the concept of “abstract API that is agnostic of any specific implementation details”.

The point of this is to decouple every part of your code from the other parts of the code, as well as from any specific, short-lived implementation. For example, if your business logic is expressed entirely in terms of how it interacts with such interfaces, you can replace some or all of your infrastructural implementations without needing to change that business logic.

When you start really applying this principle consistently, you’ll end up expressing most higher-level logic in terms of how it manipulates the underlying interfaces, and you only ever have interfaces be injected as dependencies.

The logical conclusion should be that this conceptual “interface” then is the most important building block for you to communicate your intent to the system.

PSR-2 Suffix To The Rescue…?

A lot of developers have trouble thinking in terms of interfaces and APIs. The mind has a natural tendency of thinking procedurally, and you’ll need some time to get good at thinking at the object-oriented level.

That’s why folks often end up with a number of classes that are just whatever useful first implementation they could come up with.

When the PHP-FIG introduced the PSR-2 – Coding Style Guide, they included a bylaw (which is actually not part of PSR-2) that stated that all interfaces (and this time we’re talking about the actual PHP language construct) should be suffixed with the word Interface for all code that the PHP-FIG would release. This is why we have a Psr\Log\LoggerInterface instead of a Psr\Log\Logger.

This has lead many developers that were still struggling to entirely grasp the OOP paradigm to take a shortcut in their development “proficiency” and let most classes they create implement an interface of the same name, suffixed by the word Interface. This way, you can “code against an interface” without needing to think about the design of your code. Neat!

What’s In A Name?

Naming a thing is a very important process. It forces you to think hard about the actual nature of the thing you want to find a name for. Also, the name brings with it an entire set of assumptions and expectations. If I name a class IconRenderer, you will probably know not to use that one to make a connection to an FTP server, even without looking up its functionality in the documentation. Similarly, if I name a class Class153A , you have no clue what that could possibly do.

Naming is an important process that forces you to think about the very nature of things. Click To Tweet

So, the following way of naming classes and interfaces also carries a lot of semantic information:

class Thing implements ThingInterface { };

Because of the way the brain makes assumptions about the logical relation of these two based on the specificity of the words, this tells me loud and clear: “Thing is what we’re after, that ThingInterface is only there to support it.” – And that’s where we messed with our brain!

To properly follow the above-mentioned principle and general best practices, we need to make it obvious for our brain that the interface is what counts, and the actual implementation is just some noisy detail that could easily change from one week to the other:

class CurrentThing implements Thing { };

So, please take the time to let both of these snippets sink in and consider what their “appearance” suggests. You will probably agree that the perceived importance switches positions from one example to the next.

Hungarian Class Notation

I see this as a variation of the Hungarian Notation described above. It encodes a technical implementation detail of a given entity into the domain language that we should want to have as clean and clear as possible. And, yes, the word Interface is an implementation detail, as paradox as that may sound.

To make this consistent, you would also need to have names like ThingClass or $thingVariable. It provides us with information that might be accurate, but not relevant for the consuming code.

Consider the following code:

<?php namespace Example;

use Example\Message;

class MessageRenderer {

   /**
    * @var Message
    */ property $message;

   /**
    * Initialize a Renderer instance.
    *
    * @param Message $message The message we want to render.
    */
   public function __construct( Message $message ) {
      $this->message = $message;
   }

   /**
    * Render the message.
    */
   public function render() {
      echo $this->message->toString();
   }
}

Is Message a class?

Is Message an interface?

Should we even care?

Yeah, About Naming Being Hard…

I would argue that we should get rid of that Interface suffix and use the most meaningful name for the interface, not the class. But, what will the class be named then?

If we name our interface Thing, we need a more qualified name that provides additional information about our specific implementation for the class that implements Thing. Something like GenericThing or DefaultThing does not fit that requirement. Furthermore, it might mean that we will have a situation later on where we need to provide an alternative implementation. Our DefaultThing  might end up not actually being the “default thing”.

Think About Your Design!

You will probably encounter three different situations:

  1. Your current code needs multiple implementations of a same concept.
  2. Your current code provides one implementation of a concept, but is meant to be extended by more specialized third-party code.
  3. Your current code only needs a single implementation, and there’s currently no point in extending it.

Multiple Implementations Of A Same Concept

The first one makes it pretty obvious of how to define the naming. The interface is named after the concept and the actual implementations should be named after what makes it even necessary to have different implementations in the first place. So, as an example, if you need an EmailList that can work with different mailing list service providers, like MailChimp and AWeber, the names of the classes should reflect that distinction:

interface EmailList { };

class MailChimpEmailList implements EmailList { };

class AWeberEmailList implements EmailList { };

One Implementation Open To Extensions

The second situation is less obvious. But generally, the naming should reflect the way you intend the extensions/replacements to happen.

If the one implementation you provide is useful on its own, you should still name it like you did for the first scenario.

If the implementation is only meant as a starting point so that the extensions don’t need to start from scratch, you can call it something like BaseThing and should make it an abstract class.

If the implementation is just provided so that the code does not throw errors, but does not do anything useful at all, you should name it after the NullObject pattern: NullThing.

Single Implementation, No Extension Planned

This is the most interesting scenario. Most developers will agree that one of the most difficult things to deal with in software development is to correctly anticipate future requirements. In this regard, “not planning to allow extensions” does not necessarily mean that this won’t ever happen or be necessary in the future.

One of the most difficult things for a developer is to anticipate future requirements. Click To Tweet

If you’re going with the PHP-FIG suffix, you’ll have a ThingInterface and code that relies upon that interface. Because, introducing a ThingInterface later on while all your code is programmed against a Thing would mean major refactoring. This is probably the reason why it is considered a “brainless trend” right now to just provide an interface for everything.

Comic about a man wanting to change his name.

However, that’s where my naming recommendation provides a very nice perk: If your naming does not reflect the difference between interfaces and classes, your code doesn’t need to care!

Think about it for a second!

If you don’t plan for your code to be extensible, just go ahead and provide a simple class Thing {};. As that is not extended, the only places where you’ll encounter it is in type-hints and doc-blocks.

And after six months, your client might need to have two different things: one that runs from the database, and one that runs from the filesystem. That’s where the beauty of thoughtful naming comes in… As Thing still is the actual concept you’re dealing with, you can just turn the class Thing into an interface without breaking any existing code. And all of your existing code will happily accept that new DatabaseThing implements Thing, even though you never planned for that scenario!

Conclusion

As a developer, I spend most of my time interacting with the interfaces (in the API sense) that other parts of my code provide. Naming is a hugely important factor to consider and directly influences how effective my work is and how much I enjoy it.

The names of your objects should directly stem from your domain language and provide a clean representation of it. This will result in code that often is as readable as a normal English prose. The times where we need to add cryptic symbols and abbreviations or encode technical details into our entity names are long gone, and we should be glad about that!

I would love to hear your thoughts about this! How do you go about naming your interfaces? Let me know in the comments!

4 Comments

  1. Guido on October 22, 2016 at 1:54 pm

    Hi,

    I’ve a question about namespaces.

    I made a project where I create interfaces and abstracts that are within own properly directories.
    For example:

    namespace ProjectName\Component\Interfaces;
    // These are under src/Component/Interfaces/

    namespace ProjectName\Component\Abstracts;
    // These are under src/Component/Abstracts/

    When I need to an interface and or an abstract class I simply use “use” keyword and my classe looks like:

    // src/Component/Abstracts/
    abstract class MySingularClassName implements Interfaces\MyPluralClassName { };

    // src/Component
    class SpecificClassName extends Abstracts\MySingularClassName { };

    In practice I have:

    interface IconSets { };

    abstract class IconSet implements Interfaces\IconSets { };

    class Fontawesome extends IconSet { };

    It is considered a bad practice to put interfaces and abstracts into a separate directories?Report

    • Alain Schlesser on October 22, 2016 at 5:02 pm

      Hi Guido,

      Thanks for joining the discussion!

      Although I know there are projects that have special folders for contracts, I would personally recommend against doing that, for the following reasons:

      1. If the scope of the code you’re splitting up is very large, you’ll end up having two large collections of files mirroring each other, one for the interfaces, and one for the implementations (or maybe even three, if you split off the abstracts like you do above). This forces you to constantly move around when working on this component in an erratic way, because your code flow will be spread across two (or three) different regions due to the inheritance chain.
      2. If the scope of the code you’re splitting up is very small, you’ll end up having lots of folders with a very small amount of files in each. These folders don’t provide additional structure, they are just an inconvenience.

      3. If part of the namespace is needed to distinguish files, this can cause all sorts of confusion. In places where you only see the class name (like in a class diagram), it is difficult to follow the structure.

      The beginning of your namespace denotes a logical grouping that is based on the scope, like packages and sub-packages. Interfaces or abstract classes don’t fit into that taxonomy, as they are a different type of grouping, based on the actual language structure that is used.

      I recommend only using one coherent way of grouping within your namespace. For example, I would have `Vendor\Package\Component\<interface|abstract class|class|trait>. In this way, everything that makes up that component is in one logical place. If you happen to have interfaces that are shared across components, pull them up one level.

      Having all types of language structures at one level at least makes them appear equal in importance. Putting the interfaces into a deeper subfolder makes them appear to be less than the actual implementation, which is one of the issues I’m talking about in my article. The interface is the most important one, and at best, it should be the only one a “consumer” of your code should care about.

      For some of my libraries, I have pulled the interfaces into the main namespace, with subfolders containing the different implementations for each interface.

      Also, I would recommend against using the plural form for interfaces. I guess you reason about this in a way like “Thing is a part of Things“, but this is very misleading. If you typehint against Things, for example, most developers will assume this is either an array, a collection or a repository (something that contains multiple “Things”). I strongly recommend using the form of the name that reflects whether it “accepts” a single or multiple elements.

      In my code, the plural forms are collections or repositories. When I type-hint against these, I know they can manipulate multiple elements and have ways of retrieving a specific one. Also, I know that when I retrieve a single element from these, it will normally be typed as the singular form.

      Cheers,
      AlainReport

  2. Guido on October 23, 2016 at 10:25 pm

    Hi Alain,

    Thank you so much for your reply, really appreciated.
    I’ll follow your advice.Report

  3. Alex on April 3, 2017 at 4:11 pm

    Brilliant!Report

Leave a Comment