1003. Lesson identity
This lesson turns the distinction between scope and ownership into an auditable artifact. You will build a state-ownership sheet and use it to identify one unsafe or unresolved shared variable.
1004. Learning objective
After this lesson, you can produce a state-ownership sheet that names the authoritative writer, readers, and permitted write operation for each resolved value, then identify and justify one unsafe or unresolved shared variable.
1005. Why this matters
A state value can be visible to many systems without being safe for all of them to modify. When responsibilities remain implicit, a UI component, controller, save routine, and gameplay rule may all write the same value for different reasons. The resulting defect is often a disagreement about authority rather than a syntax error.
A state-ownership sheet makes that disagreement inspectable. It helps you direct AI assistance, review code, and decide where a state change must be validated and committed.
1006. Prior knowledge
You should already be able to distinguish scope from ownership from 3.2 L1 — Scope is not ownership. You should also be able to describe a system by its responsibility and identify state that a system reads without assuming that it owns the corresponding rules.
1007. Core concept
A state-ownership sheet records separate decisions for each important value:
- State value: What fact or value exists?
- Authoritative writer: Which system owns the rule that validates and commits changes?
- Readers: Which systems may observe, serialize, or display the value?
- Permitted change boundary: Which authoritative commit operation may change it? If requests are part of the design, which request is accepted and which operation performs the commit?
- Evidence or concern: What code, rule, or unresolved question supports the classification?
A request is not the same as a committed change. A command may request a transition, an authoritative operation may validate and commit it, and an event may notify other systems that a fact has changed. Do not assume that every event writes state.
For this sheet, record either:
- the authoritative commit operation, such as
applyDamage(amount); or - both the accepted request and the committing operation, such as
RequestDamage(amount) → HealthSystem.applyDamage(amount).
Detailed message-contract design belongs to Module 3.3. Here, the goal is to make the ownership boundary explicit.
1008. Mental model
Use the one authority, many readers model:
request ───────────▶ authoritative owner ───────────▶ committed state
validates and commits
│
┌─────────────┼─────────────┐
▼ ▼ ▼
HUD reader Save reader Other reader
│
change notification
For each row, answer these questions in order:
| Question | Decision |
|---|---|
| What fact is represented? | Name the state value precisely. |
| Who validates and commits changes? | Name one authoritative writer or record an evidence gap. |
| Who only observes it? | List readers separately and keep them read-only. |
| How may it change? | Name the commit operation, or the accepted request and commit operation. |
| What would be unsafe? | Identify a system that can bypass the authority or write without validation. |
A variable is a strong candidate for review when it has unrelated writers, when a reader writes for convenience, when restoration bypasses its owner, or when the commit boundary is not explicit.
1009. Concrete example
| State value | Authoritative writer | Readers | Permitted change boundary | Concern to investigate |
|---|---|---|---|---|
playerHealth |
Health system | HUD, damage feedback, save system | RequestDamage(amount) → HealthSystem.applyDamage(amount) |
HUD directly assigning the displayed value |
selectedLoadout |
Loadout system | Menu, player spawn, summary screen | RequestLoadout(id) → LoadoutSystem.selectLoadout(id) after validation |
Menu and spawn code both assigning the selection |
isPaused |
Pause coordinator | Input routing, HUD, simulation systems | PauseCoordinator.setPauseState(source, value) |
A UI panel changing the global flag directly |
unlockedAreas |
Progression system | Map UI, save system | ProgressionSystem.unlockArea(id); restoration is validated and committed by ProgressionSystem.restoreUnlocks(data) |
A deserializer assigning the collection directly |
The important detail is the boundary, not the variable name. Other systems can request or observe a change, but the owner decides whether it is valid and commits it. A notification emitted after the commit can inform readers without becoming another writer.
If a row appears to have two independent authoritative writers, do not silently accept it. Mark the row for redesign, document why split authority is intentional, or record the evidence needed to resolve the question.
1010. Saved and restored state
Serialization usually reads state, but restoration can write it. For every saved or restored value, identify:
- the system that reads the value for serialization;
- the system that validates restored data; and
- the authoritative operation that commits the restored value.
Flag a direct deserializer write when it bypasses the system that owns the state rule. For example, a save loader may submit restored unlock data, but the progression system should validate and commit it if that system owns unlock rules.
1011. AI-native workflow
Use AI as a classification and review assistant, not as the owner of the design decision.
- Draft the sheet from the system responsibilities and code evidence you can identify.
- Ask AI to find rows with multiple possible writers, readers that appear to mutate state, vague change boundaries, or restoration paths that bypass an owner.
- Ask AI to explain each concern using the fields in the sheet. Do not ask it to redesign the architecture automatically.
- Compare each suggestion with the game rules and available evidence.
- Accept, reject, or revise each suggestion explicitly.
- Select one unsafe or unresolved shared variable and document the evidence for your conclusion.
A useful prompt is:
Review this state-ownership sheet. For every row, distinguish the authoritative writer from readers. Flag multiple writers, vague commit operations, readers that mutate state, and restoration paths that bypass the owner. Do not redesign the systems. Explain the evidence for each flag and preserve explicit unknowns.
If the project does not expose enough information to classify a row, write unknown instead of guessing. An explicit evidence gap is more useful than a confident but unsupported assignment.
1012. Common mistakes
Confusing storage with ownership
The component that stores a variable is not automatically the authority for its changes. Storage location, access scope, and ownership are separate decisions.
Calling every caller a writer
A system that submits a request is not necessarily the system that commits the change. Record both steps when the distinction matters.
Treating notifications as writes
An event may announce that a change has already happened. Do not list it as a write operation unless the architecture explicitly uses it as an accepted request and still identifies the operation that validates and commits the state.
Ignoring restoration
A save loader that assigns values directly can bypass validation. Record who validates and commits restored data instead of treating loading as a neutral read operation.
1013. Guided practice
Create a state-ownership sheet for a small game slice you know. Do not change project code during this exercise. Use this structure:
| State value | Meaning | Authoritative writer | Readers | Permitted change boundary | Evidence / concern |
|---|---|---|---|---|---|
Complete at least six rows, including:
- one player or actor state value;
- one UI-visible value;
- one progression or unlock value;
- one temporary session value;
- one saved or restored value; and
- one value whose authority is uncertain.
For the saved or restored row, name who validates and commits restoration. Flag the row if a deserializer writes directly and bypasses the authoritative owner.
Then audit the sheet:
- Mark every row with more than one possible writer.
- Check whether any listed reader also mutates the value.
- Replace vague permissions such as “can update it” with an authoritative commit operation or a request-to-commit path.
- Verify that resolved rows distinguish requests, commits, and notifications where those distinctions are relevant.
- Select one unsafe or unresolved shared variable.
- Write a two-sentence diagnosis naming the competing writers and the preferred authority, or describing the missing evidence and the next inspection needed.
Your design decision is the selection and justification of the unsafe or unresolved variable. Do not force an ownership assignment when the evidence is insufficient.
1014. Practical checkpoint
Submit the completed sheet and diagnosis through State-ownership sheet audit, the practical assessment attached to this lesson. The checkpoint evaluates whether your six rows identify authorities or evidence gaps, separate readers, name valid change boundaries, address restoration, and justify one unsafe or unresolved variable.
1015. Validation and evidence
Your work is ready for assessment when it contains:
- at least six state rows;
- one authoritative writer for every resolved row, or a specific evidence gap;
- readers separated from writing authorities;
- an authoritative commit operation, or a request and commit path, for every resolved row;
- a restoration authority and commit path for the saved or restored value;
- one variable flagged as unsafe or unresolved; and
- a diagnosis supported by evidence from the sheet.
A strong sheet lets another developer ask, “Who may commit this change?” and find one answer, a documented exception, or a precise evidence gap.
1016. Key takeaways
- Scope describes who can access state; ownership describes who validates and commits its rule-governed changes.
- One authoritative writer with many readers is a useful default.
- A request asks for a transition; the authoritative operation validates and commits it; a notification can announce the result.
- Restoration must pass through a documented authority rather than bypassing the owner.
- Multiple unrelated writers indicate an unsafe or undocumented boundary.
- AI can flag inconsistencies, but you remain responsible for the ownership decision.
1017. Next lesson
Next: 3.3 L1 — A message is a contract. The producer, authority, permitted request, and commit information in your ownership sheet will help you write one complete event contract without confusing a request, a committed state change, and its notification.
1018. Knowledge check
Answer these items for yourself before reading the answers.
Which field identifies the system that validates and commits a state change?
Show answer and feedback
Answer: Authoritative writer
Why: The authoritative writer owns the rule that validates and commits the change. Readers may observe the result without owning that rule.
A HUD displays health and assigns a new health value whenever the display refreshes. What should the sheet flag?
Show answer and feedback
Answer: The HUD is a reader and an unsafe writer unless it owns the health rule
Why: A display system normally reads health. Assigning health directly creates another writer and may bypass the system that validates health changes.
Which entry makes the permitted change boundary most auditable?
Show answer and feedback
Answer: RequestDamage(amount) → HealthSystem.applyDamage(amount), with validation before commit
Why: This entry distinguishes the request from the authoritative operation that validates and commits the change. It does not imply that a notification event directly writes state.
A save loader restores an unlock collection by assigning it directly, bypassing the progression system. What should the sheet record?
Show answer and feedback
Answer: The direct assignment as a concern, plus the system and operation that should validate and commit restoration
Why: Restoration writes state. The sheet should identify the direct write as a bypass and name the authority responsible for validating and committing restored data.