Why Ubiquitous Language Belongs in Code, Not Just Meetings

The article shows how mismatched business and code vocabularies cause confusion, then guides readers through building a shared glossary, renaming domain objects and types in Java, and enforcing the conventions with a code‑review checklist to keep the ubiquitous language alive in the codebase.

Tinker Programmer
Tinker Programmer
Tinker Programmer
Why Ubiquitous Language Belongs in Code, Not Just Meetings

Ubiquitous Language lives in code, not in meeting minutes

During a requirement review the product manager said “formal employees get bonuses, contractors do not”, while the developer responded by adding type = 1 to a user query. Both sides talked about the same concept but used completely different vocabularies – business language versus database language – and the code never aligned them. This is exactly the problem Ubiquitous Language (UDL) in Domain‑Driven Design tries to solve.

Why naming is hard

Java developers often struggle with naming not because of poor English but because they haven’t clarified what a concept means in the business domain. In a payroll system, six different kinds of “people” (regular employee, contract worker, probationary employee, former employee, rehired retiree, intern) share the same sys_user table and are distinguished only by a type field, yet each has distinct salary rules.

Step 1 – Extract business terms into a glossary

Before writing code, create a Markdown or simple document that maps every business term to an exact code name and lists prohibited names. Sources are:

Requirement documents and PRDs – pull out recurring nouns.

Conversation records with the business side – focus on ambiguous terms.

Existing code – list all occurrences of User, type, status and confirm their business meaning.

Example excerpt of the glossary (converted from the original table):

Business term: 正式员工 → RegularEmployee (prohibited: User, Staff, Worker) – employees with a formal labor contract.

Business term: 外包人员 → ContractWorker (prohibited: OutsourceUser, Temp) – third‑party staff not counted in social insurance.

Business term: 薪资单 → PaySlip (prohibited: Salary, Wage, Pay) – monthly salary statement.

Business term: 绩效等级 → PerformanceLevel (prohibited: Level, Grade, Score) – quarterly/annual performance rating (A‑D).

… (other rows omitted for brevity)

Step 2 – Let the glossary drive the code

Before refactoring, the service class looks like this:

@Service
public class SalaryService {
    // Get employees for this month (formal + probation, exclude contractors)
    public List<User> getPayableUsers(YearMonth month) {
        return userDao.findByTypeIn(Arrays.asList(1, 2));
    }
    // Calculate salary (note: salary means gross amount)
    public BigDecimal calcSalary(Long userId, YearMonth month) {
        // ...
    }
}

All naming is vague, and comments are needed to explain business intent. After applying the glossary, the code becomes:

@Service
public class PayrollApplicationService {
    /**
     * Query employees payable this month
     * Includes: RegularEmployee, ProbationEmployee
     * Excludes: ContractWorker
     */
    public List<Payable> findPayableEmployeesFor(PayCycle cycle) {
        return regularEmployeeRepository.findOnDutyDuring(cycle.getRange())
                .stream()
                .map(Payable::from)
                .collect(Collectors.toList());
    }

    public GrossSalary calculateGrossSalaryFor(EmployeeId employeeId, PayCycle cycle) {
        // GrossSalary type already conveys “pre‑tax”
        RegularEmployee employee = regularEmployeeRepository.findById(employeeId)
                .orElseThrow(() -> new EmployeeNotFoundException(employeeId));
        return salaryCalculationDomainService.calculate(employee, cycle);
    }
}

Now the type system and naming carry the business meaning; no extra comments are required.

Step 3 – Guard the standard with code‑review checklists

To prevent drift, embed a checklist into the PR template. Example items:

New class or method names match the glossary and avoid prohibited terms?

Are synonyms mixed? Does salary and wage refer to the same concept?

Do interface parameters and return types convey meaning without looking at the implementation?

Do comments explain *why* something is done rather than *what*?

Is any “patch‑style” comment (e.g., “note: xxx means …”) present? If so, move the meaning into the name.

Does any class mix multiple domain concepts (e.g., Employee handling both personal info and salary config)?

Are database field names leaking into the domain layer (e.g., type = 1 in service code)?

Are new business terms added to the glossary?

This checklist is not meant to turn code review into a language class; it simply codifies the UDL agreement so every PR performs a lightweight scan for vocabulary drift.

Conclusion

Implementing Ubiquitous Language requires three concrete actions: build a shared glossary, rename domain objects and types according to that glossary, and enforce the convention with a review checklist. The next article will explore bounded contexts – how multiple “employee” concepts can be separated into distinct domains, which is the real basis for micro‑service decomposition.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaDomain-Driven Designcode reviewUbiquitous LanguageNamingGlossary
Tinker Programmer
Written by

Tinker Programmer

Solving problems with code, sharing practical tech insights, and leveling up together!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.