Architecture & Code Debt
Code structure, patterns, sync, and offline debt. Canonical architecture lives in Global architecture. Back to register.
Patterns (TD-12)
- The codebase historically ran two presentation patterns: Android MVI (
core-uiBaseViewModel+ per-feature Clean-Arch modules) and a lighter service-oriented MVVM inshared/(StateFlow + direct Ktor service calls). The mobile consolidation (migrations.md) retires the Android MVI side; the shared MVVM is now the single target pattern. - The rationale doc that would capture this (
docs/architecture/PATTERNS_AND_TRADEOFFS.md) was never written — only a draft plan exists: plan-patterns-and-tradeoffs.md (now annotated as partly superseded).
Target: document the shared-MVVM boundaries; decide whether to introduce a small shared MVI primitive (intent + reducer) only where complexity justifies it.
God-files / decomposition (TD-07)
Status as of 2026-06:
| File | LOC | Status |
|---|---|---|
shared/.../services/finance/FinanceService.kt | 162 (was 1015) | ✅ Done — extracted into 8 sub-services: FinanceTransactionService, FinanceAccountService, FinanceBudgetService, FinanceGoalService, FinanceProductService, FinanceReconcileService, FinanceScheduledTransactionService, FinancePredictionService. The original FinanceService is now a thin facade. |
shared/.../viewmodel/WorkoutViewModel.kt | 814 | ⬜ Open |
shared/.../viewmodel/RecipesViewModel.kt | 778 | ⬜ Open |
shared/.../services/work/WorkService.kt | 638 | ⬜ Open |
shared/.../viewmodel/StudyViewModel.kt | 581 | ⬜ Open |
shared/.../services/timers/TimerService.kt | 557 | ⬜ Open |
Pattern: Each sub-service takes (baseUrl, httpClient, tokenStorageImpl) in its constructor, same as the original. Callers continue using FinanceService — the facade delegates transparently.
Finance module follow-ups (TD-09)
Closed (see commit history under features/finance/): duplicate coroutine scope, ChangeTab stub, bogus budget if-else, unsafe ?: "" IDs, pagination bug. Remaining:
FinanceRepositoryImpldoRequestduplication → generic helper.- Custom exception types + error logging instead of generic failures.
- Input validation (amounts, date ranges, required fields, account existence).
- KDoc on public methods; ADRs for non-obvious decisions.
Sync design incomplete (TD-08)
sync-algorithm-design.md defines goals (multiplatform, conflict resolution, offline queue) but the “Sync Data Model” is explicitly “to be defined.” The Android Retrofit sync was removed; a shared Ktor-based design is intended but unfinished.
Target: finish the sync data model + conflict-resolution rules, or formally record that the app is network-only post-consolidation (decide alongside the offline question below).
Offline & SWR (TD-08, related)
Offline & sync describes a stale-while-revalidate, Room-backed offline-first UX with Firebase Remote Config data-policy modes. The mobile consolidation drops the Android Room/offline layer (network-only), so this doc and the shipped behavior have diverged. (Note: Wasm is not a shipped client.)
Target: reconcile architecture/offline-and-sync.md with the post-consolidation reality — either re-introduce a shared offline cache or document network-only as the decision.
Responsive breakpoints (TD-10)
OterWindowSize exists in shared/.../ui/util/OterWindowSize.kt with breakpoints Compact <600dp, Medium 600–840dp, Expanded >840dp. Most screens now use it (via OterWindowSizeProvider / LocalOterWindowSize). The following component files were migrated from direct BoxWithConstraints { maxWidth < 600.dp } to the shared helper in 2026-06: TransactionToolbar, TransactionGridView, FilterSidePanel, TaskGrid, ScheduledTransactionToolbar, ScheduledTransactionGridView, BudgetTrackerWrapper.
Remaining: Some screens still use ad-hoc maxWidth values for layout sizing (not breakpoint comparisons) — these are acceptable as they relate to specific component dimensions rather than responsive breakpoints.
Feature stubs (TD-11) — Done (2026-06)
Previously stubbed: Finance savings-goals & debts tabs now call loadSavingsGoals()/loadDebts() via FinanceService; Settings paywall button shows “coming soon” temporary text; GeneralMenuIconUtils docs are complete (icons fall back to base until theme-specific resources are added). All in-code TODOs removed.