Studio 2 — The Model Redesign
Subtitle
Refactoring data models so systems can evolve without hidden state corruption.
Studio Focus This studio chapter is hands-on: implement, verify behavior, and document tradeoffs as you iterate.
The Situation
Studio 1 proved we could ship tiny vertical slices.
Now those slices are under stress.
As soon as requirements grow, model weaknesses appear:
- entity identity is unclear (
"task"vs"route"vs"request"used interchangeably) - relationships are implicit (IDs inside free-text fields)
- transition rules are scattered (status changes happen from many places)
- invalid states are easy to create and hard to detect
Part II gave us the tools to fix this:
- model entities explicitly
- define relationships with constraints
- shape data around real operations
- model change with legal transitions and invariants
Your job in Studio 2 is to redesign all three systems using those principles.
Engineering Brief
Redesign the core data models for all three systems (delivery, knowledge, virtual world).
Required outcomes:
- explicit entities with stable identity
- explicit relationships with clear cardinality/constraints
- transition operations with contracts (
require/ensure) - invariants that make invalid states hard to represent
- migrated behavior examples from Studio 1
Implementation guidance:
- optimize for correctness and clarity before optimization
- keep model boundaries obvious
- make failure behavior explicit (not silent)
Implementation In Nex
Use Nex to encode model assumptions directly in code.
Suggested files:
delivery_model_v2.nexknowledge_model_v2.nexworld_model_v2.nexstudio_2_main.nex
If using the web IDE, place all classes in one file and run App.run.
Delivery Model V2
Focus: identity + legal transitions + assignment relationship.
class Delivery_Task
feature
task_id: String
origin: String
destination: String
status: String
assigned_robot_id: String
assign(robot_id: String)
require
robot_present: robot_id /= ""
can_assign: status = "PENDING"
or status = "FAILED"
do
assigned_robot_id := robot_id
status := "IN_TRANSIT"
ensure
assigned: assigned_robot_id = robot_id
and status = "IN_TRANSIT"
end
complete()
require
in_transit: status = "IN_TRANSIT"
do
status := "DELIVERED"
ensure
delivered: status = "DELIVERED"
end
fail(reason: String)
require
reason_present: reason /= ""
not_delivered: status /= "DELIVERED"
do
status := "FAILED"
ensure
failed: status = "FAILED"
end
create
pending(task_id: String, origin: String,
destination: String) do
this.task_id := task_id
this.origin := origin
this.destination := destination
this.status := "PENDING"
end
invariant
id_present: task_id /= ""
endpoints_present: origin /= ""
and destination /= ""
valid_status:
status = "PENDING" or status = "IN_TRANSIT"
or status = "DELIVERED"
or status = "FAILED"
transit_has_assignment:
status /= "IN_TRANSIT"
or assigned_robot_id /= ""
end
Knowledge Model V2
Focus: relationship as first-class entity (Doc_Link) rather than ad hoc references.
class Document
feature
doc_id: String
title: String
body: String
create
make(doc_id: String, title: String) do
this.doc_id := doc_id
this.title := title
end
invariant
id_present: doc_id /= ""
title_present: title /= ""
end
class Doc_Link
feature
from_doc_id: String
to_doc_id: String
link_type: String
is_valid(): Boolean do
result :=
from_doc_id /= "" and
to_doc_id /= "" and
from_doc_id /= to_doc_id and
(link_type = "references"
or link_type = "related"
or link_type = "contradicts")
ensure
bool_result: result = true or result = false
end
create
make(f: String, t: String, lt: String) do
from_doc_id := f
to_doc_id := t
link_type := lt
end
invariant
endpoints_present: from_doc_id /= ""
and to_doc_id /= ""
no_self_link: from_doc_id /= to_doc_id
end
Virtual World Model V2
Focus: deterministic update transition with explicit bounds.
class World_Object
feature
object_id: String
x: Integer
vx: Integer
step(max_x: Integer)
require
valid_bound: max_x >= 0
do
let next: Integer := x + vx
if next < 0 then
x := 0
elseif next > max_x then
x := max_x
else
x := next
end
ensure
bounded_after_step: x >= 0 and x <= max_x
end
create
make(id: String, x: Integer, vx: Integer) do
object_id := id
this.x := x
this.vx := vx
end
invariant
id_present: object_id /= ""
end
Studio Driver
Use one driver to validate nominal + edge behavior.
class App
feature
run() do
-- Delivery
let t: Delivery_Task :=
create Delivery_Task.pending("T001", "A", "C")
t.assign("R7")
print(t.status) -- IN_TRANSIT
t.complete
print(t.status) -- DELIVERED
-- Knowledge
let l: Doc_Link :=
create Doc_Link.make("D1", "D2", "references")
print(l.is_valid) -- true
-- World
let w: World_Object :=
create World_Object.make("0-1", 9, 4)
w.step(10)
print(w.x) -- 10 (clamped)
end
end
Studio Challenges
Level 1 — Core Implementation
- Redesign one system model (delivery or knowledge or world).
- Encode at least 2 invariants and 2 transition operations.
- Run one nominal and two edge cases.
Level 2 — Cross-System Model Consistency
- Redesign all three systems.
- Use a common modeling vocabulary in notes:
- entity
- relationship
- invariant
- transition
- Show one “before vs after” bug that the new model prevents.
Level 3 — Exploration
Pick one experiment:
- State-centric vs event-centric transition handling for delivery reassignment.
- Direct references vs link entities in the knowledge model.
- Single-step deterministic update vs queued events in virtual world updates.
Evaluate:
- complexity impact
- testability impact
- failure-mode clarity
Postmortem
Discuss:
- Which entity boundary decision removed the most confusion?
- Which relationship constraint prevented a real invalid state?
- Which transition rule was hardest to make explicit?
- Which tradeoff did you intentionally accept (and why)?
Use concrete evidence from your runs, not just opinions.
Deliverables
- redesigned Nex models for delivery, knowledge, and world systems
- short modeling notes per system:
- entities
- relationships
- invariants
- transitions
- nominal + edge test output logs
- one before/after comparison showing reduced accidental complexity
Exit Criteria
You are ready for Studio 3 if:
- you can explain identity vs state for each core entity
- invalid states are blocked by model rules (not just comments)
- transition legality is encoded in operations/contracts
- relationship constraints are explicit and testable