Agent Wranglers

ARC-74Recommended

Give each bounded context its own model and words

Split the code into bounded contexts, such as billing, catalogue and shipping. Each context has its own module, its own types and its own glossary, and other contexts use only its public entry point.

How to do it

One shared Customer type for billing, support and shipping grows a field for every team and breaks all of them on each change. In billing a customer has a VAT number and a payment method. In shipping it has an address. Let each context hold its own type, named with the words its business people use, and link them by ID. Write each context's terms in a short glossary file next to its code. This builds on Group code by feature and Keep internals private.

Examples

JavaScript example

// .dependency-cruiser.cjs
module.exports = {
  forbidden: [{
    name: 'contexts-use-public-entry-only',
    severity: 'error',
    from: { path: '^src/contexts/([^/]+)/' },
    to: { path: '^src/contexts/([^/]+)/(?!index\\.ts$)', pathNot: '^src/contexts/$1/' },
  }],
};

Java example

@ArchTest
static final ArchRule shippingUsesBillingApiOnly = noClasses()
    .that().resideInAPackage("com.example.shipping..")
    .should().dependOnClassesThat().resideInAPackage("com.example.billing.internal..");

How to check

An import rule, such as dependency-cruiser, import-linter or ArchUnit, fails the build when one context imports another context's internal files. Each context folder holds a glossary file.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/architecture/domain-model/bounded-contexts">Agent Wranglers clean code and architecture playbook</a>. In code you write, add a comment next to it with the same link.