This project is inspired by @EranBoudjnah 's book, Clean Architecture for Android and readaptation of ContactsComposeMultiplatform by philipplackner. It is a Kotlin Multi platform project written almost entirely in Kotlin.
It demonstrates the key principles presented in the book and how they apply to a real life project. I will endeavour to keep this project up to date and use it to demonstrate the strengths of the architecture: scalability, testability and flexibility when it comes to choosing 3rd party solutions.
- Feature separation
- Layer separation
- UI
- Presentation
- Domain
- Data
- Data Source
- Unit tests
- End-to-end tests
- Demonstrates use of Jetbrain's Compose Multiplatform
- Demonstrates use of Coroutines including Flow
- Demonstrates MVVM
- Code quality checks using ktlint
- Manual DI
- Database SqlDelight
- KMP Compose MultiPlatform (Android/Ios)
- Shared Viewmodel e.t.c
-
Mappers as Classes vs. Mapping Extension Functions
When mapping between models, we have several options. The primary decision is between mapper classes and mapping extension functions.
While extension functions are more concise, using them for mapping limits our choices of testing frameworks (Mockito, for example, cannot stub static functions).
How about injecting the mapper extension functions? We could do that. However, this removes the benefits of conciseness almost entirely. It also makes navigation to the implementation harder.
And so, I opted for the slightly more verbose concrete mapper classes.
-
Skipping Google's Architecture Components
The greatest issue with Google's Architecture Components is that they leak Android details into the Presentation layer. This prevents the Presentation layer from being truly UI agnostic.
Another issue with the Architecture Components is that they give too much responsibility to the ViewModel. They make it persist state it does not own, leading to potential data synchronization bugs.
For these reasons, while still following MVVM, this project relies on Kotlin Flows rather than LiveData, and implements pure ViewModels rather than Google's.
-
Mocking Framework
I used Mockito-Kotlin. I find the code easier to read and follow when using it.
-
Dependency Injection Framework
Decided to opt-in for Manual Dependency Injection because hilt only supports android for now and i found Koin a little bit complicated to setup and also requires many lines of code than necessary. Refer to (covpass-android) for a real world complete app using Manual DI
-
Navigation
I used Precompose. I find it lightweight and easy to use. It is also very similar to jetpack navigation, and it's multiplatform..
Clean Architecture for Android on Amazon