Skip to content

Decompose main.js monolithic file for better maintainability #85

@IanMayo

Description

@IanMayo

Problem Description

The src/main.js file has grown to 709 lines and contains mixed responsibilities, making it difficult to maintain, test, and extend. This monolithic structure violates the single responsibility principle and makes the codebase harder to navigate.

Current File Responsibilities

The main.js file currently handles:

  • GramFrame class definition and initialization
  • UI component creation and management
  • Event handling setup and management
  • Zoom and pan functionality
  • State management integration
  • ResizeObserver setup
  • Mode switching logic
  • Configuration processing

Impact Assessment

  • Risk Level: HIGH - Large refactoring effort
  • Current Size: 709 lines in single file
  • Complexity: Mixed concerns make testing and maintenance difficult
  • Benefits: Better separation of concerns, easier unit testing, improved maintainability

Suggested Decomposition Strategy

Proposed File Structure

  1. src/components/MainUI.js (~150-200 lines)

    • UI creation methods: createSVGContainer(), createLEDDisplays(), etc.
    • Layout management functions
    • DOM element creation utilities
  2. src/core/viewport.js (~100-150 lines)

    • Zoom/pan logic: handleZoom(), handlePan(), resetZoom()
    • Viewport state management
    • Coordinate transformation utilities
  3. Enhanced src/core/events.js (~100-150 lines)

    • Event handler setup and management
    • ResizeObserver integration
    • Event delegation patterns
  4. Slimmed src/main.js (~200-300 lines)

    • Core GramFrame class definition
    • Public API methods
    • Component orchestration
    • Initialization logic

Benefits of Decomposition

  • Improved Testability: Smaller, focused modules easier to unit test
  • Better Maintainability: Clear separation of concerns
  • Enhanced Readability: Developers can focus on specific functionality
  • Easier Debugging: Issues isolated to specific functional areas
  • Future Extensibility: New features can be added to appropriate modules

Implementation Plan

Phase 1: Analysis and Planning

  • Analyze current dependencies and method relationships
  • Create detailed migration plan for each method group
  • Identify potential breaking changes

Phase 2: Extract Utility Modules

  • Create src/core/viewport.js with zoom/pan functionality
  • Create src/components/MainUI.js with UI creation methods
  • Update imports and ensure all tests pass

Phase 3: Enhance Core Modules

  • Extend src/core/events.js with additional event handling
  • Move appropriate state management helpers to src/core/state.js
  • Update documentation and type definitions

Phase 4: Slim Down Main Class

  • Remove extracted functionality from main.js
  • Update constructor and initialization logic
  • Ensure public API remains unchanged

Acceptance Criteria

  • main.js reduced to under 350 lines
  • All functionality moved to appropriate specialized modules
  • All 59 Playwright tests continue passing
  • No changes to public GramFrame API
  • TypeScript/JSDoc compliance maintained
  • Performance benchmarks show no regression
  • Code review completed for all new modules

Risk Mitigation Strategies

  • Incremental Implementation: Extract one module at a time
  • Comprehensive Testing: Run full test suite after each extraction
  • API Compatibility: Ensure no breaking changes to public interface
  • Documentation Updates: Update architecture documentation
  • Rollback Plan: Maintain ability to revert changes if issues arise

Example Migration

Before (main.js):

class GramFrame {
  createSVGContainer() { /* 50 lines */ }
  handleZoom(event) { /* 30 lines */ }
  setupEventHandlers() { /* 40 lines */ }
  // ... 600+ more lines
}

After:

// main.js
import { MainUI } from './components/MainUI.js'
import { Viewport } from './core/viewport.js'

class GramFrame {
  constructor(container, config) {
    this.ui = new MainUI(this)
    this.viewport = new Viewport(this)
    // Orchestration logic only
  }
}

// components/MainUI.js
export class MainUI {
  createSVGContainer() { /* focused implementation */ }
}

// core/viewport.js  
export class Viewport {
  handleZoom(event) { /* focused implementation */ }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions