Files
personal-portfolio/docs/project-lessons-learned/sprint-9-10-modular-callback-structure.md
lmiranda c9cf744d84 feat: Complete Phase 5 dashboard implementation
Implement full 5-tab Toronto Neighbourhood Dashboard with real data
connectivity:

Dashboard Structure:
- Overview tab with livability scores and rankings
- Housing tab with affordability metrics
- Safety tab with crime statistics
- Demographics tab with population/income data
- Amenities tab with parks, schools, transit

Figure Factories (portfolio_app/figures/):
- bar_charts.py: ranking, stacked, horizontal bars
- scatter.py: scatter plots, bubble charts
- radar.py: spider/radar charts
- demographics.py: donut, age pyramid, income distribution

Service Layer (portfolio_app/toronto/services/):
- neighbourhood_service.py: queries dbt marts for all tab data
- geometry_service.py: generates GeoJSON from PostGIS
- Graceful error handling when database unavailable

Callbacks (portfolio_app/pages/toronto/callbacks/):
- map_callbacks.py: choropleth updates, map click handling
- chart_callbacks.py: supporting chart updates
- selection_callbacks.py: dropdown handlers, KPI updates

Data Pipeline (scripts/data/):
- load_toronto_data.py: orchestration script with CLI flags

Lessons Learned:
- Graceful error handling in service layers
- Modular callback structure for multi-tab dashboards
- Figure factory pattern for reusable charts

Closes: #64, #65, #66, #67, #68, #69, #70

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 11:46:18 -05:00

1.6 KiB

Sprint 9-10 - Modular Callback Structure for Multi-Tab Dashboards

Context

Implementing a 5-tab Toronto Neighbourhood Dashboard with multiple callbacks per tab (map updates, chart updates, KPI updates, selection handling).

Problem

Initial callback implementation approach would have placed all callbacks in a single file, leading to:

  • A monolithic file with 500+ lines
  • Difficult-to-navigate code
  • Callbacks for different tabs interleaved
  • Testing difficulties

Solution

Organized callbacks into three focused modules:

callbacks/
├── __init__.py              # Imports all modules to register callbacks
├── map_callbacks.py         # Choropleth updates, map click handling
├── chart_callbacks.py       # Supporting chart updates (scatter, trend, donut)
└── selection_callbacks.py   # Dropdown population, KPI updates

Key patterns:

  1. Group by responsibility, not by tab - all map-related callbacks together
  2. Use noqa comments for imports that register callbacks as side effects
  3. Share helper functions (like _empty_chart()) within modules
# callbacks/__init__.py
from . import (
    chart_callbacks,  # noqa: F401
    map_callbacks,  # noqa: F401
    selection_callbacks,  # noqa: F401
)

Prevention

  • Plan callback organization before implementation - sketch which callbacks go where
  • Group by function, not by feature - keeps related logic together
  • Keep modules under 400 lines - split if exceeding
  • Test imports early - verify callbacks register correctly

Tags

dash, callbacks, architecture, python, code-organization, maintainability