Repository navigation
build: domain modules and one app module per surface #286
Copy link
Copy link
Closed
Description
Parent: #52
Split the single flavored :app into domain library modules and one application module per surface, so CI stops doing the same work once per variant and each domain's public interface is enforced by the compiler.
Decision (Altay): domain modules + two apps. Full feature × surface slices (~30 modules) and a package-only reorg were rejected: the first is over-modularized at ~35k lines, the second gives no build gain.
Why
- Shared
src/maincompiles once per variant: six times inverify, about 12s each locally. - Shared unit tests and lint run once per surface, and
lintVitalruns once per release build. testEvidenceandtestEmulatorHarnessdeclare no inputs, so they rerun on every build.- Baseline at
3204b82,./gradlew verifyon an 18-core Mac after a one-line edit: TV-only 46s, mobile-only 53s, shared 76s. CI takes 9–21 min for code PRs. - Google's modularization patterns say: "If your app targets multiple device types … define an app module for each one."
Target
core/common core/design
domain/{files,playback,account,transfers,downloads,history,search,trash,auth}
mobile/ :mobile app, channel flavors, mobile UI in domain packages
tv/ :tv app, channel flavors, TV UI in domain packages
- Application ids, the
channelflavors, Kotlin packages and theMainActivityFQN stay as they are. - Domain types used by both apps become public; everything else stays
internal.
Slices
- Cache the script-backed verification tasks: build: skip unchanged script checks in verify #287
- Extract
core/*anddomain/*fromapp/src/main, with their tests and test fixtures;:appstays flavored: build: move shared code into core and domain library modules #289 - Stop running the lintVital analysis that
verifydiscards (about 126 task-seconds per build; found by the audit): build: stop running lintVital analysis that verify discards #290 - Replace
:appand itssurfaceflavor with the:mobileand:tvapplication modules; update the harness, CI and docs; turn detekt on for app code, with a baseline: build: split the app into mobile and tv application modules #291 (baseline burn-down: build: burn down the mobile and TV detekt baselines #292)
The interface tightening the audit turned up (state constructors, shared kernel, downloads placement) is tracked in #288.
Acceptance
./gradlew verifyand every debug assemble are green after each slice. The surface split keeps all application ids identical (aaptcheck).scripts/prove.sh mobileandscripts/prove.sh tvpass on the final layout.- Each PR records the before/after incremental
verifybenchmark. - AGENTS.md, README and docs/harness.md describe the new layout and task names.
Written by an agent (Claude Code, Opus 5.5)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
build: skip unchanged script checks in verify (#287)
build: move shared code into core and domain library modules (#289)
build: stop running lintVital analysis that verify discards (#290)
build: split the app into mobile and tv application modules (#291)
altaywtf commentedon Oct 3, 2026
Done.
main(eda2d2d) is now 11 library modules undercore/anddomain/, plus the:mobileand:tvapplication modules. Application ids, version names,MainActivityand Kotlin packages are unchanged.verifyused to compile the shared code six times and run 1,829 unit tests; it now compiles it twice and runs 1,336. The 493 shared tests now run once instead of once per surface, and each module's tests, lint and detekt are cached.verifyno longer spends about 126 task-seconds on lintVital analysis whose report AGP skipped anyway (build: stop running lintVital analysis that verify discards #290), or about 40 on unchanged script checks (build: skip unchanged script checks in verify #287).verifybuilds the TV instrumentation APK, and the icon check scans every module.Follow-ups: #288 (tighten the domain interfaces) and #292 (detekt baselines).
Written by an agent (Claude Code, Opus 5.5)
test: run Robolectric against the Gradle-resolved android-all jar
test: run Robolectric against the Gradle-resolved android-all jar (#295)