Naming Things – Part 3

Naming conventions and naming things in Java. Stylized picture of a typical business ID card.

For the last few posts, we’ve looked at naming things. (If you missed them, here are the links to Part 1 and Part 2.) In this post we’re going to look at class and interface naming.

We’ve seen that naming things is very important. It forces us to think hard about what the item is and does. A good name suggests the item’s functionality. The name also brings with it a whole set of assumptions and expectations.

Good names can show that similar things are connected, and that dissimilar things are separate. Sometimes the quality of a name isn’t obvious until we try and name something similar. If the original name is good, we can easily derive a name for the new, similar thing. A name is good if it survives its future usage.

The longer an item is in scope (i.e. used and visible), the more important it is to have a good name for that item. Classes and interfaces are the building blocks for our design, and are used more widely and are in scope for longer than variables of those types.

Class Names

Generally, we’ll get a good “gut” feeling about an appropriate class name. It should be specific enough to focus our thoughts (Single Responsibility principle), but general enough to allow easy extension and specialisation (Open-Closed principle).

The names we chose for classes should be concise, informative, and easy to remember. They should be meaningful in the context of the problem. Names should be easy to pronounce. They shouldn’t consist of abbreviations or contain digits (if possible).

Type names for classes should indicate the functionality of the class without us needing to read the documentation or work through the source code. Good names can show patterns in the code.

If there is a class in a library called ImageRenderer, it’s very obvious that we wouldn’t use that class to make a connection to an HTTP server. We wouldn’t even have to look it up in the documentation. Conversely, if we came across a class called Class153A, we wouldn’t have a clue what it could possibly be used for.

Class names are generally nouns or noun phrases, such as Employee, Account, Invoice or ArrayList. This distinguishes type names from methods, which are named with verb phrases.

Interface names are sometimes also nouns or noun phrases such as Collection, Map and List, but are more often adjectives or adjective phrases, e.g., Cloneable, Serializable and Runnable.

We should beware of class names that are verbs or derived from verbs. This often shows that we’re using the class in place of a method of a yet-undiscovered class.

We should choose a convention for class names and stick to it. This gives internal code consistency. Many programming languages use the convention of camel case naming.

Code To An Interface, Not An Implementation

One of the most important principles in OO development is to code to an interface, not an implementation.

This is the concept of an abstract API that is independent of any specific implementation. This helps decouple (separate) our code from other parts of the code base.

If we express our business logic entirely in terms of how the code works with interfaces, we can substitute any concrete class implementation with any other concrete implementation of the same interface without changing any business logic. This is the Liskov Substitution principle at work. This means that we will only ever have interfaces injected as dependencies.

This then leads to interfaces being the most important building blocks for us to communicate our intent to the system, and on which to model our classes.

If we look at the following code, what do we know about Message? Is it an interface? Is it a class? Does it matter? Should we even care?

public void process(Message message) {
    // appropriate code
}

If our naming conventions don’t distinguish between interfaces and classes, our code doesn’t need to care!

We should be programming in terms of interfaces anyway, so name the interfaces as the base concept. In the above example, we’d code Message as an interface. After that, we would create concrete classes implementing the Message interface. These would have names such as BytesMessage, StreamMessage, TextMessage, etc.

It’s best to stick to these constructs even though the classes won’t group nicely when sorted alphabetically.

The Do’s and Don’t’s of Prefixes

Delphi had the coding convention of prefixing all class names with a “T” to show that it was a type definition. TObject was the base class of all objects and components. The same idea was applied to interfaces too. The “I” prefix was used. IInterface was the base class for all interfaces. C## uses the “I” prefix for interfaces as well.

I don’t like and won’t recommend the use of these prefixes. Class names should be clean without any clutter. The concrete implementation should tell us why it is special.

For example, a name like User is much easier to read and remember than IUser or TUser. The concept of a User should be coded as an interface. If we have a concrete implementation of a User, the name of that implementation should tell us what is special about it. Is it a user whose data is stored on a server? Call it ServerUser. Do we store the user data locally? Call it LocalUser.

Another example: if we have a concept of a notification in our system, we should create an interface called Notification which specifies its behaviour. We can then create concrete implementation classes as needed. These could be called SmsNotification, EmailNotification, PopUpNotification, etc. These class names tell us what the differences are, and give an indication of where and how we will use them.

While on personal preferences, I do like prefixing abstract classes with Abstract. Using the Abstract prefix makes it clear to the programmer that this is an abstract class with data fields and reusable implemented code. Abstract classes make good base classes for extension. The standard Java library has AbstractCollection, AbstractList, AbstractMap, etc. Spring uses the prefix extensively as well.

Conclusion

Remember that there are no hard and fast rules that will miraculously make the job of naming things simple. But by keeping the previous conventions, hints and ideas in mind when we have to think of good names will definitely make our programming life a lot easier.

Decide on a standard, be consistent and stick with it. We’ll never get universal agreement on how to name things, so we shouldn’t lose too much sleep about it.

Code is literature, so we must make it as humanly readable as possible!

I look forward to reading your comments.

Until then, stay safe and write good literary code!

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.