skipnothing/Design Patterns

Chain of Responsibility

Every new role drops a line into checkAccess. The function has grown past 40 lines of if (user.role === '...'), and every team that adds a role edits the same file.

  • ▸A 40-line checkAccess(user, file) grows another if every release, the same file shows up in every team's diff.
  • ▸Pull each if into a class with one next field; the chain's order moves to where you write app.use(...).
  • ▸Same shape, two semantics: first claimer wins (Python try/except) or every link runs pre-next-post (middleware pipelines).
01

The if-ladder that grew

Open checkAccess(user, file):

function checkAccess(user, file) {
  if (user.banned) return false;
  if (file.public) return true;
  if (file.ownerId === user.id) return true;
  if (user.role === 'admin') return true;
  if (user.role === 'auditor' && file.dept === user.dept) return true;
  if (user.role === 'editor' && file.editable) return true;
  // ...nine more arms added over six releases...
  return false;
}

Each if is one team's contribution. The audit team added its line; editor added the next; share-link slotted one in further down. Every release's diff touches this file.

Three problems hide in the shape:

1. Order is part of the contract, invisible in the syntax. if (user.banned) return false only works because it runs before if (user.role === 'admin') return true. Swap them and a banned admin gets through. 2. A new check edits a growing file. The cost of a new role isn't 'one new line', it's 'one new line in a file every team has been editing for six months'. 3. The trailing return false is silent. A permission you forgot to write returns 'deny' with no message. Nobody notices until a user complains.

The shape isn't unique to access. Validation cascades, content-negotiation, error recovery, exception handling, anywhere a request gets routed by 'who can answer this?' grows the same if-ladder.

THE FILE EVERY RELEASE TOUCHES

Keep going, sign up to unlock the rest

4 more parts in this topic, plus 18+ more topics in Design Patterns.

Sign up, it's freeSee the full Design Patterns
Behavioral Patterns0/6#4 Command
#6 Mediator