Skip to main content

Ubiquitous Language for a Team of One

What This Concept Is

Ubiquitous language is the discipline of using the same terms in the same way across code, tests, diagrams, documentation, and conversations with the user. When you are solo, your "team" is you-now, you-in-week-four, and the grader. They must all read the same word and mean the same thing. When they don't, the capstone fragments: a feature called retroSession in one file, meeting in another, board in the database, and RetroRoom in a React component is the same feature four times, and nobody -- including you -- is certain which description is authoritative.

Operationally, ubiquitous language for a solo capstone is a short glossary -- 10 to 20 terms -- plus a rule: those terms appear literally, unchanged, in your database schema, your domain types, your API names, your diagrams, and your design doc. The glossary is per-bounded-context (concept 05) because the same physical object can legitimately have different names in different contexts.

The glossary is boring on purpose. Boring is the goal: a glossary entry you could forget on Tuesday and rediscover the same answer on Thursday without having to guess.

Why It Matters Here (In the Capstone)

Terminology drift is the cheapest way to make a capstone look unprofessional. The grader opens your code and cannot tell whether ScanEvent, Scan, Movement, and StockAdjustment are the same thing or four things. Neither, after six weeks, are you. The design doc contradicts the diagrams; the diagrams contradict the database; the API contradicts both. This is a catastrophe that costs about five minutes a day to prevent.

Solo-team language drift is worse than team drift, because there is nobody to call you on it. You invented three names at 11pm across three sessions and now your model is fragmented. The glossary is how you stop that, and rolling a grep-check into your Friday review (concept 13) is how you keep it stopped.

Finally, ubiquitous language is load-bearing for every downstream artifact. The C4 diagrams (concept 11) must label boxes with glossary terms. The ADRs (concept 12) must use glossary terms in the context section. The scope-cut rules (concept 14) must name features with glossary terms so the strikethrough in week 4 is unambiguous. The defense (concept 15) must speak the glossary aloud. One drifted term fails the chain.

Concrete Example(s) -- from a real capstone

Example A -- inventory service glossary entries:

ScanEvent (n.): an immutable record of one staff scan. Fields: scanId, sku, qtyDelta, actorId, capturedAt, syncedAt, idempotencyKey, kind in {receive, pick, adjust}. In code: ScanEvent. In DB: scan_event (table). In API: POST /scan-events. In diagrams: "ScanEvent."

Explicitly not called: movement, transaction, adjustment, stock change.

OnHand (n.): the current derived quantity of one SKU at one location. Computed from the scan_event log; never directly mutated. In code: OnHand. In API: GET /skus/{sku}/on-hand.

Explicitly not called: stock, inventory count, quantity, balance.

Example B -- ticketing platform glossary:

Event (n.): one ticketed occasion -- one date, one venue, one organizer. Fields: eventId, title, startsAt, venueName, status in {draft, published, cancelled}. In code: Event. In DB: event. In API: /events/{eventId}.

Explicitly not called: show, gig, concert, session, meeting.

SeatTier (n.): one priced pool of seats within one event with a cap. Fields: seatTierId, eventId, name, capTotal, capAvailable, priceCents. In code: SeatTier. In DB: seat_tier.

Explicitly not called: ticket type, category, class, section.

Ticket (n.): one issued entitlement to one seat tier for one buyer, bound to a QR payload. In code: Ticket. In DB: ticket.

Explicitly not called: pass, seat, admission.

Example C -- finance aggregator glossary:

RawRow (n.): a single line from an uploaded CSV as originally parsed, before dedupe or categorization. Fields: rawRowId, sourceFileId, rowIndex, rawPayload, contentHash. In code: RawRow. In DB: raw_row.

Transaction (n.): a deduped, categorized monetary event. Fields: transactionId, accountId, occurredAt, amountCents, memo, categoryId, sourceRowIds (array). In code: Transaction. In DB: transaction. In API: GET /transactions.

Explicitly not called: tx, entry, line, record, charge.

CategoryRule (n.): one YAML-declared matcher mapping a memo/amount pattern to a category, with a priority integer. In code: CategoryRule. In YAML: rules: entries.

Explicitly not called: tag rule, classifier, filter.

Boring, specific, with explicit "not called" lists. The explicit synonyms list is where most of the value lives: it gives you something to grep for in week 4.

Common Confusion / Misconceptions

  • "It's just naming conventions." Conventions are "use camelCase." Ubiquitous language is "the word for this thing in code, tests, diagrams, and the design doc is the same word." Convention is stylistic; ubiquitous language is semantic.
  • "I do not need a glossary for a 6-week capstone." Every capstone that ends with "what did I call this thing?" search-and-replace in week 5 is a capstone that would have been shorter with a glossary in week 1. The glossary is 5 minutes a day.
  • "Only domain objects need it." Cross-cutting terms matter too. What do you call "the thing that merges offline scans when Wi-Fi returns"? If it is "reconciler" in code and "merger" in the design doc, you have drift.
  • "Cleanup pass at the end." The cleanup pass never happens at capstone scale -- it is always lower priority than a working feature. Day-1 vocabulary is cheaper than week-5 renaming.
  • "One glossary per project." Ubiquitous language is per bounded context, not per project. If you have two contexts (e.g., "live scanning" and "reporting"), a term can legitimately mean different things in each. For a solo capstone you usually have one context, so the glossary is flat -- but name the single context in the design doc so the single-vocabulary assumption is visible.

Where Language Has to Match Literally

For the glossary term to be "ubiquitous," it must appear identically (modulo casing and plurality) in at least these five places:

  1. Domain types in code: class ScanEvent, type Ticket.
  2. Database schema: table scan_event, column scan_event_id.
  3. API paths and field names: POST /scan-events, JSON field scanId.
  4. Diagrams: a box labeled "ScanEvent" on the C4 Component diagram.
  5. The design doc and ADRs: every prose reference says "scan event," never "movement" or "stock adjustment."

A simple test: grep for your glossary terms across src/, library/raw/, and db/migrations/. Every term should appear in all three. Grep for the forbidden synonyms. They should appear zero times.

How To Use It (In Your Capstone)

  1. Start the glossary on day 1, empty. Put it at the top of library/raw/glossary.md and cross-link from the design doc.
  2. Seed from the EventStorm. Every recurring past-tense verb ("scan") and its object noun ("ScanEvent") is a glossary candidate.
  3. Every time you invent a new word, add an entry. Include: the term, a one-sentence definition, where it appears (code type, DB, URL, diagram), and what it is not called.
  4. When you see a synonym emerging, pick one. Rename the losing synonym everywhere; don't "leave the old one for compatibility" -- this is a solo capstone, there is no compat.
  5. Do a Friday glossary pass. Open the glossary, grep the codebase for forbidden synonyms, rename.
  6. Verify every new API path and DB migration uses glossary terms literally. This is the cheapest drift prevention.
  7. If a term no longer appears anywhere, delete it. Dead terms create confusion too.

See also (integrative)

Ubiquitous language is the capstone's concentrated use of DDD's shared-vocabulary discipline, and it is the thread that keeps API design and data modeling from diverging.

External references (curation-validated this session):

Check Yourself

  1. Name one synonym you have already accidentally introduced in your capstone. What is the right term?
  2. What does "ubiquitous" add beyond "consistent naming"?
  3. Where, besides code, does the glossary term need to appear to be ubiquitous?
  4. Grep your repo for one of your "explicitly not called" forbidden synonyms. If you find hits, you have drifted. When will you rename?
  5. Is your glossary scoped to a single bounded context, and is that context named explicitly in the design doc?

Mini Drill or Application (Capstone-scoped)

  • Drill 1 (15 min). Open your capstone code (even a skeleton) and list every noun that refers to a domain concept. Collapse synonyms. Pick winners. Write two-line glossary entries.
  • Drill 2 (10 min). For each entry, add the "explicitly not called" list. These are the grep targets.
  • Drill 3 (10 min). Grep the repo for every forbidden synonym. Rename today. Commit.
  • Drill 4 (5 min, Friday ritual). Rerun the grep every Friday. New drift is normal; un-reverted drift is the problem.
  • Drill 5 (15 min, once). Rewrite the design doc's Domain Model section using only glossary terms. If a sentence cannot be written in glossary, either add to the glossary or drop the sentence.

Source Backbone

Capstone design applies earlier architecture and domain material. These books are the source backbone for the decisions in this module.