Note
Work in progress... The project is going to rebuild OpenMovieDB using Clean Architecture, Kotlin Coroutines and JetPack Compose.
Project demonstrates how to
build domain driven clean architecture using Android MVVM approach.
Overall, the application architecture provides a solid foundation for building a clean and maintainable code. It emphasizes the importance of separating concerns, isolating the core business logic, and making the code testable and reusable.
- This is a core principle of clean architecture. The domain layer encapsulates the core business rules and logic, independent of any external frameworks or technologies. This makes it easier to test and maintain.
- The absence of external dependencies in the domain layer makes it easier to write unit tests that quickly and reliably verify the correctness of the business logic.
- The data layer provides and manages data, acting as a single source of truth. This ensures data consistency and unidirectional data flow.
- The app layer primarily focus on presenting data to the user and passing events to the data layer. It also observes data streams to update the UI as needed. This separation of concerns helps to keep the app layer clean and focused.
- Each layer and class has a well-defined purpose and structure. Data layer only provides data, domain layer applies data transformations and app layer only displays data. This makes the code easier to understand, maintain, and extend.
- The single responsibility principle is applied to each class, meaning that a class has only one reason to change. This helps to keep classes focused and manageable. For example, view only displays data, view-model only keeps UI state and so on.
- The dependency inversion principle ensures that the domain layer does not depend on the data or app layer, but rather the other layers depend on the domain layer. This makes the code more flexible and testable.
As the Kover report indicates, all the business logic is encapsulated inside domain use cases and fully covered with unit tests.
Application contains three modules:
- app - Android module with UI and framework dependencies, e.g. JetPack Compose to display views
- data - Android module with data dependencies, e.g. Retrofit to get data from the remote API
- domain - pure Java/Kotlin module without any external dependencies
graph TD
subgraph APP[App module]
direction LR
subgraph AppDependencies[Dependencies]
direction TB
AndroidDependencies(Android Dependencies):::red
UiDependencies(Ui Dependencies):::red
end
subgraph AppTests[Tests]
direction TB
AppUnitTests(Unit Tests):::green
IntegrationTests(Integration Tests):::green
E2ETests(End-To-End Tests):::green
end
subgraph AppClasses[Classes]
direction TB
Views(Views)
ViewModels(View-Models)
UiModels(Ui Models)
DI(Dependencies Injections)
Android(Android Classes)
end
end
subgraph DOMAIN[Domain module]
direction LR
subgraph DomainClasses[Classes]
direction TB
UseCases(Use Cases)
Repositories(Repositories Interfaces)
DomainModels(Domain Models)
end
DomainUnitTests(Unit Tests):::green
end
subgraph DATA[Data module]
direction LR
DataClassesTests(Unit Tests):::green
DataDependencies(Data Dependencies):::red
subgraph DataClasses[Classes]
direction TB
RepositoriesImpl(Repositories Implementations)
DataSources(Data Sources)
RemoteAPI(Remote API)
LocalDB(Local DB)
DataModels(Data Models)
end
end
APP--depends on-->DOMAIN
DATA--depends on-->DOMAIN
classDef green fill:#90EE90
classDef red fill:#FFB6C1