vampire-like/skills/ui-five-layer-architecture/references/ui-five-layer-standard.md

5.8 KiB

UI Five-Layer Architecture Standard

Table of Contents

  1. Scope and Intent
  2. Core Model
  3. Layer Definitions
  4. UI Module Levels
  5. Dependency Rules
  6. Event Communication Rules
  7. Interaction Flow
  8. Naming and Folder Conventions
  9. Testing Policy
  10. Anti-Patterns
  11. Delivery Checklist

Scope and Intent

Use this standard to define and enforce a stable UI architecture that can be reused across projects.

Primary goals:

  • keep business logic independent from UI rendering
  • keep UI rendering deterministic and testable
  • make reviews and refactors consistent
  • reduce coupling and regression risk

Core Model

Base chain:

External Flow
  -> Controller
      -> UseCase
      -> RawData / Result
      -> BuildContext
      -> View

View
  --(UI-local event)--> Controller

Rules:

  • UseCase produces business outputs only.
  • Controller is the only layer that creates Context.
  • View only renders and emits interaction events.

Layer Definitions

UseCase

Responsibilities:

  • own business rules and state transitions
  • validate business actions
  • return RawData or result objects

Constraints:

  • do not depend on Context, View, or rendering types
  • do not format display strings or map visual assets
  • do not publish UI-local events

RawData

Responsibilities:

  • carry business data from UseCase to Controller

Constraints:

  • keep data business-oriented
  • do not reference any *Context type
  • do not contain rendering objects (for example UI components)

Controller

Responsibilities:

  • be the external entry point for open/close/refresh
  • bind and call UseCase
  • transform RawData/Result into Context
  • subscribe/unsubscribe UI-local events
  • coordinate full or partial refresh

Constraints:

  • do not let View bypass controller orchestration
  • do not hide heavy business logic that belongs in UseCase

Context

Responsibilities:

  • carry display-ready data for rendering

Constraints:

  • construct/update only in Controller
  • do not enter UseCase
  • allow composition (FormContext, ItemContext, AreaContext)

View

Responsibilities:

  • bind controls and render Context
  • emit UI-local interaction events

Constraints:

  • do not call UseCase
  • do not mutate domain state
  • do not subscribe to global business events
  • do not become external entry points

UI Module Levels

Standard Five-Layer Module

Structure:

  • UseCase + RawData + Controller + Context + View

Use when:

  • module owns business rules, validations, or branching state transitions
  • user actions mutate domain state
  • behavior requires automated verification

Lightweight Module

Structure:

  • Controller + Context + View

Use when:

  • module is display/navigation/confirmation only
  • no independent business rules are present

Rule:

  • upgrade to standard five-layer as soon as business rules appear

Dependency Rules

Allowed:

  • UseCase -> domain/services/RawData/Result
  • Controller -> UseCase/RawData/Result/Context/View/UI-local events
  • Context -> child context/value objects
  • View -> Context/UI-local events

Forbidden:

  • UseCase -> Context/View/rendering types
  • RawData/Result -> Context/View
  • Context -> UseCase/View
  • View -> UseCase
  • View -> global business events
  • View -> domain state mutation

Event Communication Rules

Event Ownership

  • View -> Controller uses UI-local events only
  • UI-local events are not global business contracts
  • business/domain modules must not consume UI-local event semantics

Safety Requirements

  • validate sender ownership in Controller
  • scope handling to the active UI instance
  • keep subscribe/unsubscribe symmetric

Interaction Flow

Standard Module

External Flow
   -> create/bind UseCase
   -> open UI via Controller

Controller
   -> UseCase action
   -> RawData/Result
   -> BuildContext
   -> View refresh

View
   --(UI-local event)--> Controller

Lightweight Module

External Flow
   -> open UI via Controller(userData)

Controller
   -> BuildContext(userData)
   -> View refresh

View
   --(UI-local event)--> Controller

Naming and Folder Conventions

Recommended folders:

  • UI/<Domain>/UseCase
  • UI/<Domain>/RawData
  • UI/<Domain>/Controller
  • UI/<Domain>/Context
  • UI/<Domain>/View

Recommended naming:

  • XXXFormUseCase
  • XXXFormRawData
  • XXXFormController
  • XXXFormContext, XXXItemContext, XXXAreaContext
  • XXXResult, XXXActionResult

Testing Policy

Policy:

  • if a UI has a UseCase and automated tests are added, use EditMode tests for the UseCase

Priority coverage:

  • initial model generation
  • business branch and validation behavior
  • action result correctness
  • boundary and invalid input handling

Manual verification focus:

  • first open
  • interaction refresh
  • partial refresh
  • close and reopen
  • null/invalid userData behavior

Anti-Patterns

Do not allow:

  • UseCase returning Context
  • RawData carrying *Context
  • View subscribing global business events
  • direct domain mutation inside View
  • skipping Controller as module entry
  • module marked lightweight while carrying business state transitions

Delivery Checklist

Use this checklist before marking work complete:

  1. classify each module as standard or lightweight
  2. verify business rules sit in UseCase only
  3. verify Context is built only in Controller
  4. verify RawData has no presentation model leakage
  5. verify View is render-and-emit only
  6. verify UI-local events are scoped and sender-checked
  7. verify dependency direction constraints pass
  8. verify tests/manual checks match the testing policy