Studio 4

The Architecture Refactor

Evolving Studio 3 optimizations into stable component architecture.

The Situation

Studio 3 made the common lookups fast by adding indexes around the Studio 2 classes. The speed came at a price. The delivery workflow now calls Delivery_Task_Store_V3 directly, so it knows how tasks are stored as well as what they mean, and the same coupling repeats in the knowledge and world code. Swapping a store, or testing a workflow without one, now means touching code that has nothing to do with the change. The symptoms:

  • orchestration logic mixed with storage details
  • duplicate workflow rules across modules
  • direct dependency on concrete classes everywhere
  • difficult integration testing due to tight coupling

Engineering Brief

Refactor around components, ports, and contracts without changing externally visible behavior.

Required outcomes:

  • preserve Studio 3 semantics and performance intent
  • define explicit component boundaries
  • introduce interface-style ports for collaboration
  • isolate domain logic from infrastructure details
  • keep dependencies pointing toward domain intent

Implementation guidance:

  • start from existing V3 code paths
  • create extension points first, then move logic behind them
  • prove behavior parity with before-and-after run checks

Implementation In Nex

Suggested files:

  • architecture_ports.nex
  • delivery_arch_refactor.nex
  • knowledge_arch_refactor.nex
  • world_arch_refactor.nex
  • studio_4_main.nex

Shared Ports (Interfaces By Contract)

These ports abstract over concrete V3 storage and index implementations from Studio 3. Each port is a deferred class: it states the contract and leaves the implementation to an adapter. The adapters below wrap the Studio 3 V3 classes directly, so this studio builds on the Studio 2 and Studio 3 files, and every service depends on a port rather than on the adapter behind it.

deferred class Task_Query_Port
feature
  status_of(task_id: String): String
  require
    id_present: task_id /= ""
  deferred
  ensure
    non_empty: result /= ""
  end
end

deferred class Doc_Query_Port
feature
  has_doc(doc_id: String): Boolean
  require
    id_present: doc_id /= ""
  deferred
end

deferred class World_Update_Port
feature
  step_object(object_id: String, max_x: Integer): String
  require
    id_present: object_id /= ""
    valid_bound: max_x >= 0
  deferred
  ensure
    known_result: result = "UPDATED" 
                  or result = "NOT_FOUND"
  end
end

Delivery Refactor (Using Studio 3 V3 Store)

Before (Studio 3): callers directly used Delivery_Task_Store_V3.

After (Studio 4): callers depend on Task_Query_Port; concrete store is adapted behind it.

class Delivery_Task_Adapter
  inherit Task_Query_Port
create
  make(store: Delivery_Task_Store_V3) do
    this.store := store
  end
feature
  store: Delivery_Task_Store_V3

  status_of(task_id: String): String do
    result := store.find_status(task_id).value
  end
end

class Delivery_Workflow
create
  make(tasks: Task_Query_Port) do
    this.tasks := tasks
  end
feature
  tasks: Task_Query_Port

  dispatch_view(task_id: String): String
  require
    id_present: task_id /= ""
  do
    let st: String := tasks.status_of(task_id)
    if st = "NOT_FOUND" then
      result := "UNKNOWN_TASK"
    else
      result := "TASK_STATUS:" + st
    end
  ensure
    non_empty: result /= ""
  end
end

Knowledge Refactor (Port and Validator Service)

class Doc_Query_Adapter
  inherit Doc_Query_Port
create
  make(model: Knowledge_Model_V3) do
    this.model := model
  end
feature
  model: Knowledge_Model_V3

  has_doc(doc_id: String): Boolean do
    result := model.by_id.contains_key(doc_id)
  end
end

class Link_Validation_Service
create
  make(docs: Doc_Query_Port) do
    this.docs := docs
  end
feature
  docs: Doc_Query_Port

  validate(from_id, to_id: String): String
  require
    ids_present: from_id /= "" and to_id /= ""
  do
    if not docs.has_doc(from_id) then
      result := "MISSING_FROM"
    elseif not docs.has_doc(to_id) then
      result := "MISSING_TO"
    else
      result := "VALID"
    end
  ensure
    known_result:
      result = "VALID" or
      result = "MISSING_FROM" or
      result = "MISSING_TO"
  end
end

World Refactor (Port and Use Case Service)

class World_Update_Adapter
  inherit World_Update_Port
create
  make(model: World_Model_V3) do
    this.model := model
  end
feature
  model: World_Model_V3

  step_object(object_id: String, max_x: Integer): String do
    result := model.step_by_id(object_id, max_x).value
  end
end

class World_Step_Service
create
  make(updater: World_Update_Port, max_x: Integer) do
    this.updater := updater
    this.max_x := max_x
  end
feature
  updater: World_Update_Port
  max_x: Integer

  advance(object_id: String): String
  require
    id_present: object_id /= ""
  do
    result := updater.step_object(object_id, max_x)
  ensure
    known_result: result = "UPDATED" 
                  or result = "NOT_FOUND"
  end
invariant
  bound_valid: max_x >= 0
end

Studio Driver (Behavior Parity Check)

class App
feature
  run() do
    -- Delivery setup (Studio 2 tasks, Studio 3 store)
    let t1 := create Delivery_Task.pending("T-1", "Hub-A", "Zone-1")
    let t2 := create Delivery_Task.pending("T-2", "Hub-A", "Zone-2")
    t2.assign("R-2")
    let ds := create Delivery_Task_Store_V3.make([t1, t2])
    let dw := create Delivery_Workflow.make(
      create Delivery_Task_Adapter.make(ds)
    )
    print(dw.dispatch_view("T-2"))   -- TASK_STATUS:IN_TRANSIT
    print(dw.dispatch_view("T-99"))  -- UNKNOWN_TASK
    -- Knowledge setup (Studio 2 documents, Studio 3 index)
    let km := create Knowledge_Model_V3.make([
      create Document.make("D-1", "Graphs"),
      create Document.make("D-2", "Trees"),
      create Document.make("D-3", "Maps")
    ])
    let lvs := create Link_Validation_Service.make(
      create Doc_Query_Adapter.make(km)
    )
    print(lvs.validate("D-1", "D-3"))   -- VALID
    print(lvs.validate("D-9", "D-3"))   -- MISSING_FROM
    -- World setup (Studio 2 objects, Studio 3 index)
    let wm := create World_Model_V3.make([
      create World_Object.make("E-1", 8, 2)
    ])
    let wss := create World_Step_Service.make(
      create World_Update_Adapter.make(wm), 10
    )
    print(wss.advance("E-1"))  -- UPDATED
    print(wss.advance("E-9"))  -- NOT_FOUND
  end
end

Expected outcome:

  • same core behavior as Studio 3 refactored paths
  • clearer component boundaries
  • easier component-level testing due to port boundaries

Studio Challenges

Level 1 — One Architectural Extension Point

  • pick one Studio 3 optimized path
  • introduce a port-and-adapter boundary
  • prove behavior parity on nominal and edge cases

Level 2 — Three-Domain Architecture Pass

  • apply the port-and-adapter pattern, with service orchestration, to delivery, knowledge, and world
  • remove at least one direct concrete dependency per domain
  • document dependency direction before and after

Level 3 — Alternative Architecture Experiment

  • compare two styles:
    • ports and adapters with thin services
    • feature modules with internal adapters
  • evaluate maintainability and migration cost

Postmortem

Discuss with evidence:

  • Which extension point reduced coupling the most?
  • Which abstraction clarified behavior, and which added unnecessary ceremony?
  • Which components are still doing too much?
  • What is the next architecture risk if the system doubles again?

Deliverables

  • architecture diagram with components and dependency direction
  • refactored Nex code using ports and adapters over Studio 3 V3 logic
  • behavior-parity run log (before-and-after outputs)
  • short architecture decision record (ADR): a note stating the chosen architecture, the alternative we rejected, and why

Exit Criteria

We are ready for Part VII if:

  • key use cases depend on ports, not concrete storage classes
  • orchestration logic is separated from storage and index details
  • cross-component contracts are explicit and testable
  • behavior parity with Studio 3 is demonstrated