· 15 min read Posted by Kevin Galligan

Piloting

KMP For Native Mobile Teams

The first stage is adding some KMP libraries and introducing KMP to the team.

This is a post series with several sections. If you landed here first, make sure to go back to the Intro to get the full story.

Javascript disabled?
Our site requires Javascript for some sections. Please check that Javascript is enabled.

Piloting is the first phase. The goals are:

  • “Pitch” the tech to the team
  • Create an evaluation and adoption roadmap
  • Form a core KMP team
  • Write some KMP code
  • Establish tools and libraries that best improve the developer experience

Piloting is about evaluating and learning KMP, as well as setting up the team for success. While Android developers are familiar with Kotlin, there’s a lot to learn about using KMP on iOS. Contrary to what some believe, Android developers cannot “hit the ground running” with KMP for iOS. KMP is also something that iOS developers will have concerns about (to put it mildly). This is the phase where the team as a whole is exposed to KMP, where the basic structure and lessons are learned, and a general plan for how the whole team will interact with KMP is developed.

It is important to stress that this is not the time to show how much efficiency KMP will add to your development workflow. KMP is new to everybody, and while learning can be accelerated, it still takes time.

Plan First

This is an obvious first step, but it should be stressed. It is important. While you can just “add some KMP” and see how it goes, having a plan is better. There are many issues that can be avoided if addressed early.

What are your KMP goals?

As discussed in Basic Concepts, the two main development modes are library dev and feature dev. Library dev involves publishing a few library modules that are consumed by the apps. It is a fairly simple approach, but limits KMP adoption. Feature dev involves day-to-day feature development. The scaling phase involves feature dev, and while more complex, this is also where you’ll get the most return from KMP.

Some teams really just want to share some libraries. For those teams, adopting KMP should be straightforward, and with proper execution, pretty much guaranteed to succeed. You don’t really need a plan for the wider team, nor do you need to worry too much about addressing concerns of how everybody will work with KMP. Essentially, they won’t. The libraries will be published as dependencies to the apps.

However, most teams thinking about KMP want to adopt KMP at scale, and get the most out of the technology. For those teams, the Piloting phase is the time to learn the basics.

Take the Temperature

Who’s on board with adopting KMP? We have seen many different situations, ranging from full management mandate and budget, to a single member of the Android team lobbying for the tech with no interest from management or the iOS team. Different contexts will likely have different outcomes.

Generally speaking, success is more likely with some management/organizational interest, and at least some of the iOS team being curious about trying KMP. Having those conversations and discovery is important.

If there is not much discussion about adopting KMP currently, we’ve found that simply presenting that the tech “works” does not move the needle much. “Pitching” KMP is important.

“Pitch” KMP and the plan

Present about what KMP is, the basic phases of adoption, and the vision for how KMP would be used in your org assuming a successful rollout.

This assumes your role is some form of management or decision-maker, or at least a senior member or tech lead on the team. If not, the first step would be to get some leadership on board at least for an evaluation.

While there are Android devs who have reservations about KMP, Android devs tend to be open to the idea. The “pitch” is less for them. The iOS devs tend to be more concerned, for a number of reasons. Also, the potential to disrupt ongoing development or lose key staff will raise eyebrows outside of just the dev team, so having a reasonable, staged, low-risk plan is a good idea.

iOS Dev Concerns

iOS devs tend to have more reservations about KMP, and that makes perfect sense.

From a technical perspective, even if the tooling and developer experience for Android and iOS devs were on a similar level, iOS developers are unfamiliar with Kotlin and Kotlin-related tools. They would automatically be at a significant disadvantage. The worse news is, the KMP/iOS developer experience is not great, and certainly far worse than the KMP/Android developer experience.

iOS team members will be starting with multiple technical and tooling disadvantages. Your tooling and library choices can significantly improve the “out-of-the-box” experience. It is critical to select those tools and add them to your team’s stack.

Beyond the technical perspective, there are team and career concerns. The most severe view of “what happens when KMP comes to town?” is that the Android devs will be doing all of the heavy lifting work, and iOS devs will be exclusively writing UI. When the tech economy was strong, this might trigger key iOS devs to leave (still might). With the very public tech layoffs of the past ~2 years, this kind of vision will introduce anxiety about job security.

iOS Dev Role

The good news is, Android devs are definitely not prepared to starting writing all of the shared architecture for KMP/iOS. That sounds a bit like bad news, but it’s not. Most cross-platform tools position themselves as “replacements” for the native platform, so that you can build 2 apps from one codebase. In reality, as the old joke goes, “I thought React Native (or whatever) would mean I have 1 platform instead of 2, but now I have 3”. You’re always living on the platform you’re deploying on. Trying to hide that fact leads to issues.

KMP is not “hiding” the native platform. It is cooperating with it. As such, there is definitely a specialty that I would call “KMP/iOS expert”. Understanding how Xcode works, how native builds and deployments work, linkers, native Swift/Objc/C integrations work. Understanding the iOS platform and APIs. Also knowing how to structure the exported KMP API surface to be best consumed by Swift. These are all things that require a relatively shallow understanding of Kotlin, but deep understanding of iOS, and they are critical skills for serious KMP adoption.

Indeed, as KMP adoption increases, iOS developers with a functional understanding of Kotlin and KMP will be in demand.

KMP and Native Mobile Specialists

Many potential KMP adopters plan to “merge” their mobile teams. Rather than Android and iOS specialists, there would be one team of “mobile developers”.

A detailed discussion about merging teams is beyond the scope of this series, but in summary, this is a risky plan. Merging teams has been a common discussion for years, but native specialists is how teams generally operate. If merging teams was straightforward, many mobile teams would work that way. KMP might make “merging teams” easier, but KMP is new. That means there’s little evidence to point to, and from what we’ve seen, to the degree that KMP might make it “easier”, it certainly doesn’t make it “easy”.

In short, specialties emerge for practical reasons. I wouldn’t assume KMP removes those reasons.

A more reasonable approach and expectation is that developers will have a platform affinity. Largely focused on either the Android or iOS app, but be able to edit the shared KMP. The approach should be gradual, especially for iOS developers, as there is much to learn. Over time, iOS developers can become functional Kotlin developers without needing deep Android platform experience. It’s also important to keep in mind that the “clock” goes back to zero for each new hire.

You can always “continue the path” later. As developers become comfortable with the shared feature code, they can start editing both platforms’ native code. However, a plan to simply “force it” can trigger anxiety in the team, and will almost certainly be painful for everybody.

Build a Piloting Team

Assemble a core group that will actually “figure out” the initial KMP introduction. Again, every team is different, but unless you have a small team, this is probably not an “everybody” team. You’re starting small and learning.

The initial technical implementation is not going to be very complex, in the grand scheme of things. The Iteration step is where more folks get involved, and feedback starts to get “real”. That’s later. Right now, we’re piloting.

Having said that, in all phases that actually involve the tech, get the iOS team involved. One of the biggest success indicators is direct involvement with members of the iOS team. We’ve seen several KMP efforts where nobody from the iOS team was involved at all. If there is zero interest from the iOS team, I would suggest revisiting the “pitch” phase.

Actually add some KMP

You’ll be adding some smaller library modules, using a unidirectional, library dev workflow. The goal of piloting is to get the ball rolling, start to get the team comfortable and familiar with the tech, and start getting feedback.

That means, it doesn’t need to be a lot of code, and again, this is not the time to try to “prove” that KMP will “make dev more efficient”. At this point, it will not.

Module Recommendations

Library dev involves building “libraries”. Hence, the name. “Libraries” are units of code that are used by the apps, but aren’t directly impacted by the app’s day-to-day work. They are developed and changed on their own schedule, and can be published sequentially.

My favorite bit of advice comes from Jesse Wilson. Try to find something that nobody really likes to do. A good example would be analytics. Most devs don’t enjoy the “add analytics” task. Write a typed library in KMP that the apps can call.

Common examples:

  • Networking library. Networking calls are defined on the back end, not on the app.
  • Database storage. The local db schema is defined by app dev, but those changes tend to be infrequent, and db schemas/migrations are defined sequentially.
  • Tax calculations. Potentially difficult to implement and critical to get “right”. Not really impacted by the app’s features. This one might be better for the next phase, Iterating, but you get the idea.

Keep in mind, we’re adding KMP code. That doesn’t mean we’re immediately putting it into production, or need to rely on it for the production apps. If there is worry about about actually relying on the KMP code in production, point out that “production” is the next phase: Iteration.

Adding Code

Most teams add KMP by introducing a new KMP repo, and publishing from that repo. For piloting especially, this is the approach we’d recommend. It will minimize any potential disruption to your current development workflow.

Library Dev Publishing Options

Traditionally, most teams introduce KMP by publishing binary dependencies and consuming those from the Android and iOS apps. This is such a common approach that we’ve built KMMBridge to facilitate publishing iOS binaries.

However, if you are planning to scale KMP, we no longer recommend binaries. We recommend having all devs build Kotlin source locally.

Why not binaries?

If the ultimate goal is to have the team working with KMP directly, as opposed to consuming libraries, starting with source code is better.

For Android, published dependencies can also include source jars. You can browse and debug published dependencies directly from your IDE.

For iOS, this is not the case. KMP code needs to be published as compiled binaries. You cannot browse or debug these dependencies. That is, again, taking an already imbalanced developer experience and making it worse. The engineers who most need to see Kotlin and become familiar with it are unable to do so.

Further, the API exported from KMP to iOS can be rough. Particularly if written by Android devs who aren’t very familiar with Swift nor with how Kotlin exports its types. That means you’re giving a “black box” to the iOS team, with an unpleasant API surface. That is unlikely to make them more comfortable with KMP.

Starting with binaries is a lost opportunity. Being able to browse, debug, and even lightly edit the Kotlin code is a much better introduction to KMP.

GitPortal for Publishing Source

Linking code between repos usually means “git submodules”. Few developers like using submodules. We’ve built a tool call GitPortal to facilitate KMP teams sharing source code.

Git submodules can be difficult to work with, but they are appropriate for library publishing, which is one of their common use cases. However, they can be difficult to manage. It’s easy to “get into trouble”. GitPortal was designed to make introducing KMP source easy. Also, while library dev is well supported by submodules, feature dev is not. If your eventual goal is feature dev and scaling, submodules would not be a great choice.

GitPortal “links” repos by pulling the KMP repo into a folder of the app repo. That code lives in the app repo and is not simply “linked” as with git submodules. Once that code is pulled in, the app developer should not generally have to worry about GitPortal much, except for “the one rule”.

When using a library dev workflow, the apps should be linked to a specific version of the KMP code. Changes to KMP code flows in one direction only: from the KMP repo to the app repo. This is GitPortal’s “Unidirectional” mode. Its one rule is that you can’t commit and push KMP changes directly to the app repo.

You can locally edit the KMP code. Say, put in some print statements, or try fixing a bug. That’s actually part of the benefit. Any developer can “lightly edit” code in different languages, and the iOS developers will have the opportunity to make some local, light Kotlin edits. However, a library dev workflow mandates that all committed changes to the library code must come from the library repo itself.

To try using GitPortal to add your KMP library, see the GitPortal for KMP Tutorial. It will walk you through setting up some template repos, wiring CI, and using GitPortal to manage library changes.

GitPortal and KMMBridge are not mutually exclusive. You can use both with the same library. While we feel that sharing source is the better option, there are a number of practical situations that may require sharing binaries, and you certainly can do that.

KMMBridge for Binaries

KMMBridge is designed to package and publish XCFrameworks from KMP builds, so they can be consumed by either SPM (Swift Package Manager) or CocoaPods.

KMMBridge has gone through a few major releases. The latest iteration, 1.0, is mostly geared towards SPM publishing, with simplified integration and publishing. See the KMMBridge SPM Quick Start for a quick tutorial that walks through

Why we changed our recommendation

The lack of source visibility has long been an issue. However, for much of KMP’s history, the tech was “pre-stable”. It was easy to assume that KMP would ultimately be abandoned. There is more friction for iOS devs using KMP source. They need to install a JVM and properly configure their build system, as well as wait for a longer initial build.

These issues were often sufficient to push back on the KMP effort, and arguably, that wasn’t unreasonable pushback. To get KMP “in the door”, binary packages were an easy starting point. No friction. KMP needed to “prove” itself, and since it caused essentially zero friction for iOS developers to consume binaries, there was much less to push back about.

Times have changed. KMP is stable, is now endorsed by Google, etc. The tech “works”. Proving that it “works” doesn’t accomplish much. The goal of the piloting phase is to evaluate if KMP works for your team. Starting with binaries does not move you significantly towards that goal.

The “friction” of installing some tooling, now that KMP is “stable”, is no longer really “reasonable” pushback. It’s simply not that difficult to do. If, for your team, that is enough pushback, I’d argue your overall chances of success aren’t very high.

Tooling and Developer Experience

Choose tools and libraries that will present the best possible iOS developer experience for KMP. As a quick overview we recommend the following:

The Xcode Kotlin plugin

This allows iOS developers to browse and debug Kotlin code directly from Xcode. It is not a great editing experience. For that, your iOS devs should also install whatever IDE your Android devs use. However, browsing, debugging, and potentially some light editing from Xcode is a great way to introduce Kotlin to iOS developers.

SKIE

The Kotlin compiler exports any valid Kotlin to Swift, but a lot of the expressiveness of Kotlin is stripped in the process. SKIE bridges many of Kotlin’s modern features to Swift, in a way that is more familiar and natural for Swift developers. We recommend any new project start with SKIE on by default.

Prepare Onboarding Docs

Installing and maintaining build tools, while conceptually simple, can be practically difficult. This is true for many ecosystems: Ruby, Node, Python, and the JVM. MacOS ships with some of these by default, but the versions are usually too old for modern development.

Prepare a common install process for all of your developers, document it, and test it. Every time I set up a new mac laptop, I have to spend a fair bit of time reminding myself what SDK manager to use, how to properly configure paths, etc. Me. Personally. An iOS developer with no significant JVM experience will likely struggle.

With specific guidance, setting up a JVM is easy. Draft that specific guidance, and make sure you test it with a few devs. First impressions count. It’s also a good idea to have live “setup” meetings, to provide immediate support if needed.

See Ideal iOS KMP Setup for our tooling recommendations and our recommended setup process for iOS developers.

The Piloting Process

You’ve added some KMP, the iOS devs can browse, build, and use KMP. The remainder of “Piloting” is to gather feedback and prepare for the next phase: Iterating.

There’s not a hard line between these two phases. They’re both using a library dev workflow. Piloting is the phase where you get the ball rolling, and gather initial feedback. Iterating is where you actually ship to production, expand the “team”, improve your KMP/iOS fundamentals, and prepare for Scaling.

Once you have some KMP written and available, devs should be able to build it, but it’s best to avoid putting KMP into production until you have some more tools in place, which will be added during the Iterating phase. For now, make sure everybody can build KMP, then gather more feedback from the team. What’s been good? What’s been bad? What concerns do they have as you move forward?

Some of this feedback may be directly addressable, either with tech or training. Some may simply fall into the category of necessary compromise. Listening to feedback and taking it seriously is important, even if the ultimate answer is that some of these issues must simply be accepted.

Next Section : Iterating

Iterating is where your team gets “good” at KMP, and you put some code into production. Iterating is also where you start to prepare for Scaling.