Happy Employees == Happy ClientsCAREERS AT DEPT®
DEPT® Engineering BlogKotlin

Kotlin Multiplatform Mobile (KMM) Adoption: Insights and Lessons Learned

At DEPT® we believe that Kotlin Multiplatform is a true game-changer. By sharing business logic between platforms, we had the opportunity to shift our focus to the UI aspects of an app.

As we learnt in our last post about Kotlin Multiplatform Mobile (KMM), traditionally, building a native app is quite time-consuming. Developers build an identical app per platform and both apps contain twice the same business logic. This costs us and you a lot of time with building, testing, and maintenance.

This can be done much smarter with a multi-platform approach, without compromising on experience or quality. With a native multi-platform framework we build the business logic of an app only once. This logic is then converted without too much fuss into native code, to which both apps can then connect. With both apps, you can focus on the user experience. KKM gives us the option to write the business logic for multiple platforms at the same time. Building the shared KMM layer is handled by the same native developers. No additional resources or resources with other skills are required.

At DEPT® we believe that Kotlin Multiplatform is a true game-changer, it is a relatively new way of working for mobile development. That is why our mobile team invested time and research to push forward with this approach to stay ahead of the game.

It did not become a game-changer for us over night. When is the right time to start working with it and when are we confident that KMM will work for us in the long run? Should we wait until it is widely accepted or should we already start investigating?

KMM was introduced in 2020 and currently just gone into Beta. KMM allows sharing code for Android, iOS, and even more platforms. The common code consists of business logic. Business logic is never seen visually in an application but is still the foundation of every application. By sharing business logic between platforms, we had the opportunity to shift our focus to the UI aspects of an app.

Where did we start

We started with multiple proofs of concepts that used KMM, testing basic functionalities like code sharing, networking, and storage. It took a little time before the team had something up and running. The PeopleInSpace repository is a really good example of what we were looking for in the first place.

Each of these concepts would use KMP-Coroutines, which allowed us to minimize the gap between the platform concurrencies and offer cancellation support like any other project. iOS projects even have the choice to integrate shared with Combine, ReactiveX, or Async/await.

Below you can find an example of using KMP-Coroutines, where the plugin automatically generates an additional function that can be used within the iOS project:

class NewsRepository {
    
    // A suspend function to retrieve data
    suspend fun getNews(): List<Article>

    // The plugin will generate this function, which can be used on iOS
    fun getNewsNative() = nativeSuspend { getNews() }
}

Note: Currently the 1.0.0 alpha versions removes even the Native suffix from the ObjC/Swift names, which makes the usage on both platforms even more similar.

Another interesting part of the concepts was about defining the process of how the teams should work together. We would start by exploring how both teams would depend on the same business logic, and how this business logic would be distributed to all teams.

The integration with an iOS project was pretty straightforward. Initially, the team looked into CocoaPods but quickly shifted to Swift Package. Building the KMM project would generate a swift package that is pushed to a separate repository. The iOS team would include the repository as Swift Package in their project. It allowed the iOS team to make use of the common code without having to set up an entire Android Studio / IntelliJ environment.

It was by far the most interesting topic during the proof of concept: Getting the process up and running of publishing swift packages when we made changes in the KMM repository.

What did we learn

KMM can be introduced gradually in a project, it is not mandatory from the start of a project. It is a tool that helps you to achieve your goals. However, our goal should never be to build something with KMM. It is one way to do something, but that is not always the right one!

Meetings were more centralized now that there is a shared dependency for both platforms, which has to work for both platforms. Suddenly more discussions took place, which would never have happened when building two fully native projects. Using the same naming convention defined in shared and the need to ask more questions resulted in better communication. The terms shared and platform became part of our natural vocabulary. It became a way to define where something lives in a project.

A culture change happened over time. Up until now we always had two separate products, based on two entirely different tech stacks. These two approaches resulted in two different products, which had nothing to do with each other. Now that we are using KMM as a foundation for business logic, it has become a different game.

One thing we did not expect was that the team became more interested in the other platform. At some point, the team members started up the other IDE and invested time learning the other platform! We did not have this set as a goal, but it is a nice bonus.

What helped us move forward

There are some essential libraries that we have used during our journey of using KMM.

KMP-NativeCoroutines;

  • As described before, it allowed us to use Flows and suspend functions of Kotlin in our Swift projects;

SwiftPackageManager;

  • In showing us the way how to build a plugin;
  • Unfortunately, the project got abandoned which required us to do something similar in-house;

Ktor;

  • Easy-to-use networking features;
  • Allowed us to use WebSockets on both platforms without any additional platform-specific code;

Koin;

  • Koin brought possibilities to expose what matters to the platforms from shared;

What can we conclude?

The quality of our apps increased by using KMM. Compared to a traditional native project, we see over 50% fewer issues created by QA.

While working with KMM our team has shown an increase in performance. We communicate better, collaborate more, and individually know more about the other platform, resulting in team growth. As a bonus, we even work with kick-ass technologies and learn some things along the way.

The flexibility that KMM gives us to share the application's business logic between both platforms. It gives us the benefits of native programming by writing platform-specific code where it only is necessary. That allows us to focus more on creating beautiful native UI.

This is a big win for us. It brings the benefits of cross-platform frameworks (faster, cost-effective, consistent, and reusability) to native app development. Based on this great experience, KMM will be used in a lot of our native app projects in the future.