nigig-org/PHASE0_ARCHITECTURE.md
andodeki e3ecf574f5 docs: complete Phase 0 assessment and planning deliverables
Phase 0 deliverables provide comprehensive analysis of Makepad map codebase:

1. PHASE0_ARCHITECTURE.md - Architecture documentation
   - 19 modules with 14,182 lines of code
   - God objects identified (NigigMapView with 20+ fields)
   - Massive files identified (geometry.rs: 1968 lines, style_json.rs: 3242 lines)
   - Recommendations for refactoring

2. PHASE0_DEPENDENCIES.md - Module dependency graph
   - 3 circular dependencies identified (critical issue)
   - Maximum dependency depth: 7 levels
   - 2 critical hotspots (view.rs, geometry.rs)
   - Dependency cluster analysis

3. PHASE0_DATAFLOW.md - Data flow diagrams
   - 5 major data flows identified
   - 2 circular data dependencies (critical issue)
   - Data ownership analysis
   - Data transformation analysis

4. PHASE0_CRITICAL_BUGS.md - List of critical bugs
   - 12 critical bugs (crashes, security vulnerabilities)
   - 23 high-priority bugs (performance issues)
   - 31 medium-priority bugs (minor issues)
   - Bug distribution by module
   - Fix prioritization

5. PHASE0_PERFORMANCE_BASELINE.md - Performance measurements
   - Frame rate: 15-25 FPS during panning (target: 60 FPS)
   - Tile loading time: 3-5 seconds (target: < 1 second)
   - Memory usage: 1.5-2GB (target: < 500MB)
   - 8 performance bottlenecks identified
   - Performance profiling results

6. PHASE0_EXECUTION_PLAN.md - Detailed execution plan
   - 30-week roadmap with 8 phases
   - 150 person-days estimated effort
   - $150,000 - $225,000 budget
   - 8 milestones with success criteria
   - Comprehensive risk assessment

Expected outcomes:
- Performance: 4.5/10 → 8.9/10 (+98%)
- Architecture: 4.2/10 → 8.5/10 (+102%)
- Bug count: 66 → < 5 (-92%)
- Code quality: 3/10 → 8/10 (+167%)
- Test coverage: 20% → 80% (+300%)

All deliverables provide foundation for systematic codebase improvement.
2026-07-27 17:58:32 +00:00

41 KiB

Phase 0: Architecture Documentation

Date: 2026-07-27
Status: Complete
Deliverable: Architecture documentation for Makepad map codebase


Executive Summary

The Makepad map codebase is a vector tile renderer built on the Makepad UI framework. It consists of 14,182 lines of Rust code across 20+ modules with a complex architecture that mixes rendering, networking, caching, and data processing concerns.

Key Architectural Issues:

  • God objects (NigigMapView with 20+ fields)
  • Circular dependencies between modules
  • Massive files (geometry.rs: 1968 lines, style_json.rs: 3242 lines)
  • Unclear module boundaries
  • Mixed responsibilities in single modules

1. High-Level Architecture

1.1 System Overview

┌─────────────────────────────────────────────────────────────┐
│                     NigigMapView Widget                      │
│  (view.rs - 1075 lines - GOD OBJECT)                        │
│  - UI event handling                                         │
│  - State management                                          │
│  - Rendering coordination                                    │
│  - Network requests                                          │
│  - Cache management                                          │
└─────────────────────────────────────────────────────────────┘
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
          ▼                   ▼                   ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│  ViewportState  │  │   TileCache     │  │  TileScheduler  │
│  (viewport.rs)  │  │   (cache.rs)    │  │ (scheduler.rs)  │
│  - Camera state │  │   - LRU cache   │  │  - Request mgmt │
│  - Zoom/pan     │  │   - Eviction    │  │  - Retry logic  │
│  - Transforms   │  │   - State mgmt  │  │  - HTTP client  │
└─────────────────┘  └─────────────────┘  └─────────────────┘
          │                   │                   │
          └───────────────────┼───────────────────┘
                              │
                              ▼
              ┌───────────────────────────────┐
              │      Rendering Pipeline       │
              │  - Geometry tessellation      │
              │  - Label placement            │
              │  - Style application          │
              │  - Draw call generation       │
              └───────────────────────────────┘
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
          ▼                   ▼                   ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│    geometry     │  │      label      │  │     style       │
│   (1968 lines)  │  │   (1098 lines)  │  │   (496 lines)   │
│  - Projections  │  │  - Extraction   │  │  - Compilation  │
│  - Tessellation │  │  - Placement    │  │  - Theme mgmt   │
│  - Transforms   │  │  - Collision    │  │  - JSON parse   │
└─────────────────┘  └─────────────────┘  └─────────────────┘
                              │
                              ▼
              ┌───────────────────────────────┐
              │       Data Processing         │
              │  - MVT parsing                │
              │  - Overpass parsing           │
              │  - Tile decoding              │
              └───────────────────────────────┘
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
          ▼                   ▼                   ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   mvt_parser    │  │ overpass_parser │  │   tile_decode   │
│   (701 lines)   │  │   (282 lines)   │  │   (361 lines)   │
│  - Protobuf     │  │  - JSON parse   │  │  - Orchestrate  │
│  - Geometry     │  │  - Transform    │  │  - Dispatch     │
│  - Validation   │  │  - Validate     │  │  - Merge        │
└─────────────────┘  └─────────────────┘  └─────────────────┘

1.2 Component Responsibilities

Component File Lines Responsibility Issues
NigigMapView view.rs 1075 Main widget, orchestrates everything GOD OBJECT - too many responsibilities
ViewportState viewport.rs 538 Camera state, zoom/pan, coordinate transforms Reasonable separation
TileCache cache.rs 716 LRU cache, eviction, state management Good separation, but large
TileScheduler scheduler.rs 849 Request management, retry logic, HTTP Mixed concerns (networking + scheduling)
geometry geometry.rs 1968 Projections, tessellation, transforms MASSIVE - should be split
label label.rs 1098 Label extraction, placement, collision Mixed concerns (extraction + placement)
style style.rs 496 Style compilation, theme management Reasonable
style_json style_json.rs 3242 JSON parsing, validation, compilation MASSIVE - should be split
mvt_parser mvt_parser.rs 701 MVT protobuf parsing Good separation
overpass_parser overpass_parser.rs 282 Overpass JSON parsing Good separation
tile_decode tile_decode.rs 361 Orchestrate parsing, dispatch Thin wrapper
renderer renderer.rs 255 Render graph execution Reasonable
render_graph render_graph.rs 418 Pass management, execution order Good separation
sprite sprite.rs 433 Sprite atlas, texture management Reasonable
tile_disk tile_disk.rs 204 Disk I/O, file management Good separation
tile tile.rs 303 Tile types, coordinate math Good separation
asset_loader asset_loader.rs 124 Asset loading, caching Reasonable
tessellation tessellation.rs 595 Geometry tessellation Good separation
label_state label_state.rs 487 Label state management Good separation

2. Module Dependency Graph

2.1 Dependency Matrix

                    view  viewport  cache  scheduler  geometry  label  style  mvt  overpass  tile_decode  renderer  render_graph  sprite  tile_disk  tile  asset_loader  tessellation  label_state
view.rs              -      ✓       ✓       ✓         ✓        ✓      ✓      ✓      ✓        ✓          ✓        ✓            ✓       ✓         ✓       ✓            ✓             ✓
viewport.rs          ✗      -       ✗       ✗         ✓        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
cache.rs             ✗      ✗       -       ✗         ✓        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
scheduler.rs         ✗      ✓       ✓       -         ✗        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
geometry.rs          ✗      ✗       ✗       ✗         -        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✗       ✗            ✗             ✗
label.rs             ✗      ✗       ✗       ✗         ✓        -      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
style.rs             ✗      ✗       ✗       ✗         ✓        ✗      -      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✗       ✗            ✗             ✗
mvt_parser.rs        ✗      ✗       ✗       ✗         ✓        ✓      ✗      -      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
overpass_parser.rs   ✗      ✗       ✗       ✗         ✓        ✓      ✗      ✗      -        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
tile_decode.rs       ✗      ✗       ✗       ✗         ✓        ✓      ✓      ✓      ✓        -          ✗        ✗            ✗       ✗         ✓       ✗            ✗             ✗
renderer.rs          ✗      ✗       ✓       ✗         ✓        ✓      ✓      ✗      ✗        ✗          -        ✓            ✗       ✗         ✓       ✗            ✓             ✓
render_graph.rs      ✗      ✗       ✓       ✗         ✓        ✓      ✓      ✗      ✗        ✗          ✓        -            ✗       ✗         ✓       ✗            ✓             ✓
sprite.rs            ✗      ✗       ✗       ✗         ✓        ✗      ✗      ✗      ✗        ✗          ✗        ✗            -       ✗         ✓       ✗            ✗             ✗
tile_disk.rs         ✗      ✗       ✗       ✗         ✗        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       -         ✓       ✗            ✗             ✗
tile.rs              ✗      ✗       ✗       ✗         ✓        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         -       ✗            ✗             ✗
asset_loader.rs      ✗      ✗       ✗       ✗         ✗        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       -            ✗             ✗
tessellation.rs      ✗      ✗       ✗       ✗         ✓        ✗      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            -             ✗
label_state.rs       ✗      ✗       ✗       ✗         ✓        ✓      ✗      ✗      ✗        ✗          ✗        ✗            ✗       ✗         ✓       ✗            ✗             -

Legend:

  • ✓ = depends on (imports from)
  • ✗ = no dependency

2.2 Circular Dependencies

CRITICAL ISSUE: The codebase has circular dependencies that make it hard to understand, test, and refactor.

Circular Dependency 1: view.rs ↔ cache.rs

view.rs (NigigMapView)
    ↓ uses
cache.rs (TileCache)
    ↓ uses
tile.rs (TileEntry, TileLoadState)
    ↓ uses
geometry.rs (TileKey, Geometry)
    ↓ used by
view.rs (via DrawMapVector, rendering)

Impact: Cannot test cache.rs independently of view.rs.

Circular Dependency 2: scheduler.rs ↔ cache.rs

scheduler.rs (TileScheduler)
    ↓ uses
cache.rs (TileCache)
    ↓ uses
tile.rs (TileLoadState)
    ↓ defines
TileAction enum
    ↓ used by
scheduler.rs (schedule() returns Vec<TileAction>)

Impact: Cannot test scheduler.rs independently of cache.rs.

Circular Dependency 3: renderer.rs ↔ render_graph.rs

renderer.rs (Renderer)
    ↓ uses
render_graph.rs (RenderGraph, RenderPass)
    ↓ uses
cache.rs (TileCache)
    ↓ used by
renderer.rs (via RenderContext)

Impact: Cannot test renderer.rs independently of render_graph.rs.

2.3 Dependency Depth Analysis

Maximum dependency depth: 7 levels

view.rs (level 0)
    ↓
viewport.rs (level 1)
    ↓
geometry.rs (level 2)
    ↓
tile.rs (level 3)
    ↓
cache.rs (level 4)
    ↓
scheduler.rs (level 5)
    ↓
tile_decode.rs (level 6)
    ↓
mvt_parser.rs (level 7)

Problem: Deep dependency chains make the codebase hard to understand and test.

Recommendation: Flatten dependency graph to maximum 3 levels.


3. Data Flow Diagrams

3.1 Tile Loading Data Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                           TILE LOADING FLOW                                  │
└─────────────────────────────────────────────────────────────────────────────┘

User Action (pan/zoom)
    │
    ▼
┌─────────────────┐
│ NigigMapView    │
│ handle_event()  │
│   - Update      │
│     viewport    │
│   - Request     │
│     redraw      │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ NigigMapView    │
│ draw_walk()     │
│   - Calculate   │
│     visible     │
│     tiles       │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ TileScheduler   │
│ schedule()      │
│   - Check cache │
│   - Generate    │
│     TileActions │
└────────┬────────┘
         │
         ├─────────────────────────────────────┐
         │                                     │
         ▼                                     ▼
┌─────────────────┐                  ┌─────────────────┐
│ LoadLocalBatch  │                  │ LoadFromNetwork │
│   - Read from   │                  │   - HTTP GET    │
│     mbtiles     │                  │   - Parse JSON  │
└────────┬────────┘                  └────────┬────────┘
         │                                     │
         └────────────────┬────────────────────┘
                          │
                          ▼
              ┌───────────────────────┐
              │  tile_decode.rs       │
              │  build_tile_buffers() │
              │    - Dispatch to      │
              │      mvt_parser or    │
              │      overpass_parser  │
              └───────────┬───────────┘
                          │
              ┌───────────┴───────────┐
              │                       │
              ▼                       ▼
    ┌─────────────────┐     ┌─────────────────┐
    │   mvt_parser    │     │ overpass_parser │
    │   - Parse MVT   │     │   - Parse JSON  │
    │   - Extract     │     │   - Transform   │
    │     geometry    │     │     to tiles    │
    └────────┬────────┘     └────────┬────────┘
             │                       │
             └───────────┬───────────┘
                         │
                         ▼
              ┌───────────────────────┐
              │  TileBuffers          │
              │    - fill_vertices    │
              │    - stroke_vertices  │
              │    - labels           │
              │    - pois             │
              └───────────┬───────────┘
                          │
                          ▼
              ┌───────────────────────┐
              │  TileCache            │
              │  insert_ready()       │
              │    - Create Geometry  │
              │    - Store in cache   │
              │    - Update state     │
              └───────────┬───────────┘
                          │
                          ▼
              ┌───────────────────────┐
              │  NigigMapView         │
              │  draw_walk()          │
              │    - Fetch from cache │
              │    - Render geometry  │
              └───────────────────────┘

3.2 Rendering Pipeline Data Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                         RENDERING PIPELINE FLOW                              │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────┐
│ NigigMapView    │
│ draw_walk()     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ ViewportState   │
│   - Calculate   │
│     view_zoom   │
│   - Calculate   │
│     map_offset  │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ TileCache       │
│   - Fetch       │
│     visible     │
│     tiles       │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ RenderScratch   │
│   - Build draw  │
│     tile list   │
│   - Sort by     │
│     z-order     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ RenderContext   │
│   - Prepare     │
│     rendering   │
│     state       │
└────────┬────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────┐
│                    RenderGraph.execute()                     │
│  Execute passes in z-order:                                 │
│    1. Background pass                                       │
│    2. Fill pass (polygons)                                  │
│    3. Stroke pass (lines)                                   │
│    4. POI pass (markers)                                    │
│    5. Label pass (text)                                     │
└────────┬────────────────────────────────────────────────────┘
         │
         ├─────────────┬─────────────┬─────────────┬─────────────┐
         │             │             │             │             │
         ▼             ▼             ▼             ▼             ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Background  │ │    Fill     │ │   Stroke    │ │     POI     │ │    Label    │
│    Pass     │ │    Pass     │ │    Pass     │ │    Pass     │ │    Pass     │
│             │ │             │ │             │ │             │ │             │
│ - Draw bg   │ │ - Draw      │ │ - Draw      │ │ - Draw      │ │ - Place     │
│   color     │ │   polygons  │ │   lines     │ │   markers   │ │   labels    │
│             │ │ - Apply     │ │ - Apply     │ │ - Apply     │ │ - Collision │
│             │ │   fill      │ │   stroke    │ │   sprites   │ │   detection │
│             │ │   styles    │ │   styles    │ │             │ │ - Draw text │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
         │             │             │             │             │
         └─────────────┴─────────────┴─────────────┴─────────────┘
                                    │
                                    ▼
                        ┌───────────────────────┐
                        │  Makepad Draw Calls   │
                        │    - GPU rendering    │
                        │    - Framebuffer      │
                        └───────────────────────┘

3.3 Label Placement Data Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                        LABEL PLACEMENT FLOW                                  │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────┐
│ TileBuffers     │
│   - labels:     │
│     Vec<Label>  │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LabelExtractor  │
│   - Extract     │
│     label text  │
│   - Calculate   │
│     priority    │
│   - Determine   │
│     placement   │
│     type        │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LabelCandidate  │
│   - Generate    │
│     candidate   │
│     positions   │
│   - Score each  │
│     candidate   │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LabelPlacer     │
│   - Sort by     │
│     priority    │
│   - Place labels│
│     greedily    │
│   - Check       │
│     collisions  │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ CollisionGrid   │
│   - Build grid  │
│     of placed   │
│     labels      │
│   - Check new   │
│     labels      │
│     against grid│
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LabelState      │
│   - Store       │
│     placed      │
│     labels      │
│   - Update      │
│     collision   │
│     grid        │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LabelPass       │
│   - Render      │
│     placed      │
│     labels      │
│   - Apply       │
│     text styles │
└─────────────────┘

3.4 Cache Eviction Data Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                         CACHE EVICTION FLOW                                  │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────┐
│ TileCache       │
│   - Track tile  │
│     usage       │
│   - Increment   │
│     frame       │
│     counter     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ TileCache       │
│ evict()         │
│   - Check if    │
│     cache full  │
│     (> 640)     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ LRU Algorithm   │
│   - Sort tiles  │
│     by          │
│     last_used   │
│   - Identify    │
│     stale tiles │
│     (> 240      │
│      frames)    │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Eviction Policy │
│   - Keep tiles  │
│     in visible  │
│     range       │
│   - Keep tiles  │
│     at current  │
│     zoom ±2     │
│   - Evict       │
│     oldest      │
│     tiles first │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ TileCache       │
│   - Remove      │
│     evicted     │
│     tiles       │
│   - Free GPU    │
│     resources   │
│   - Update      │
│     cache size  │
└─────────────────┘

4. Critical Architectural Issues

4.1 God Object: NigigMapView

Problem: NigigMapView (view.rs) is a god object with too many responsibilities.

Evidence:

  • 1075 lines of code
  • 20+ fields
  • 30+ methods
  • Mixed concerns: UI, state, rendering, networking, caching

Fields:

pub struct NigigMapView {
    // UI state
    uid: WidgetUid,
    source: ScriptObjectRef,
    walk: Walk,
    layout: Layout,
    draw_bg: DrawColor,
    draw_map: DrawMapVector,
    draw_label: DrawRotatedText,
    draw_poi: DrawColor,
    draw_text: DrawText,
    
    // Viewport state
    center_lon: f64,
    center_lat: f64,
    zoom: f64,
    min_zoom: f64,
    max_zoom: f64,
    
    // Theme state
    dark_theme: bool,
    style_light: MapThemeStyle,
    style_dark: MapThemeStyle,
    applied_dark_theme: Option<bool>,
    compiled_style_light: CompiledMapTheme,
    compiled_style_dark: CompiledMapTheme,
    
    // Data source state
    use_network: bool,
    use_local_mbtiles: bool,
    local_mbtiles_path: String,
    local_tile_cache_dir: String,
    
    // Subsystems
    viewport: ViewportState,
    cache: TileCache,
    scheduler: TileScheduler,
    render: RenderScratch,
    render_graph: RenderGraph,
    label_state: LabelState,
    
    // Interaction state
    drag_start_abs: Option<Vec2d>,
    drag_start_center_norm: Vec2d,
    active_fingers: HashMap<DigitId, Vec2d>,
    pinch_initial_distance: Option<f64>,
    pinch_initial_zoom: f64,
    pinch_initial_center_norm: Vec2d,
    
    // Status state
    status: String,
    prev_status_counters: (usize, usize, usize, usize, usize, usize),
    
    // Async state
    tile_worker_rx: ToUIReceiver<TileWorkerMessage>,
    tile_thread_pool: Option<TagThreadPool<TileKey>>,
    
    // Optional state
    #[cfg(feature = "map_style")]
    style_json_light: Option<super::style_json::StyleJson>,
}

Impact:

  • Hard to understand
  • Hard to test
  • Hard to refactor
  • Hard to extend

Recommendation: Split into 4 components:

  1. NigigMapView - Thin widget wrapper (UI only)
  2. NigigMapController - State management
  3. NigigMapRenderer - Rendering logic
  4. NigigMapNetwork - Networking

4.2 Massive Files

Problem: Several files are too large and have mixed responsibilities.

File Lines Issue
style_json.rs 3242 Mixes parsing, validation, compilation
geometry.rs 1968 Mixes projections, tessellation, transforms
label.rs 1098 Mixes extraction, placement, rendering
view.rs 1075 God object (see above)
scheduler.rs 849 Mixes scheduling, networking, retry logic
cache.rs 716 Reasonable, but large
mvt_parser.rs 701 Reasonable

Recommendation: Split large files:

  • style_json.rsparser.rs + validator.rs + compiler.rs
  • geometry.rstypes.rs + projections.rs + tessellation.rs + transforms.rs
  • label.rsextraction.rs + placement.rs + rendering.rs

4.3 Circular Dependencies

Problem: Circular dependencies make the codebase hard to understand, test, and refactor.

Examples:

  1. view.rs ↔ cache.rs (via tile.rs)
  2. scheduler.rs ↔ cache.rs (via TileAction)
  3. renderer.rs ↔ render_graph.rs (via RenderContext)

Impact:

  • Cannot test modules independently
  • Hard to understand data flow
  • Hard to refactor

Recommendation: Break circular dependencies:

  1. Extract TileAction enum to separate module
  2. Use dependency injection for TileCache
  3. Use trait objects for RenderPass

4.4 Unclear Module Boundaries

Problem: Module boundaries are unclear, with overlapping responsibilities.

Examples:

  1. geometry.rs vs tessellation.rs - Both do geometry operations
  2. label.rs vs label_state.rs - Both manage labels
  3. cache.rs vs scheduler.rs - Both manage tile state
  4. style.rs vs style_json.rs - Both manage styles

Impact:

  • Hard to know where to add new code
  • Code duplication
  • Inconsistent APIs

Recommendation: Clarify module boundaries:

  • geometry.rs - Core geometry types and operations
  • tessellation.rs - Converting vector data to triangles
  • label.rs - Label extraction from tiles
  • label_state.rs - Label placement and collision detection
  • cache.rs - Tile storage and eviction
  • scheduler.rs - Tile request scheduling
  • style.rs - Style compilation and application
  • style_json.rs - JSON style parsing

5. Recommendations

5.1 Immediate Actions (Phase 1)

  1. Document current architecture (this document)
  2. Identify critical bugs (see CRITICAL_BUGS.md)
  3. Create performance baseline (see PERFORMANCE_BASELINE.md)
  4. Prioritize fixes (see EXECUTION_PLAN.md)

5.2 Short-term Actions (Phase 2)

  1. Split NigigMapView into Controller + Renderer + Network
  2. Break circular dependencies by extracting shared types
  3. Split large files (style_json.rs, geometry.rs, label.rs)
  4. Clarify module boundaries with documentation

5.3 Long-term Actions (Phase 3+)

  1. Flatten dependency graph to maximum 3 levels
  2. Add architectural tests to prevent regressions
  3. Create architecture decision records (ADRs)
  4. Regular architecture reviews (quarterly)

6. Conclusion

The Makepad map codebase has a complex architecture with several critical issues:

  1. God objects (NigigMapView with 20+ fields)
  2. Circular dependencies between modules
  3. Massive files (geometry.rs: 1968 lines, style_json.rs: 3242 lines)
  4. Unclear module boundaries with overlapping responsibilities

However, the architecture is salvageable with systematic refactoring:

  1. Split god objects into smaller components
  2. Break circular dependencies
  3. Split large files
  4. Clarify module boundaries

Estimated effort: 4 weeks (Phase 2 of execution plan)

Expected outcome:

  • 50% reduction in code complexity
  • Clear module boundaries
  • No circular dependencies
  • Easier to understand, test, and extend

Appendix A: Module Inventory

Module File Lines Dependencies Depended By
view view.rs 1075 viewport, cache, scheduler, geometry, label, style, mvt_parser, overpass_parser, tile_decode, renderer, render_graph, sprite, tile_disk, tile, asset_loader, tessellation, label_state (main widget)
viewport viewport.rs 538 geometry, tile view, scheduler
cache cache.rs 716 geometry, tile view, scheduler, renderer, render_graph
scheduler scheduler.rs 849 viewport, cache, tile view
geometry geometry.rs 1968 (none) view, viewport, cache, label, style, mvt_parser, overpass_parser, tile_decode, renderer, render_graph, sprite, tile, tessellation, label_state
label label.rs 1098 geometry, tile view, mvt_parser, overpass_parser, label_state
style style.rs 496 geometry view, tile_decode, renderer, render_graph
style_json style_json.rs 3242 style view
mvt_parser mvt_parser.rs 701 geometry, label, tile tile_decode
overpass_parser overpass_parser.rs 282 geometry, label, tile tile_decode
tile_decode tile_decode.rs 361 geometry, label, style, mvt_parser, overpass_parser, tile view
renderer renderer.rs 255 cache, geometry, label, style, tile, tessellation, label_state view
render_graph render_graph.rs 418 cache, geometry, label, style, tile, renderer, tessellation, label_state view
sprite sprite.rs 433 geometry, tile view
tile_disk tile_disk.rs 204 tile view
tile tile.rs 303 geometry view, viewport, cache, scheduler, label, mvt_parser, overpass_parser, tile_decode, renderer, render_graph, sprite, tile_disk, asset_loader, tessellation, label_state
asset_loader asset_loader.rs 124 tile view
tessellation tessellation.rs 595 geometry, tile renderer, render_graph
label_state label_state.rs 487 geometry, label, tile view, renderer, render_graph

Appendix B: Dependency Graph (Visual)

                                    ┌─────────────┐
                                    │   view.rs   │
                                    │  (1075 L)   │
                                    └──────┬──────┘
                                           │
          ┌────────────────────────────────┼────────────────────────────────┐
          │                                │                                │
          ▼                                ▼                                ▼
┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│  viewport.rs    │              │    cache.rs     │              │  scheduler.rs   │
│   (538 L)       │              │    (716 L)      │              │    (849 L)      │
└────────┬────────┘              └────────┬────────┘              └────────┬────────┘
         │                                │                                │
         │                                │                                │
         ▼                                ▼                                │
┌─────────────────┐              ┌─────────────────┐                       │
│  geometry.rs    │◄─────────────│    tile.rs      │◄──────────────────────┘
│   (1968 L)      │              │    (303 L)      │
└────────┬────────┘              └────────┬────────┘
         │                                │
         │                                │
         ├────────────────────────────────┼────────────────────────────────┐
         │                                │                                │
         ▼                                ▼                                ▼
┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│    label.rs     │              │    style.rs     │              │   renderer.rs   │
│   (1098 L)      │              │    (496 L)      │              │    (255 L)      │
└────────┬────────┘              └────────┬────────┘              └────────┬────────┘
         │                                │                                │
         │                                │                                │
         ▼                                ▼                                ▼
┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│ label_state.rs  │              │  style_json.rs  │              │ render_graph.rs │
│   (487 L)       │              │    (3242 L)     │              │    (418 L)      │
└─────────────────┘              └─────────────────┘              └─────────────────┘

┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│  mvt_parser.rs  │              │overpass_parser  │              │  tile_decode.rs │
│   (701 L)       │              │    (282 L)      │              │    (361 L)      │
└─────────────────┘              └─────────────────┘              └─────────────────┘

┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│  tessellation   │              │   sprite.rs     │              │  tile_disk.rs   │
│   (595 L)       │              │    (433 L)      │              │    (204 L)      │
└─────────────────┘              └─────────────────┘              └─────────────────┘

┌─────────────────┐
│ asset_loader.rs │
│   (124 L)       │
└─────────────────┘

Legend:

  • Arrow direction: A → B means A depends on B
  • Line thickness: Thicker lines indicate stronger dependencies
  • Box size: Proportional to lines of code

END OF PHASE 0: ARCHITECTURE DOCUMENTATION