Skip to content

10 · Patterns in the model

When you finish this lesson you should be able to:

  • Steal a named analysis pattern (account, posting, interest) instead of inventing a worse local dialect
  • Use Strategy as Policy and Composite when the model is a tree of meaning
  • Reject Flyweight-as-habit for values
  • Say “this pattern is in the ubiquitous language” or not use it

Deep models are expensive. Sometimes an experienced person looks at a domain and sees a familiar shape. Fowler-style analysis patterns (and the domain’s own literature) are knowledge to draw on, not homework to implement in full.

Evans’s banking-shaped examples: accounts, interest, postings, nightly batch. The insight is not “always use Account.” It is:

  • The nightly batch was not “just a job.” It was a temporal concept in the domain (when value is recognized).
  • Interest was not a stored number; it was a rule with a duration.
  • Once those names exist, the batch and the online path stop being two programs that happen to write the same table.

Your analog: a “nightly send” of emails is often an implicit DeliveryWindow or Digest, not a cron. A “ledger” of experiment exposures might be an Entry you should not overwrite. A “balance” of remaining messages in a quota is an account-like pattern whether or not you are a bank.

How to use this as a strong engineer:

  1. Hear a job, report, or batch.
  2. Ask: is this a concept with a name in this industry?
  3. Try that name with experts. If they light up, you found prior art. If they stare, do not force Fowler into a chat app.

Design patterns are not a badge. They belong when they express the model.

When experts talk about interchangeable rules—“retry policy,” “holdout policy,” “quiet hours policy”—the model is a Strategy. The word in the language is Policy.

const quietHoursPolicy = { allows: (ctx, at) => quietHoursAllows(ctx.quietHours, at) };
const alwaysAllow = { allows: () => true };

The application picks a policy; the domain does not switch(type) across the whole codebase.

When the domain is truly a tree of the same kind of meaning (a route made of legs, a spec that is AND/OR of specs, a notification rule that is nested groups), Composite is the model. Nested ifs that happen to look like a tree in one function are not yet Composite—you have not named the node.

Sharing a single object instance to save memory is an implementation trick. Values are already small and immutable. Do not introduce identity and caches to “Flyweight” QuietHours. You will accidentally create entities.

  • Implement a pattern because a blog said DDD + Strategy + CQRS + Event Sourcing.
  • Name a class CompositeSpecificationAbstractFactory when experts say “eligible.”
  • Copy Evans’s interest-accrual example into a product that has no interest.
  1. Find one batch, cron, or report. Propose an analysis-pattern-shaped name. Test it in a sentence with a fake expert.
  2. Find one switch(type) on behavior. Extract a Policy object. Name it in product words.
  3. Find a nested boolean. Either it is a Specification Composite, or it is two concepts. Pick.
  4. Write one sentence: “We are not using Flyweight because…”
  • Domain-Driven Design — Chapter 11, Applying Analysis Patterns
  • Domain-Driven Design — Chapter 12, Relating Design Patterns to the Model