A vocabulary, not a dictionary you write once
The Ubiquitous Language is the precise, shared vocabulary used by both domain experts and developers within a given boundary. “Shared” means a customer-support rep, a warehouse manager, and the engineer writing Order.java all use the word Order to mean the exact same thing, with the exact same rules attached. “Precise” means the word isn’t a vague gesture — cancel, in the bookstore’s Sales context, has one agreed meaning: the order is voided before a shipment is created, inventory is released, and no charge occurs. A different operation — voiding after a shipment exists — is a different word (recall, say), because it has different rules and different consequences.
This precision is the whole point. A word that means three slightly different things to three different people isn’t language, it’s noise that happens to be spellable.
Building a glossary
The most practical way to recover (or design) a Ubiquitous Language is to build a glossary, one row per term, with three columns:
- Term — the domain word itself:
Order,place,OrderLine,cancel,OrderPlaced. - Kind — is it a thing (a noun, likely to become an Entity or Value Object later), an action (a verb, likely a method or a Domain Service operation), a state, or an event?
- Evidence — where does this term actually show up? A class name, a method signature, a field, an event type. No evidence, no entry — a glossary of words nobody actually uses in the code (or the business conversation) isn’t recovering anything.
Here’s a starting glossary for the bookstore’s Sales context, the area this course treats as the core domain:
| Term | Kind | Evidence |
|---|---|---|
Order |
Thing | Order class, OrderId field, Order.place(...) |
place |
Action | Order.place(customerId, lines) |
cancel |
Action | Order.cancel() — only valid before shipment |
OrderLine |
Thing | OrderLine value held inside Order |
OrderPlaced |
Event | Raised by Order.place(...), consumed by Billing and Shipping |
split shipment |
State / concept | Discussed by the business, not yet named in code — a gap worth flagging |
That last row matters as much as the others. A glossary isn’t just a list of classes you already have — it’s where you notice that “split shipment” is something the business talks about constantly but no class, method, or field currently represents. That gap is a signal, not an error in your glossary.
A term that recurs across many classes and drives behavior is load-bearing. A term that shows up once in a private helper method usually isn't part of the language at all.
Telling the language from the scaffolding
Real Java codebases are full of names that look like domain vocabulary but are actually technical scaffolding wrapped around one real concept. The classic giveaway is a single domain idea duplicated across every architectural layer:
class Order { /* the domain concept */ }
class OrderEntity { /* JPA row, same concept again */ }
class OrderDTO { /* wire format, same concept again */ }
class OrderService { /* orchestration, same concept again */ }
class OrderController { /* HTTP layer, same concept again */ }
class OrderRepository { /* persistence access, same concept again */ }
That’s not six domain concepts. That’s one domain concept — Order — wearing five different costumes for five different technical jobs. When you’re building a glossary, collapse these into the underlying term and note the layers as evidence, not as separate entries. The same goes for generic suffixes that signal “this name doesn’t carry domain meaning”: Manager, Util, Helper, Impl, and framework annotations. They’re plumbing labels, not vocabulary.
Tip. A fast test: would a warehouse manager or a customer-support rep ever say this word out loud while describing their job?
Order,cancel, andsplit shipmentpass.OrderServiceImpldoes not.
Why this is worth the discipline
It’s tempting to treat the glossary as paperwork — something you write once for a design doc and never open again. In practice it earns its keep two ways. First, it’s the fastest way to onboard someone: read the glossary, and you know what the system is about before you’ve opened a single file. Second, and more importantly, the glossary is a verification tool. If a new method doesn’t fit any term in it — and isn’t worth adding as a new term — that’s a sign the method doesn’t belong to this model at all, or that the model needs to grow on purpose rather than by accident.
That second use is exactly what the next three modules build on. A Ubiquitous Language only stays precise within a boundary — the word Customer can (and, in real systems, usually does) mean something different in Sales than it does in a marketing context. Module 3 starts dividing the bookstore’s domain into the areas where a single language can hold, starting with the broadest cut: subdomains.