Skip to content

refactor(tui): decompose 62-field Model struct into focused sub-models #78

@jongio

Description

@jongio

Summary

The Model struct in internal/tui/model.go has grown to 62 fields across 100 lines (lines 143–244), and the file itself is 3,438 lines long. This makes the struct a God Object — a single type that manages UI state, data layer, query parameters, loaded data, search tracking, attention scanning, work status, click debounce, Copilot SDK coordination, and DB watching.

Why This Matters

  • Cognitive load: Any developer modifying TUI behavior must understand 62 fields and their interactions.
  • Divergent change: The struct is modified for unrelated reasons — UI layout changes, search behavior, attention scanning, work status tracking, and Copilot SDK coordination all touch the same type.
  • Test difficulty: Testing any single concern requires constructing the entire 62-field Model.

Current Field Groups

Concern Fields Lines
UI state 5 144–152
Data layer 2 155–156
Query parameters 5 159–163
Loaded data 3 166–168
Shell/terminal detection 2 171–172
Sub-components 9 175–183
UI toggles 10 186–195
Click debounce 3 199–201
Search tracking 4 207–208, 212
Status bar 2 215–216
Copilot SDK 5 219–223
Attention tracking 2 226–227
Plan tracking 2 230–231
Work status 6 234–239
DB watcher 2 242–243

Suggested Refactoring

Extract focused sub-models using composition:

  • SearchState — deepSearchVersion, deepSearchPending, copilotSearchVersion, copilotSearching, copilotSearchCancel, aiSessionIDs
  • WorkStatusState — workStatusMap, filterWorkStatus, workStatusScanned, workStatusScanning, workStatusAICancel, autoShowPlan
  • AttentionState — attentionMap, attentionFilter
  • ClickState — pendingClickVersion, pendingClickY, pendingClickItemIdx

Each sub-model can own its related update logic, reducing the Model.Update method size proportionally.

Smell Categories

  • Bloaters → Large Class (62 fields, threshold: 10)
  • Change Preventers → Divergent Change (modified for 10+ unrelated reasons)
  • Architectural → God Object (single struct managing entire application state)

Metadata

Metadata

Assignees

No one assigned

    Labels

    automatedCreated by automationsmellsCode smell detection

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions