Skip to content

Refactor: decompose the 644-line show() god-function into named stages #697

@timtreis

Description

@timtreis

Summary

PlotAccessor.show (src/spatialdata_plot/pl/basic.py:1250-1894, ~644 lines) is a god-function interleaving 8 distinct responsibilities with a doubly-nested render loop. Decomposing it into named stages would make each independently readable/testable and remove the reassigned-local-variable hazards that already produced two bugs.

The 8 interleaved responsibilities

  1. Arg validation / deprecation (~L1370–1448)
  2. Render-command extraction (~L1418–1441)
  3. Coordinate-system resolution (~L1462–1503)
  4. Panel-layout planning (~L1505–1538)
  5. Canvas / legend-param setup (~L1540–1575)
  6. Per-panel render dispatch loop (~L1669–1854, ~185 lines, 4 levels deep)
  7. Second-pass colorbar layout engine (~L1577–1878)
  8. Save / show / return (~L1880–1894)

No stage is independently testable; locals (ax, sdata, cs, coordinate_systems) are reassigned across stages — which is exactly what enabled the two bugs filed alongside this audit (leaked cs; per-command title block).

Suggested decomposition

Extract pure-ish stage helpers so show becomes a ~60-line orchestrator:

  • _collect_render_commands(plotting_tree)
  • _resolve_coordinate_systems(...)
  • _plan_panels(...)
  • _build_legend_params(...)
  • _render_panel(...) (the inner loop body)
  • _finalize_panel(ax, i, title, ...)
  • _layout_pending_colorbars(...) (note: _draw_colorbar is currently a ~90-line closure that captures only colorbar_params — promote to a module function taking it explicitly)

Also: the call to _validate_show_parameters passes 24 positional args (basic.py:1379) that must mirror the show signature exactly — switch to keyword args so a reorder can't silently misvalidate (e.g. dpi validated as fig).

Sequencing

Do this as mechanical, behavior-preserving extractions (one stage per commit), and after the two companion bug fixes land, so the extracted stages don't enshrine the bugs.

Risk / effort

Effort: high · Risk: medium — guard with the existing image baselines (CI). Also flatten the has_*/wants_* boolean sprawl in the dispatch loop (8 hand-threaded booleans) into a small dispatch table while restructuring.


Part of a maintainability/refactor audit of main.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions