Ubiquitous Language and Naming

In this post, I’d like to talk about naming and Ubiquitous Language.

Ubiquitous Language and naming

There are only two hard things in Computer Science: cache invalidation and naming things.

 — Phil Karlton

Naming is hard. Anyone who ever tried to give some vague concept in code a clear, meaningful name knows that. It is even harder when you consider how important it is. This realization can add up some pressure which doesn’t always help when trying to choose a good name.

Domain-Driven Design explicitly emphasizes the importance of naming things properly with the notion of Ubiquitous Language. If you work in the domain of, say, furniture e-commerce, you probably shouldn’t name a table as WoodenFurnitureItem. Table would be a more concise and specific option.

Why? Because of translation overhead. If you need to constantly translate notions in your code base to the language of the business and back, you waste precious mental cycles. This additional translation layer taxes everything. Discussing a feature with the business people, and even just thinking about a problem - all this becomes harder as you need to put additional effort to go back and forth between the code and the language of domain.

Weasel words

Probably the most common example of violating this guideline is the use of weasel words. Programmers love them. All these "Info", "Base", "Item", "Manager" comprise a common vocabulary from which people choose words to name concepts in their codebases.

Have you ever seen a domain class named UserInfo? If you ask the author about the reasoning behind this name, the answer would be clear-cut: it contains information about a user. But does this "Info" suffix bring any additional value? Not at all. It’s a distraction, a weasel word you can safely get rid of. User is a much cleaner option.

I struggle with it myself as much as anyone else. It’s hard to come up with a precise and short name. And it’s too easy to just pick one from the commonly available vocabulary every programmer knows and loves. Need a name for that thing the business uses to assemble tables? Here you go: FurnitureItemProcessor.

It’s not only "Item" and "Manager" that belong to the set of weasel words, though. It’s also such things as "Repository", "Dto", and "Service". They don’t carry any business meaning either. How often do you hear a business person saying something like:

"We need to take a closer look at table repositories. I’m sure they will help us increase sales in the upcoming quarter."

No one said that, ever. Repositories, as well as other DDD patterns, are not part of the Ubiquitous Language.

However, unlike "UserInfo" which we can easily rename to "User", it’s not as certain what to do with "UserRepository" or "UserDto". The name "User" is already taken by the domain class itself. How should we name the corresponding repository then?

Two types of code

Here’s where it gets tricky. Not all code should be treated equally from the naming perspective. And not all weasel words introduce communication overhead.

You need to divide classes in your codebase into two groups:

  • Those that have a meaning for business.

  • Those that don’t have a meaning for business.

The first category is where you need to make sure you have no weasel words whatsoever. These classes directly translate into notions from the domain, they constitute the Ubiquitous Language. Any unnecessary or excessive words here would result in communication overhead because chances are, business people don’t use those words when speaking about the problem domain.

Classes that reflect notions your business cares about comprise the Core Domain. They usually include Entities, Value Objects, Domain Events, and (some) Domain Services.

Note, however, that some weasel words can actually have a meaning for the business. If that is the case, you can keep them. For example, this class:

public class FurnitureEntity : Entity { /* ... */ }

is not named properly. No business person calls a piece of furniture "FurnitureEntity". You can safely get rid of the suffix here:

public class Furniture : Entity { /* ... */ }

But this one:

public class CustomerRegisteredEvent : IDomainEvent { /* ... */ }

might be meaningful to business. When there’s a new customer registering within the system, it’s an event, and business people might as well use this terminology.

In all other cases, however, don’t pollute your Core Domain. It’s not UserAggregate. There’s no such thing as aggregate in the real world. Keep it simple: User. And it’s not MoneyValueObject either. Whether or not a concept is a value object should be understood from studying the domain. Or looking from which base class this type inherits (if you use base classes for entities and value objects).

The second category consists of classes that don’t have a business meaning. They are repositories, most domain services, application services, etc.

With such classes, you don’t have to get rid of all weasel words. It might simply be impossible due to the fact that there’s no corresponding notion in the Ubiquitous Language. It will not entail any communication overhead either because business people don’t talk about such things.

Here’s how we can diagram the two:

Ubiquitous Language and Core Domain
Figure 1. Ubiquitous Language and Core Domain

You can keep UserRepository and UserService as is if they are outside the reach of the Ubiquitous Language. And you need to take extra care of classes that do have a meaning for business analysts, product owners, and other non-programmers.

Note that even if the class doesn’t belong to the Core Domain, it doesn’t mean you can go astray with naming. Try to follow YAGNI regardless. Don’t name that thing BaseItemProcessManager just yet, try to think of something shorter.

Another example I often encounter is BaseController (or ControllerBase). Get rid of the "Base" part, use Controller instead. And one more: UserSQLRepository. The fact that the repository uses a SQL database as an underlying storage is an implementation detail. No need to manifest it in the class name.

Summary

  • There are two types of classes in your codebase:

    • Those that have a meaning for business.

    • Those that don’t have a meaning for business.

  • The classes from the first category comprise the Core Domain and Ubiquitous Language.

  • Get rid of weasel words altogether when naming classes from the Core Domain.

  • You can use weasel words if the class’s name doesn’t belong to the Ubiquitous Language.

    • Even in this case, try to follow YAGNI and keep the name short.

Subscribe


I don't post everything on my blog. Don't miss smaller tips and updates. Sign up to my mailing list below.

Comments


comments powered by Disqus