How to build a ubiquitous language

Insight

  • Domain modelling
1-1

The language you use in the code and the artefacts should be the same language that you agree upon with the business

The language you use in the code should be the language you agree with the business

A ubiquitous language is a shared, deliberately designed vocabulary that developers and domain experts use everywhere: in conversations, diagrams, documentation, tests and the code itself. Each term has one precise meaning within a bounded context, and it reads the same way on the whiteboard as it does in a class name.

“On a project without a common language, developers have to translate for domain experts. Domain experts translate between developers and still other domain experts. Developers even translate for each other. Translation muddles model concepts, which leads to destructive refactoring of code.”

Eric Evans

Author of Domain-Driven Design: Tackling Complexity in the Heart of Software

In any team or department, a shared social language that works for them will evolve. This language is very organic and always in motion. It’s messy and often ambiguous, with words shifting meaning over time. The team will use different words for the same thing, or the same word for slightly different things. All this is very normal; that’s how natural language works, and our brains are very good at dealing with this ambiguity.

But the language needs to be precise and unambiguous when we get to system design. The nature of software tells us whether our language is wrong or not. A misspelling or a forgotten comma will break the build. A concept that means two things to two people will break something far more expensive, and much later.

In Domain-Driven Design we say that the language you use in the code and the artefacts should be the same language that you agree upon with the business. Instead of choosing the domain language, which is too messy and evolving, or the language of the developers, which can be too esoteric, we use an agreed-upon language to talk in unambiguous terms. It has been deliberately designed, based on the domain, between the engineering and business stakeholders.

It takes deliberate effort from the team to find the right words. The very act of naming is often an overlooked part of software design. When we persist with using new names in diagrams, conversations and code, we iron out ambiguity and misunderstandings. That gives us a better model and, by extension, a more coherent and performant system.

What vocabulary should be agreed upon?

Not every word the business uses needs to be in the ubiquitous language. Eric Evans, who coined the term in Domain-Driven Design, says it should name the core elements of the model and the system you’re building:

  • Classes, types and prominent operations

  • Terms to discuss rules that have been made explicit in the model

  • Terms from high-level organising principles imposed on the model

  • Names of patterns the team commonly applies to the model

In practice, a good test is this: if the word will show up in the code, in a test name, or in a decision the business makes about the system, it belongs in the language. If it’s incidental (“the big screen”, “Monday's report”), it can stay informal.

Pay special attention to verbs. Teams tend to agree on nouns (Order, Customer, Policy) and leave the behaviour vague. But “cancel”, “void”, “refund” and “reverse” are four different business operations with four different consequences. Naming them explicitly is where much of the modelling value lives.

Ubiquitous language and bounded contexts

A ubiquitous language is invariably never company-wide. It is tightly coupled to a single bounded context, so the same word can legitimately mean different things in different parts of the system.

Trying to force one definition of “Product” or “Customer” across the whole organisation is a common mistake we see. It produces bloated models that try to serve everyone and ends up serving no one well.

The work is to make the boundaries explicit, so a team knows which language it is speaking, and to translate deliberately where contexts meet. We’ve written more about how those boundaries relate in Bounded Context Maps: Upstream vs Downstream.

How to build a ubiquitous language, step by step

A ubiquitous language emerges during collaborative domain modelling. You can’t model without some agreement on language; otherwise you just have a drawing and words without meaning. But there's a big gap between something evolving and a deliberate language. Here is how we approach it:

1. Get the right people in the room

The language is designed jointly, so the key stakeholders need to be present: the people who build the software and the people who know the domain. If developers are guessing at meaning, they’re building a language for themselves.

2. Surface the language that already exists

Start by listening, not defining. Collaborative modelling techniques like EventStorming, Domain Storytelling and Example Mapping are built for this: they get people describing what actually happens in the business, in their own words. Capture every term you hear, including the messy ones. Write them on stickies, on the board, wherever the team can see them.

3. Seek ambiguity

Now look at what you’ve collected and surface the misunderstandings. There are three patterns to watch for:

  • One word, several meanings. “Account” means a login to IT, a customer to sales and a ledger to finance.

  • Several words, one meaning. Half the team says “client”, the other half “customer”, and nobody knows whether there’s a difference.

  • Vague verbs. “Process the order” hides five distinct steps, each with its own rules.

Every one of these becomes a question. Ask “what’s the difference?” until the answer is either “none” (pick one word) or a real distinction (name both).

4. Define terms in relation to the model

When you define something, define it in relation to other things in the domain. Take an e-commerce platform. If an “Order” consists of a list of “Products” and “Quantities”, that’s a model, because it describes a relationship between Order and Product. But you also need to understand what a Product is to define an Order. The language is always defined in terms of the model, and the relationships between terms describe the model. That’s why language and model can’t be built separately.

5. Write it down where the team works

Record the agreed terms in a glossary per bounded context. Keep it close to the code: a Markdown file in the repository is usually better than a wiki page nobody opens. A diagram sometimes explains a concept better than a definition does, so include those too.

6. Put it in the code

The language isn’t real until it’s in the code. Rename classes, methods, events and test cases to match the agreed terms.

7. Use it out loud

Use the agreed words in stand-ups, tickets, documentation and conversations with stakeholders. It can feel pedantic at first to say “we call that a reservation, not a booking”. Do it anyway. People adjust faster than you expect, and the payoff is that everyone means the same thing.

Working with Aardling helped our organisation understand our domain, (re)design our bounded contexts and, especially, align the language across departments, which was my primary goal.

Engineering Manager at CarOnSale

How formal should this language be?

The formality of the language depends on your context. If you’re a fast-moving startup, formal might mean a quick discussion during domain discovery to agree on key terms. If you are in a life-critical domain like medical devices, formal might mean following a strict RFC process. If you are tasked with writing the next version of the HTTP specification, formal is something that will be considered the one way to do things for the next 100+ years.

Formality is contextual, but the ubiquitous language is always more formal than the everyday language people in the domain use.

Keeping the language alive

A ubiquitous language is ever evolving. As the business changes and your understanding deepens, the language should change with it, and the code, models, documentation and tests should co-evolve.

The danger is that language drifts: the business starts saying “subscription” where it used to say “membership”, nobody updates the code, and two years later you have a translation layer nobody planned. A few habits prevent this:

  • Review names like you review logic. In pull requests, ask whether new classes, methods and events use the agreed terms. A misleading name is a defect.

  • Rename when the model changes. Renaming is cheap with modern tooling. Living with a wrong name is expensive, because every new team member learns the wrong concept.

  • Treat confusion as a signal. When a conversation stalls because people mean different things, stop and resolve it. Then update the glossary and the code.

  • Revisit after big changes. A new product line, a merger or a regulatory change usually brings new language with it. Run a short modelling session rather than letting the new terms leak in unchecked.

Naming isn’t a one-off task at the start of a project, it’s ongoing design work that you need to keep on top of.

How do you know it’s working?

  • Domain experts can follow a walkthrough of the code, or at least its test names, without translation.

  • New developers learn the business by reading the codebase.

  • Requirements conversations get shorter, because people stop clarifying what they mean.

  • Bugs caused by misunderstanding (“we thought cancelled meant refunded”) become rare.

When the ubiquitous language is used well, a non-technical domain expert could read the code and understand what it does. But even without going that far, a shared language makes communication about the software much smoother, and the resulting software is much more closely aligned with what the business needs.

Asked what advice they’d pass on to other teams, one client put it in a single line: "Start small and build a ubiquitous language"

Struggling to align business and engineering on language? We help teams run collaborative modelling sessions and turn the results into models and code that hold up.

Frequently asked questions

What is a ubiquitous language in DDD?

It’s a shared vocabulary, agreed between developers and domain experts, that is used consistently in conversation, documentation and code within a bounded context. The term comes from Eric Evans’ 2003 book Domain-Driven Design.

What’s the difference between a ubiquitous language and a glossary?

A glossary is a single place to record the language. The ubiquitous language itself lives in how the team speaks and how the code is written. A glossary that doesn’t match the code is documentation, not a ubiquitous language.

Should the whole company share one ubiquitous language?

No. Each bounded context has its own. The same word can mean different things in different contexts, and that’s fine as long as the boundaries are explicit and translation between contexts is deliberate.

When should you start building a ubiquitous language?

As early as possible, ideally during the first domain discovery or modelling sessions. Clarifying language early defuses misunderstandings between engineering and business before they turn into code.

Can you introduce a ubiquitous language into an existing legacy system?

Yes, though it takes more care. Start with the part of the system you’re actively changing, agree the language for that context with the domain experts, and refactor names as you touch the code. An anti-corruption layer can protect the new language from the legacy model.

Who owns the ubiquitous language?

The whole team, jointly. Neither developers nor domain experts get to dictate it. Developers bring precision, and domain experts bring meaning.