Decode your feedbackDecode: layering, boundaries, and naming
No narration yet
Module 12 · Lesson 314 min

Decode: layering, boundaries, and naming

Three of Rai's reviewers pushed the same underlying idea from different angles: logic belongs to the layer that owns it, and decisions get made at the boundary. This lesson decodes all three, because they're one principle.

The comment (Nisha Nambissan, PR #491, on a frontend retry):

"the pattern of retrying on the browser side looks like an antipattern. This should not have been a frontend concern in the first place. We have surfaced it backwards and made it a client concern, when it should have stayed in the backend and been addressed there."

And (Nick Ferrell, PR #355, on a nullable date threaded downstream):

"Why allow null at all? Doesn't it just use the current date anywhere? I would think about making this explicit upstream rather than buried downstream."

And (Nick, same PR, on the query store):

"nit: the querystore should NOT be making this business decision."

What they meant. A resilience concern (retrying a flaky dependency) is owned by the backend, which makes the call; pushing it to the browser inverts the layering and, worse, stacks client retries onto a cold-start timeout. A business default (what "no date" means) is owned by the boundary, the endpoint; defaulting it with ?? today deep in the query store buries a product decision in the persistence layer, where it's invisible and untestable. Both are the same rule: push each decision to the layer that owns it, and make it explicit at the edge.

Decide at the boundary (Rai's resolution of Nick's note)
// What Nick flagged: a nullable date threaded down, defaulted deep inside.
public Task<FlightsView> Execute(DateOnly? day) { var d = day ?? Today; /* ... */ }

// The fix: the endpoint resolves the default; Execute takes a non-null DateOnly.
public Task<FlightsView> Execute(DateOnly day, CancellationToken ct) { /* ... */ }
// endpoint: useCase.Execute(day ?? DateOnly.FromDateTime(clock.UtcNow), ct)

And the boundary-validation flavour of the same idea, from Nick on PR #397:

"Data should be cleaned/valid before being sent/used in the domain."

Rai's fix: "the query store drops (and logs) any row without a unique_flight_key, so the aggregate receives a guaranteed-present, valid id." Clean at the boundary so the domain never re-checks; its invariants are guaranteed by the fact that nothing invalid can reach it.

Practice

Try it yourself

Recall

Decide at the boundary

State Nick's rule in your own words.

Nick asked, of a nullable date threaded deep into a query store, "Why allow null at all? ... make this explicit upstream rather than buried downstream." What's the general rule, and how did Rai resolve it?

Quiz

Where the retry belongs

Nisha wrote that browser-side retrying "should not have been a frontend concern in the first place ... it should have stayed in the backend." What layering principle is that?