# Phase 0 — Baseline Metrics (02-coupling-refactoring) **Date**: 2026-05-10 **Mode**: Automatic (user-confirmed scope) **Goal**: Resolve remaining Medium architecture findings from `architecture_compliance_baseline.md`: 1. Route the two API endpoints `ServeTile` and `GetTileByLatLon` through `ITileService` (baseline F3). 2. Split `SatelliteProvider.Services` into per-component csprojs to add a compiler-enforced module boundary (baseline F4). ## Scope and Constraints - Behavior must be preserved across all changed paths (smoke + unit suite must stay green). - No database schema changes. - No public HTTP route changes — the same endpoints must accept the same request shapes and return the same response shapes. - C# namespaces will change for the moved classes. Tests and `Program.cs` will need their `using` statements updated. ## Current Code Topology | Project | LOC (.cs, excl. Migrations/bin/obj) | Files | |---------|-------------------------------------|-------| | SatelliteProvider.Api | 465 | 1 (Program.cs) | | SatelliteProvider.Common | 462 | DTOs, interfaces, configs, GeoUtils | | SatelliteProvider.DataAccess | 614 | Repositories, Models, Migrations | | SatelliteProvider.Services | 2130 | TileService, GoogleMapsDownloaderV2, RegionService + Processing + Queue, RouteService + Processing | | SatelliteProvider.Tests | 1070 | xUnit unit tests (35 tests, all passing) | | SatelliteProvider.IntegrationTests | 1434 | Console runner, 11 integration scenarios | `SatelliteProvider.Services` files (proposed split): | File | Logical Component | Proposed Project | |------|-------------------|------------------| | TileService.cs | TileDownloader | SatelliteProvider.Services.TileDownloader | | GoogleMapsDownloaderV2.cs | TileDownloader | SatelliteProvider.Services.TileDownloader | | RegionService.cs | RegionProcessing | SatelliteProvider.Services.RegionProcessing | | RegionProcessingService.cs | RegionProcessing | SatelliteProvider.Services.RegionProcessing | | RegionRequestQueue.cs | RegionProcessing | SatelliteProvider.Services.RegionProcessing | | RouteService.cs | RouteManagement | SatelliteProvider.Services.RouteManagement | | RouteProcessingService.cs | RouteManagement | SatelliteProvider.Services.RouteManagement | ## Test Coverage Baseline | Suite | Count | Status | Source | |-------|-------|--------|--------| | Unit tests | 35 | All passing | Step 7 run, 2026-05-10 | | Integration smoke | 5 scenarios | All passing in 111.86 s | Step 7 run, 2026-05-10 | | Integration full | 11 scenarios | Last verified before refactor | full mode preserved behind `--full` flag | Coverage measurement tooling (Coverlet) is not yet wired into the project. For this refactor, the existing pass rate of unit + smoke is the safety net; we'll re-run both at the end of every phase. ## Code Smell Baseline From `architecture_compliance_baseline.md`: | ID | Severity | Status | Action in this run | |----|----------|--------|--------------------| | F1 | High | Resolved (testability refactor) | None | | F2 | High | Resolved (testability refactor) | None | | F3 | Medium | Open | **Address in this run** | | F4 | Medium | Open | **Address in this run** | | F5 | Low | Open | Will be auto-corrected by F4 (module-layout doc rewrite) | No new architecture findings were added by Step 6 (Implement Tests) or Step 7 (Run Tests). ## Performance Baseline | Metric | Value | Source | |--------|-------|--------| | Smoke wall-clock | 111.86 s | Step 7 run | | Unit suite wall-clock | ~1.2 s | Docker `dotnet test` | | Build time (cold restore + build, all projects) | ~30 s | Docker `dotnet build` | Targets after refactor: no measurable regression in smoke or unit time. Build time may increase slightly (more csproj boundaries → more restore steps) but should stay <60 s cold. ## Dependencies No new package dependencies are required for either change. The split moves existing code into new csproj files. ## Functionality Inventory | Endpoint | Current Coupling Issue | Behavior Preserved? | |----------|------------------------|---------------------| | GET `/tiles/{z}/{x}/{y}` (`ServeTile`) | injects `ISatelliteDownloader` + `ITileRepository` + `IMemoryCache` | Yes — moves logic into TileService | | GET `/api/satellite/tiles/latlon` (`GetTileByLatLon`) | injects `ISatelliteDownloader` + `ITileRepository` | Yes — moves logic into TileService | | All other endpoints | Already route through services | Unchanged | ## Self-Verification - [x] RUN_DIR created (`_docs/04_refactoring/02-coupling-refactoring/`). - [x] Metrics measured for the categories that apply (coverage proxy via test count, code smells from baseline doc, performance from Step 7 run, build time from prior runs, deps from csproj files). - [x] Functionality inventory complete for the in-scope endpoints. - [x] Measurements reproducible: every count above can be recomputed by running `find ... | wc -l`, `dotnet test`, or reading the linked baseline doc. ## Goals (success criteria) 1. After the refactor, `Program.cs` has zero direct injections of `ISatelliteDownloader`, `ITileRepository`, or `IMemoryCache` for tile endpoints — they all flow through `ITileService`. 2. The seven Services files are physically split into three csprojs (`Services.TileDownloader`, `Services.RegionProcessing`, `Services.RouteManagement`) with explicit `ProjectReference` boundaries. 3. `SatelliteProvider.Services.csproj` is deleted (or renamed to a meta-package; deletion preferred). 4. Unit suite: 35/35 still passing. 5. Integration smoke suite: still passing in <120 s. 6. `architecture_compliance_baseline.md` (or a refreshed copy) shows F3 and F4 as **Resolved**. 7. `module-layout.md` is updated to reflect the new project layout (resolves F5 incidentally).