Conversation
added 6 commits
May 26, 2026 16:08
Move from package-level Clean Architecture to Gradle module boundaries so the dependency direction is enforced at build time: :app -> :domain, :app -> :data, :data -> :domain. Module ownership: - :domain (Kotlin/JVM) — models, repository contracts, use cases, Resource and DomainError. - :data (Android library + KSP) — Room, Retrofit, DTOs, repository implementation, technical exception mapping and the data-level Koin module (base URL inlined here). - :app — Compose UI, navigation, ViewModels, presentation mapping and the app-level Koin module. ChiApplication loads both modules. Tests follow ownership: use-case tests in :domain, mapper and repository tests in :data, DAO instrumented tests in :data androidTest, and ViewModel + Konsist architecture tests in :app. Also: libs.versions.toml gains kotlinx-coroutines-core, :app drops its direct Retrofit/OkHttp/Room/KSP dependencies, and .gitignore ignores module-level build/ directories.
Move TestJokes and FakeJokeRepository into :domain testFixtures so :data and :app tests consume them instead of carrying duplicates. Add JokeDtos and JokeEntities in :data testFixtures for mapper and repository tests, both derived from TestJokes.
Move from the legacy buildscript { classpath(...) } override to the
plugins DSL with version-catalog aliases:
- Drop the root buildscript block.
- Add alias(libs.plugins.kotlinJvm) apply false to the root plugins
block alongside composeCompiler and devToolsKsp.
- :domain applies via alias(libs.plugins.kotlinJvm) and drops its
redundant java { sourceCompatibility } block now that
kotlin.jvmToolchain(17) drives both Kotlin and Java compile targets.
The old setup pinned KGP 2.3.21 / KSP 2.3.7 (vs the older versions
bundled with AGP 9) by adding them as classpath() entries in the root
buildscript, which required mirroring them as library coordinates
(kotlin-gradle-plugin, ksp-gradle-plugin) in [libraries] just to feed
classpath().
Google has recommended the plugins DSL with apply false at the root
and alias() in submodules since AGP 7 / Android Studio Arctic Fox
(2021), and the gradle/libs.versions.toml catalog became the Android
Studio default around AGP 8 (Giraffe). The plugins block resolves
plugin marker artifacts directly, so declaring kotlinJvm there
enforces the same KGP 2.3.21 onto the build classpath without the
buildscript override or the library-coordinate mirrors. The two now-
unused library aliases are removed; resolved KGP and KSP versions
are unchanged.
…port boundary Each architecture rule now lives with the module it asserts about, so `./gradlew :domain:test` or `:data:test` independently verifies that module's invariants instead of leaning on :app to police everything. Redistribution: - :domain absorbs DomainLayerArchitectureTest and UseCaseArchitectureTest, plus the "no *Api in domain" and "any Repository interface lives in domain.repository" rules from the old RemoteApi / Repository suites. - :data absorbs DataLayerArchitectureTest, plus "Api interfaces live in data.remote", "Retrofit annotations stay confined to data.remote", "RepositoryImpl lives in data.repository", and "RepositoryImpl implements a domain.repository contract". - :app keeps ProjectArchitectureTest and gains AppLayerArchitectureTest with two rules: only ChiApplication and com.compose.chi.di may import com.compose.chi.data.* (presentation, navigation, theme and analytics must go through :domain), and :app must not reference retrofit2 anywhere (broadened from the previous presentation-only guard). :domain and :data gain testImplementation(libs.konsist) so the suites can run there. Konsist.scopeFromProject() still walks the whole project tree, so path / package matchers keep working from any module. 26 architecture test methods before, 26 after: every rule preserved, two strengthened. The redundant RemoteApi and Repository test classes in :app are deleted; their assertions live with their owners.
Three small follow-ups to the modularization work: - Extract BASE_URL_JOKES into data/remote/NetworkConfig.kt (internal) so DI stays focused on wiring. - Rename OfficialJokeApi.kt to JokeApi.kt to match the interface it declares. - Align :app namespace and applicationId from com.example.chi to com.compose.chi to match where the code lives.
Update documentation after the three-module split. - Refresh README architecture, project structure, testing, roadmap, and checklist sections - Add modularization documentation covering module ownership, dependency direction, DI split, test fixtures, and architecture guardrails - Update testing documentation to reflect the new :domain, :data, and :app test layout - Update changelog with the Phase 5 modularization summary - Clarify that :app depends on :data only as the Android composition root, while presentation code depends on domain abstractions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.