Understanding Layered Architecture in KMM — Part 5— The Presentation Layer
Now it’s time to talk about the presentation layer. This layer is related to the UI framework, that is: Android with Jetpack Compose, iOS with SwiftUI or UIKit, web with React, etc. They all can differ in the implementation, however, the have, at least, one thing in common: the business logic, which we implemented in the domain layer.
Moreoever, in many cases, the way how our software access to the data is the same. That’s why we have implemented the data layer in our shared/commonMain module.
As you can see in the architecture diagram of our project, there are two main things that are going to be implemented in the presentation layer (Android and iOS modules):
- The view or UI itself. For Android, we are using Jetpack Compose. For iOS, we are using SwiftUI.
- The UI logic. We are implementing for both platforms the MVVM pattern. As you might be guessing, this is a presentation pattern (others call it as presentation architecture pattern).
Let’s see how the Android app is structured. First of all, we want to respect the Dependency Inversion principle and for that, we are going to help us by implementing the Dependency Injection design pattern. We are not going to use any library for this.
First of all, let’s define an interface which is going to act as a contract for giving us the necessary dependencies that we need to show the movies in the screen.
As you can see, this interface that we have defined in our Android app module knows about classes in the domain and data layers. MoviesDb
and the data sources are from the data layer, the DispatcherProvider
, GetMoviesInteractor
and the MovieRepository
are from the domain layer and the TimeProvider
is actual class
implementation we created in the androidMain
module.
We just have to implement the AppInjector
interface and return the actual implementations of our dependencies. But, how does the Android module knows about all of those classes? The answer is very simple: the presentation layer depends almost in all layers. If you have read about “clean architecture”, it’s the outer layer.
Now, we only have to implement our ViewModel which is going to have the UI logic, like invoking the interactors, updating the UI states, etc.
In summary
- We have created a KMM project and implemented a layered architecture, having three main layers: domain for business logic, data for data access and presentation for the platform on where the user is going to interact on.
- The presentation layer will depend in all the other layers.
- Code related to business rules and data access is going to reside in the
shared/commonMain
module, which is pure Kotlin. - If we need to make any change to the business rules, we only have to modify the code in the domain layer. The change is going to be reflected in all the platforms (Web, Android, iOS, etc).
- If, for any reason, the business or data access logic might differ in any platform, we only have to change the injection of the implementation by another one.
You can follow the progress of the project on Github:
https://github.com/jflavio11/LayeredKotlinMultiplatform
Split of this post series
This has been the second post in which we have talked about the domain layer. In the following we will talk about the data layer. This guide is divided into the following posts:
- Introduction
- Designing the solution
- Creating the domain layer
- Creating the layer data
- Implementing the presentation layer (this post)