Ubiquitous Language in your software domain

Defining your software domain’s language makes everything easier

Christopher Laine
Jun 12 · 6 min read

(First off, I’d like to thank Rafał Lewandowski for his recent post on SwingDev, which inspired me to talk about Ubiquitous Language)

Jobs, and Items, and Actions, Oh My!

I spent some time the other day trawling through documentation on a platform I help support. I bumped into this idea of a “Job”. A Job in this software represents work which someone needs to move to completion. The Job has associated with it the items and actions which need to be completed for the Job to be considered “Done”. The items need to be ordered or removed, and the actions need to be in specific states for the Job to be “Done”.

The Job arrives in our system via an external source, and the user begins interacting with the Job, ordering items and completing actions. Good so far?

Yeah, I thought so too. I have seen the users of this platform, and seen what they do. This is how these terms came about.

However, while reading the documentation (as created by our devs, testers, and support staff), I found that the terms Job, Item and Action were used interchangeably.

Example 1: “When a user sends their Job out for ordering…”

Example 2: “When the Job is actioned, it is now considered done…”

Example 3: “You can either send out the Job, or click the action button to complete those first…”

Now, this was only three examples of failed documentation. There were plenty more.

In reviewing the code, while a bit better, the concepts of Job, Actions and Items were pretty muddy. I struggled in reading the code to work out how what our users are doing was being modeled in the code.

When I questioned people about this, they all came back with their own terminology of the process. The words Job, Actions, and Items were all used interchangeably. Verbs were used on each of those nouns to represent behaviour, but none of it actually approached the reality of what was actually happening, nor what was actually being modeled.

I am sure this is a familiar enough scenario for you to be sighing and shaking your head. This is all too common in software / product development.

The people involved in the product come up with terms which represent the objects and actions in your software, but the terms are as well-defined as a 12th century map of the universe.

Ubiquitous Language to the Rescue

A Ubiquitous Language is a concept from Domain-Driven Design. If you’re unfamiliar, here is Martin Fowler’s definition

Ubiquitous Language is the term Eric Evans uses in Domain Driven Design for the practice of building up a common, rigorous language between developers and users. This language should be based on the Domain Model used in the software — hence the need for it to be rigorous, since software doesn’t cope well with ambiguity.

In essence, your Ubiquitous Language is the heart of your software model. The Ubiquitous Language defines the types of entities, actions, and behaviours your user can understand, and thus the way you should model your software.

This might seem arbitrary, as often devs imagine that what their code is doing is a layer abstracted from what the users want. As in

public class Job
{
public IEnumerable<Action> Actions { get; }
public IEnumerable<Item> Items { get; }
public JobState State { get; }
}
public class Item
{
//…
}
public class Action
{
//…
}
public enum JobStatus
{
Open,
InProgress,
ItemsOrdered,
ActionsCompleted,
Done
}

Sure, the user doesn’t know what an IEnumerable is, nor what the hell an enum is about, but even with these abstractions, we see the fundamentals of the Job, the Items and the Actions. We see the status through which the Job might flow. We are seeing something approaching what the user understands.

We can reach these kinds of clean implementation (not to mention clean documentation) by sitting down before we begin our development and formulating our Ubiquitous Language. Our Ubiquitous Language comprises all the concepts of which our domain is made. The nouns, verbs, states, behaviours, interactions. All of it should be there in plain language for anyone to read and understand.

This Ubiquitous Language comes about as part of a series of discussions with our users who are describing to us what their process looks like, how the Job looks, how Items are ordered, how Actions are progressed.

During this process, your team will ask questions, find holes or vagaries in what the user is telling you, so you can fill in all the blank spaces. It also gives the users a chance to talk it out, to see where they have missing knowledge, where their understanding isn’t as robust as they might think at first.

This process will create a Ubiquitous Language, a dictionary of terms and concepts which are agreed upon by the users, the devs, and the testers.

How does this really help?

One of my favourite expressions about junior devs is “Oh, they were trying to code their way out of the problem”. In essence, juniors will often just sit down and write code without really stepping back to look at the definitions of what they are trying to create. The underlying fallacy is that with enough code, the problem will sort itself out. I think any intermediate dev and above knows this is never the case.

More code just leads to more complexity, and if you don’t understand your domain, more confusion.

A Ubiquitous Language will ensure that before anyone starts with the typey-typey, everyone understands the ins and outs of the process / domain they are out to create. It means that your team understands what is afoot with the users. It means your users are well informed about what you’re building for them, through the process described above, as well as through documentation created from your Ubiquitous Language. It means your testers are better equipped to come up with test cases for all scenarios, because the language they are dealing with is clearly defined.

Technical implementation aside, you now have a map which shows all the paths through, not just the imaginary or misunderstood ones you’ve created in your head.

Things to look out for

From my experience with this process, I’ll give a few pointers

  1. Start broad and come back to details later In your first pass at a Ubiquitous Language, don’t delve too deeply into every detail. This helps you avoid burnout in the process, and means you can get the big picture down early.
  2. Double-back until you have filled it all in It is seductive to just fill in ‘part of the map’ and leave concepts as incomplete or undefined. Avoid this temptation. Keep going over your users’ domain until your Ubiquitous Language is as complete as your first cut of the software is going to be. This leads me to
  3. Don’t bite off more than you can chew If you intend to build your software in several phases, then just focus on the deeply-detailed aspects of the Ubiquitous Language which are needed for your first phase. By getting the broad strokes as I mentioned above, you get a good idea of what is coming in later phases of the project, so you can cater for them at a high level, but without you gold-plating every bit of the Ubiquitous Language before any work can be done. Your Ubiquitous Language, like your software, is an evolving beast.
  4. Don’t forget the verbs and states Often, devs get the nouns pretty well nailed, but then fail on the verbs (the actions which can be performed) and the states (the various statuses of your noun). For example, this Job I mentioned above has a state called ‘Finished’. The user never used that word in any conversation I heard. The term they used was ‘Done’, and thus the Job status should match this. Do the same with method naming: Keep it as close to the Ubiquitous Language as possible. While you might think it doesn’t matter, it really does. In fact, you’ll find your code is a lot easier to read when written as defined by the Ubiquitous Language. Derivation from the Language, and now you’re in trouble.
  5. Talk the talk No matter what, your team must use the Ubiquitous Language in all discussions, all documentation, all test cases, everywhere. If you aren’t using the correct nomenclature in your day-to-day talks, how do you expect anyone else to do so?

Conclusion

If you’ve not followed this process before, I say you give it a try on your next body of work. Even if your system is not a DDD system, this process of creating a Ubiquitous Language really does help as a means of gathering requirements.

Hope this helps

IT Dead Inside

IT is a cesspool, but its home

Christopher Laine

Written by

Writer, sci fi / Lovecraftian nutbag, "master' chef, gym rat, martial artist, Dungeon Master, and programmer. I cover all the useless bases

IT Dead Inside

IT is a cesspool, but its home

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade