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.
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:
NigigMapView- Thin widget wrapper (UI only)NigigMapController- State managementNigigMapRenderer- Rendering logicNigigMapNetwork- 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.rs→parser.rs+validator.rs+compiler.rsgeometry.rs→types.rs+projections.rs+tessellation.rs+transforms.rslabel.rs→extraction.rs+placement.rs+rendering.rs
4.3 Circular Dependencies
Problem: Circular dependencies make the codebase hard to understand, test, and refactor.
Examples:
- view.rs ↔ cache.rs (via tile.rs)
- scheduler.rs ↔ cache.rs (via TileAction)
- renderer.rs ↔ render_graph.rs (via RenderContext)
Impact:
- Cannot test modules independently
- Hard to understand data flow
- Hard to refactor
Recommendation: Break circular dependencies:
- Extract
TileActionenum to separate module - Use dependency injection for TileCache
- Use trait objects for RenderPass
4.4 Unclear Module Boundaries
Problem: Module boundaries are unclear, with overlapping responsibilities.
Examples:
geometry.rsvstessellation.rs- Both do geometry operationslabel.rsvslabel_state.rs- Both manage labelscache.rsvsscheduler.rs- Both manage tile statestyle.rsvsstyle_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 operationstessellation.rs- Converting vector data to triangleslabel.rs- Label extraction from tileslabel_state.rs- Label placement and collision detectioncache.rs- Tile storage and evictionscheduler.rs- Tile request schedulingstyle.rs- Style compilation and applicationstyle_json.rs- JSON style parsing
5. Recommendations
5.1 Immediate Actions (Phase 1)
- Document current architecture (this document)
- Identify critical bugs (see CRITICAL_BUGS.md)
- Create performance baseline (see PERFORMANCE_BASELINE.md)
- Prioritize fixes (see EXECUTION_PLAN.md)
5.2 Short-term Actions (Phase 2)
- Split NigigMapView into Controller + Renderer + Network
- Break circular dependencies by extracting shared types
- Split large files (style_json.rs, geometry.rs, label.rs)
- Clarify module boundaries with documentation
5.3 Long-term Actions (Phase 3+)
- Flatten dependency graph to maximum 3 levels
- Add architectural tests to prevent regressions
- Create architecture decision records (ADRs)
- Regular architecture reviews (quarterly)
6. Conclusion
The Makepad map codebase has a complex architecture with several critical 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 with overlapping responsibilities
However, the architecture is salvageable with systematic refactoring:
- Split god objects into smaller components
- Break circular dependencies
- Split large files
- 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