Today, we’ll talk about exposing the class’s implementation details in its name.

1. The question

This topic came up in a question about the CQRS pattern, but it’s equally applicable to other patterns as well. Here’s the gist of it:

Why does DatabaseRetryDecorator expose its structure and implementation details in the class name?

What if I change the class’s implementation and replace the decorator with something else? Will I have to rename it just because I changed its implementation?

And just for the context, decorators are classes that allow you to introduce cross-cutting concerns in your application layer.

Here’s a usage example for the database retry decorator:

[DatabaseRetry]
public class EditPersonalInfoCommandHandler :
    ICommandHandler<EditPersonalInfoCommand>
{
    public Result Handle(EditPersonalInfoCommand command)
    {
        /* Editing the customer's info */
    }
}

The DatabaseRetryAttribute above connects the command handler to the DatabaseRetryDecorator. If the command handler throws a database exception, the decorator re-runs that handler again.

The idea is similar to how middleware works in ASP.NET. Here’s the decorator itself:

public sealed class DatabaseRetryDecorator<TCommand> :
    ICommandHandler<TCommand>
    where TCommand : ICommand
{
    public Result Handle(TCommand command)
    {
        for (int i = 0; ; i++)
        {
            try
            {
                /* _handler is the underlying command handler */
                return _handler.Handle(command);
            }
            catch (Exception ex)
            {
                if (i >= 3 || !IsDatabaseException(ex))
                    throw;
            }
        }
    }
}

In any case, this is a great question and it ties back to the article I wrote awhile back: Ubiquitous Language and Naming.

Indeed, why should you call the class DatabaseRetryDecorator and not just DatabaseRetry?

The same argument can be applied to other classes as well, for example CustomerRepository, CustomerFactory, or even EditPersonalInfoCommandHandler for that matter.

Do they really need to specify the patterns they implement in their names (repository, factory, and command handler)?

2. Naming guidelines

There are 2 relevant guidelines here.

First, you should never use pattern names when naming classes in the domain layer.

[Enable Images]

In fact, you should only use terms from the Ubiquitous Language when naming domain classes.

So, it’s probably not MoneyGeneratingBipedalEntity, and not even CustomerEntity or CustomerAggregate. It’s just Customer.

Second, you can use pattern names when naming classes in the application layer.

That’s because the application layer is outside the reach of the Ubiquitous Language, and there’s simply no corresponding notion for its classes in that language.

Also, pattern names help you better understand the intent behind classes in the application layer, since those classes don’t have a direct connection to your domain model.

Note that you should follow the YAGNI principle at all times, even when naming application layer classes. This means that you should put the minimum amount of descriptors in class names.

The most common example of violating YAGNI is calling a repository CustomerSqlRepository.

Unless you use multiple storage paradigms, such as SQL and NoSQL, there’s no need to specify that your repository works on top of a SQL database.

--Vlad

https://enterprisecraftsmanship.com


Enjoy this message? Here are more things you might like:

Consulting and training — I offer consulting and group training for organizations on Unit Testing and Domain-Driven Design. Reply to this email with the word "consult" to discuss.

Unit Testing Principles, Patterns and Practices — A book for people who already have some experience with unit testing and want to bring their skills to the next level.
Learn more »

My Pluralsight courses — The topics include Unit Testing, Domain-Driven Design, and more.
Learn more »