YNAB: where money is kept and what it is for are different questions
YNAB helps people give the money they already have a purpose. Accounts show where it is kept; categories show what is reserved for rent, food or later needs. Both views describe the same funds.
Break down the problem and try your own design and implementation first. Then explore the reasoning to check states, edge cases, trade-offs, and ways to test your approach. The guide offers a reasoning path, not a complete implementation.
Apply a group of allocation changes together
Implement an “apply adjustments together” module for a local purpose planner. A user lists several category transfers at once. On confirmation, either all succeed or the original plan stays completely unchanged. Amounts use integer cents. A plan contains category names and their nonnegative available amounts. Each adjustment specifies a source category, destination category and amount. Categories are guaranteed to exist, source and destination differ, and amounts are positive integers.
- Accept a plan and an ordered list of adjustments. Check sufficient funds in that order; money received in an earlier adjustment may fund a later one. If all succeed, return a success result and the new plan. If any lacks funds, return a failure result, the position of the first failed adjustment and the original plan, without retaining earlier calculated changes. An empty list succeeds with unchanged amounts. Never modify the input plan, whether successful or not. A caller changing the returned plan must not affect the input plan either. Choose the interface and internal code organization yourself.
- Start with {food:40000,outing:20000,rent:90000}. First move 10000 from outing to food, then 45000 from food to rent. The result is {food:5000,outing:10000,rent:135000}, still totaling 150000. If the second adjustment instead moves 15000 from outing to rent, the whole group fails and returns the original 40000, 20000 and 90000, not the state after the first adjustment. Also test moving all 20000 from outing to food: it succeeds with outing at zero.
- Deliver a runnable module and these call results. Add checks for an empty list and a caller changing a returned result. Explain how you organize sequential calculations and the final result so later steps can use earlier funds without leaving partial changes after failure. Handle local data only, without a bank or database.
Explore the reasoning
- Sketch the initial plan, each intermediate state and the final return value. Distinguish changes used only for this calculation from the result handed to the caller.
- Compare a working copy, accumulated changes or undo information: how would each preserve the original plan when the second adjustment fails? Do not check only a successful single transfer.
- Check an earlier transfer funding a later one, insufficient funds in the second adjustment, exact depletion and an empty list. Then modify the returned plan to check for unintended links between external data objects.