Real-world DDD

Ubiquitous Language

Domain-driven design (DDD) is not a new subject (Eric Evans formalized the concept over a decade ago). However, it is curious how, until today, the basic concepts on the subject arouse interest, especially in .NET communities. Even stranger is how these same concepts are misinterpreted.

The foundation of DDD lies in the concept of the ubiquitous language. It is not in determining what an entity, value object, aggregate, service, or repository is.

The impression we get is that anyone who starts studying DDD reads the first few pages of the Evans book or the Vernon book and quickly jump straight to the pages that describe the patterns.

We often talk to IT people who think that having a defined ubiquitous language means that the name of classes and properties, written by programmers, conforms to the vocabulary of domain experts. However, this is a gross simplification.

To understand the importance of ubiquitous language, let’s start with the “entity” listed below:

public class Employee
{
  public string Id { get; set; }
  public string Name { get; set; }
  public string Cpf { get; set; }
  public decimal Salary { get; set; }
}

Here is an excellent example of anemic implementation! But before you read on, try to figure out why.

In our daily work, when we use this example, we hear suggestions that this class lacks behaviors (Which is right!). However, when we ask what such “behaviors” would be, we find that people are repeating generic arguments (from people who have not “gotten” the idea either) and cannot identify what is wrong!

One of the most frequent arguments is that property setters should be private. In their place, we should have “DefineXXX” methods that would implement validations. This idea makes no sense because the purpose of setters is precisely to set values for the properties, and there would be no problem to implement validating logic in them.

An entity’s methods should spell out the motivations for its state changes. Also, there must be at least one constructor capable of instantiating the entity from the beginning, in a valid state.

It is not uncommon to find class implementations with properties that check, for example, whether the value you are trying to set is non-null, even when these same properties have null as default value. What is the logic here?

See another example of an anemic class:

public class Customer 
{
  public string Name { get; private set; }

  public string Email { get; private set; }

  public DateTime BirthDate { get; private set; }

  public Customer(Guid id, string name, string email, DateTime birthDate) 
  {
    Id = id;
    Name = name;
    Email = email;
    BirthDate = birthDate;
  } 
}

In the class above, we have a typical “record” for a functional implementation. But in an object-oriented language, this is not an entity.

The idea would even make sense in a purely functional language where the “entity” is conceptually spread out in various functions that define behavior, but in C#, it makes no sense at all.

Let’s try a second version for the Employee class:

public class Employee
{
  public string Id { get; private set; }
  public string Name { get; private set; }
  public string Cpf { get; private set; }
  public decimal Salary { get; private set; }

  public Employee(string name, string cpf) 
  {
   //..
  }

  public void RaiseSalary(decimal amount)
  {
    //..
  }
}

This time the entity is less anemic. After all, the motivations that drive property value change are evident. Notice how even the value of test writing becomes more explicit.

Anyway, we still have problems. We named the method “RaiseSalary,” however, this is not the way domain experts describe this operation. The only way to define actual reasons for changing property values is by talking with these experts.

To think about…

Identifying and implementing the ubiquitous language is not just for defining class names or properties. The ubiquitous language must be revealed mainly in the motivations for the state changes of our entities explicitly.

Understanding ubiquitous language is much more important than learning the standards. Without real knowledge of the domain, the value of design patterns is null.

Worry first about learning the most important. Take the time and effort to understand the domain well and spell out its ubiquitous language. Then it may even make sense to think of associating DDD with more advanced technical concepts.

More posts in Real-world DDD series

1 Comment
  1. David

    Interesting, for me when answering why it’s anemic I thought on the fact that all of the properties are not value objects, that’s one thing that helps me with maintaining the ubiquitous language. Salary is not conceptually an int. So having a Value object that represents the salary than even raise salary gets more interesting.

Leave a Reply

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