As we approach a Kotlin Multiplatform Beta announcement, let’s take a look back at some of the challenges and missteps that early adopters had to overcome (and let us brag a bit about how we helped make those better). We’ve been active in developing solutions, from early pain-points that developers experienced to the growing pains teams are feeling.
Early Adopter Issues
In the early days we found that getting a KMP project set up was not straightforward. Project and gradle configuration was tricky and it took a lot for us to ramp up new devs. Configuring your targets and sourcesets was not very straight forward. Many developers weren’t sure what libraries were available and integrating them added further complexity to the project setup.
This is why we partnered with JetBrains and created KaMPKit. Its purpose was to be an example of a ready-to-build project set up with common libraries. The idea is we get developers through the annoying project configuration stage and on to writing shared code and evaluating KMM.
Jetbrains has made significant improvements in their project wizards and tutorials since KMM first launched, making it easier for individuals to get started and evaluate KMM without KaMPKit, but it still serves as a good example of common usage beyond the getting started stage. We are also now developing similar examples geared towards larger teams.
Jetbrains originally elected to take a strict approach to memory management which required objects crossing thread boundaries to be “frozen” (made immutable). This felt restrictive to JVM developers who were used to a more lax memory policy and led to a lot of frustrating bugs as well as a learning curve for everyone getting started in KMM. Touchlab was on the forefront of educating and providing tools such as Stately to enable JVM developers to ramp up more quickly.
While the intention of the legacy memory model was good, the issues it caused for new developers ultimately drove Jetbrains to introduce a new memory model which features more familiar garbage collection and does not require developers to freeze objects which cross threads.
Touchlab has adopted the new memory model for all new KMM development and will continue supporting developers in navigating migration and usage.
Growing Pains In Production
Now that the early issues have been largely addressed, we have been turning our attention to challenges faced by larger, in-production teams. These typically have less to do with the technology itself and more with how to make the best use of it.
Tutorials and getting started projects are generally focused on a small, greenfield application use case. It makes sense to simplify code in samples to clearly demonstrate core concepts. Larger production projects, however, have additional complexities which simple samples ignore.
Existing projects usually consist of dedicated platform developers working in separate repositories. This siloed approach can make it difficult to get started sharing code both from a people and technical perspective. I’ve written previously about how we can encourage people to get involved in shared code and skill up as mobile developers. That is an important goal to aim for particularly for smaller teams, but we’ve found that larger teams with dedicated platform developers will have to develop a workflow to get started with.
Most teams that succeed in putting KMM in production start with an “internal SDK” flow, where shared code is developed and delivered to each platform as a consumable library. From the technical perspective, we encourage teams to start small and identify areas of the code that depend on alignment between platforms (such as analytics).
iOS Developer experience
iOS developers are often the most skeptical party when introducing KMM to a team.
Once concern is that interacting with Kotlin Native code from iOS can at times be difficult. The K/N compiler generates Objective C code which can appear out of place amongst existing iOS code and can require special care or wrappers when using. We have been working on three different ways that can improve the experience:
- Following the practices found in KaMPKit. As an example, exposing Kotlin coroutines (flows and suspending functions) from the shared code feels natural to the Kotlin developer, but doesn’t work well when exported to iOS. KaMPKit demonstrates how to add a callback layer to your iOS layer to facilitate ease of use.
- Use the xcode-kotlin debugger. This tool adds Kotlin breakpoints, debugging and syntax highlighting directly to XCode. This allows iOS developers to easily troubleshoot issues originating in shared code.
- We’re currently piloting a tool that features a compiler plugin which generates a Swift-friendly API surface and packages it directly into your shared XCode framework. This makes the iOS usage of your shared code seamless and familiar. Sign up for the pilot and to stay in the loop about other enhancements we have coming up!