Replace four widgets that hold each other with one room that applies the rules, then add an autosave that restores a draft from sealed, deep-copied snapshots.
A group-order screen has four widgets: a Cart, a Roster, a PayDesk and a Banner. In the code in the editor each one holds the others it needs, so the rules about how they affect each other are spread over all four. It works. It just can't grow: a fifth widget edits three of the old ones. Refactor it into the Mediator pattern, then add the Memento pattern for an autosaved draft.
Build this API:
Mediator.notify(sender, event, name="", amount=0). Room implements it. The colleagues hold only the room, never each other.Cart(room): add(name, price) only reports "add" to the room (sender "cart"); put(name, price) stores the item (the room calls it); total(); items (a list of (name, price)).Roster(room): join(name) reports "join" (sender "roster"); admit(name) stores it; names.PayDesk(room): lock() reports "lock" (sender "desk"); pay(name) reports "pay" and returns the member's share; split(total, names) sets shares (equal shares, and the first total % count members pay one rupee more); paid is the list of members who have paid.Banner: show(text) and text.Room(): builds the four parts, and has locked, heard (a dict of events accepted, by sender) and rules (a dict from event name to a function (name, amount)). notify runs the event's rule, then counts it in heard, then sets the banner. An unknown event raises ValueError("unknown event: <event>"). A refused call must change nothing, counts included.add and join raise ValueError("the cart is locked") once locked. lock raises "nobody has joined" for an empty roster, otherwise splits the cart's total over the roster and locks. pay raises "lock the cart first" before the lock, "not in this room" for a name with no share, and "already paid" for a second payment.open: 3 members, 3 items, total 490, then locked: total 490, 1 of 3 paid, and placed: total 490, paid by 3 once everyone has paid.Draft() with add(name, qty), note(name, text), remove(name), render() (for example biryani x2 [no onion]; lassi x1, or (empty)), save() returning a memento and restore(memento). Both save and restore deep-copy.Autosave(draft, every=3, keep=2) with edited() (call it after every edit: every everyth call saves, and only the newest keep saves are kept), restore(back=1) (1 is the newest save, 2 the one before), and the counters edits, saves and kept. It must never look inside a memento.JavaScript and TypeScript use the same names; errors are Errors with the same messages, and heard is a Map.
The tests check the shares and the banner, refusals, the counts, a colleague with a fake room, a new event added to the rule table inside a test, that no colleague mentions another, deep snapshots and the autosave limit.
Write your code, then run 9 example tests and 5 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.