part 2 of 5
The application we are going to develop is quite simple, but in order to understand all the features of separating the project into layers, we are going to complicate it, perhaps unnecessarily.
Our app will display a list of movies. That’s it. just that. So we are going to make layers and give responsibilities to each one. I will list them in the order in which we are going to develop it:
Here we will create our main “Movie” model. Also, the contract or definition of stores and data sources.
Store a. will have an interface inside
domain classes for packages and data sources would be in another
data Packages that we will look at in the next chapter of the series (including libraries that will help us save data in a local database and one that will help us get data from a REST service).
We will have all the logic within our domain layer that we want our application to have regardless of the platform on which it will be implemented,
For example, do we want our app to display a list of movies? So we should create a class that is in charge of bringing us movies. We will call this class “use case”, Example either interactor, It doesn’t matter if you are programming an Android or iOS app, it will show a list of movies and the logic will be the same in both.
This means that our domain module should be able to “extract” itself from the source code of the Android app and be able to be used in another framework Keeping the core functionality.
Perhaps it doesn’t seem very useful to create a class that only has a single function, and the only function it does is return a list of movies that are given to it by the repository. it’s like it Example There is a railing, there is a bridge.
But let’s look at it this way: reading the following structure, what do you think this example app does?
Most likely it’s an app that has a shopping cart, right? In which you can view products, promotions, add them to cart and make purchases if all data in cart is valid.
When you enter a project and find something like this, you save a lot of time trying to understand how the app works. of course, maybe use cases,interactors which perform more complex actions.
Our app will have only one Example execution:
GetMoviesInteractor, By the way, I prefer to use the term “interactor” when creating use case classes, because an interactor is an object that implements a system use case.
The data layer should also be the same for every framework or platform. It doesn’t matter whether the app runs on Android, iOS, web or desktop. The logic for repository and data source implementations should be exactly the same.
However, we find a stopper here. Each platform has different ways of connecting to the REST API or saving the data to the local database. Android mostly uses Retrofit and the iOS app uses Alamofire. So, how can we handle a unique way of accessing external or internal data?
You can think of Retrofit as it works on any JVM project and the core of KMM is a pure Kotlin module. Although, As you can read in this issue on GithubAs Jake Wharton points out this is going to take some time as Retrofit depends on other libraries such as OKHttp.
The best option we can find so far (March 2022) is to use ketoro REST API to consume.
And what should we use as local data source library? for that, there is sql delight, and the implementation for the KMM project is pretty straightforward! We have to create database driver for each platform and put the data source implementation in
commonMain (core package inside
shared modulus). They (the data sources) are going to depend on the database driver interface. Easy!
It’s easy (or maybe not). Here all we have to do is write the UI of each platform! That is, use Jetpack Compose for Android, SwiftUI for iOS, etc.
If you want to try something more sophisticated, you can try adding a
presentation inside the package
shared Module and define contracts for View, Presenter and ViewModel (if you want to implement MVP or MVVM pattern). To be honest I haven’t tried anything like this yet, but it could be very interesting.
This is the final architectural design of our project:
As you can see, we are maximizing the approach of having a unique cross-business layer that can be used by any platform.
And our project tree should look something like this:
As you may have noticed, we are starting to build software from the core, from the business logic or domain layer. Business rules and requirements will guide the development of software: Domain Driven Development.
Note: I am developing an open-source Kotlin multiplatform project in Github, check it out!
This is the second post in which we have created a solution for our project. In the following, we will talk about domain layer implementation. This guide will be divided into the following posts:
#Understanding #Layered #Architecture #KMM #Part #Designing #Solution #Jose #Flavio #Quispe #Irazabali