← All categories

Modern & Enterprise

Patterns from everyday business applications: values, repositories, retries and events.

Business software has its own recurring problems: money and dates passed around as raw numbers and strings, SQL mixed into business rules, half-saved records after a failure, and services that keep calling a dependency that is clearly down.

The patterns here give those ideas a proper home: small immutable value types, repositories that speak in domain terms, a unit of work that saves everything or nothing, and policies for retries and circuit breaking.

You'll recognise it when

  • Amounts are doubles, and rounding bugs appear in invoices.
  • The same validation of an email or phone number is copied around.
  • Services build query objects or SQL strings themselves.
  • Optional collaborators are guarded by null checks everywhere.

Example

A travel app adds up trip distances. Some partners send kilometres, others miles.

Before
double total = 0;
for (Leg leg : trip.legs()) {
    total += leg.distance();          // km? miles? nobody knows
}
if (total > 500) offerRestStop();
After
record Distance(long metres) {
    static Distance km(double km)       { return new Distance(Math.round(km * 1000)); }
    static Distance miles(double miles) { return new Distance(Math.round(miles * 1609.344)); }
    Distance plus(Distance other)       { return new Distance(metres + other.metres); }
    boolean isLongerThan(Distance d)    { return metres > d.metres; }
}

Distance total = trip.legs().stream().map(Leg::distance).reduce(new Distance(0), Distance::plus);
if (total.isLongerThan(Distance.km(500))) offerRestStop();

Why it's better: The unit is decided once, when a distance is created. Adding kilometres to miles by accident becomes impossible, and the comparison reads like the rule it implements.

Ideas you'll practise

Value ObjectRepositoryUnit of WorkSpecificationNull ObjectDependency InjectionEvent BusRetry and Circuit BreakerRich domain model

Problems 16