# Reference patch — 03-maintenance-mode

The answer key for how the reference absorbs this change, and the thing that makes
`budget.json` reproducible. **Never shipped to the candidate.**

1. **Overlay** `../contract-delta/MachineState.java` and `../contract-delta/VendingMachineApi.java`
   onto the files of the same names in `contract/`. Contract files are given, so nothing here is
   charged.
2. **Add** `MaintenanceTransitions.java` (in this directory) to `reference/src/`. New file, so it
   is free.
3. **Change one line** in `reference/src/MachineEvent.java` — the two new words:

   ```diff
   -public enum MachineEvent { INSERT_COIN, SELECT, COLLECT, REFUND }
   +public enum MachineEvent { INSERT_COIN, SELECT, COLLECT, REFUND, ENTER_MAINTENANCE, LEAVE_MAINTENANCE }
   ```

4. **Change one line** in `reference/src/MachineFactory.java`, in `standard()`:

   ```diff
   -                new TransitionTable(Transitions.standard()));
   +                new TransitionTable(MaintenanceTransitions.all()));
   ```

5. **Add four lines** to `reference/src/VendingMachine.java`, after `refund()`:

   ```java
   @Override
   public void enterMaintenance() { state = transitions.next(state, MachineEvent.ENTER_MAINTENANCE); }

   @Override
   public void leaveMaintenance() { state = transitions.next(state, MachineEvent.LEAVE_MAINTENANCE); }
   ```

Measured: `reference_diff = 8` — `MachineEvent.java` 1+1, `MachineFactory.java` 1+1,
`VendingMachine.java` 4+0 — so `diff_budget = max(3, 8 + ceil(8/2)) = 12`.

Both the curveball suite (7 tests) and the base suite (16 tests) are green after the patch. The
base suite staying green matters here: the new table is a strict superset of the old one, so
nothing a customer could already do has changed.

## What the 8 lines are, and what they are not

This is the most expensive of the three curveballs and almost none of the cost is the requirement.
Six of the eight lines are declaration: two new words in an enum, and two new interface methods that
every design must declare somewhere. The budget carries them rather than charging them as a design
failure — the same reasoning as parking-lot's `nextSpotFor`.

**What the requirement itself cost: two rows in a list.** Read
`MaintenanceTransitions.all()` and notice how much of the requirement is not written down anywhere:

| The requirement said | Where it is enforced |
|---|---|
| out of service, it accepts no coins, no selections, no collections and no refunds | nowhere — `MAINTENANCE` has no outgoing edge for those events, and a missing cell already means refuse |
| it can only go out of service when idle | nowhere — the only row pointing at `MAINTENANCE` starts at `IDLE` |
| going out twice, or coming back when never out, is refused | nowhere — same reason |
| coming back leaves the stock and coins as they were | nowhere — a transition moves the state and touches nothing else |

Four rules, zero conditionals. **A table where absence means refusal turns "reject everything" into
the cheapest thing you can ask for.** That is the entire argument for B6, and it is measurable
rather than aesthetic.

## What this costs without the seam

The plausible alternative is a `boolean outOfService` field, or `switch (state)` inside each
operation. Then this requirement is:

- a guard clause in `insertCoin`, `select`, `collect` and `refund` — four edits to four methods, in
  the class that must not break, each one a place the next mode of operation will have to edit again
- an `if (state != IDLE) throw` inside `enterMaintenance`, restating a rule the table would have
  held as data, and a second one inside `leaveMaintenance`
- and, if the state was tracked by an exhaustive `switch (state)` anywhere, **a compile error at
  every such site**, because `MachineState` gained a constant

The last point is worth stating carefully in the defence, because it cuts both ways. An exhaustive
switch failing to compile on a new enum constant is usually a *feature* — it forces the author to
decide. Here the decision is already forced, and forced in the better place: a new state that no
transition mentions can never be entered, so the table cannot be silently incomplete either. The
reference gets the safety without the edits by keying on `EnumMap<>(MachineState.class)` instead,
and that trade is the answer to "why not a switch?".
