KMP For Teams

(Draft) Mobile Development Efficiency

· 8 min read

Author: Kevin Galligan
The debate around KMP necessarily involves "efficiency", but development efficiency is notoriously difficult to define. We'll cover some topics rarely mentioned in the debates around "cross-platform" vs "native" that are useful for making platform decisions, but also for devising a KMP approach.

Draft Document

This doc is a work in progress.

Overview

The debate around cross-platform vs native has almost universally been framed as a choice between efficiency and quality. This framing is commonly used by everybody in the debate, which is an interesting concession from the fans of “native dev”. The “choice” then hinges on whether the cross-platform tool produces “good enough” output. However, the situation isn’t that simple.

If you were building a product for one platform specifically, and there was no chance you’d ever want the “other” platform, the chances are very high that you’d build that product with the platform-native tools and frameworks. The quality will almost certainly be better, and the process will almost certainly be more efficient. Assuming, of course, we can ignore specific context (if you had a team of React experts who would be building it, for example).

Another aspect that is often overlooked is that the second platform is much easier to build than the first. It doesn’t matter which platform is first. The first build needs to figure out technical issues like server calls, architecture, performance, etc. Potentially far more impactful would be creating a real product from what product owners and designers prepare, as well as their feedback after seeing real builds. The second platform has to resolve none of this.

Those considerations are useful to understand when evaluating tech choices in general, and for KMP, thinking through your approach.

Feature Implementation Efficiency

“Feature Implementation Efficiency” (FIE) is how “efficient” building something for a native mobile app is, for one platform (or both, if you’re using a cross-platform framework that can’t not build both). It’s a relative measure of how much more or less time it takes to build the same “feature” using different frameworks and tools.

I’ll say this up front. FIE isn’t something you can reasonably measure to everybody’s general satisfaction. If one person is a fan of a particular technology, their assessment of how “efficient” it is will be higher than someone else’s.

If you’re a Flutter fan, you’ll focus on the “quick round trip”. If you’re a React Native fan, probably something similar. However, there are other factors to take into account. For example:

  • Platform-specific calls that need to be bridged?
  • Platform-specific libraries unavailable for your framework?
  • Native views without implementations?

Most cross-platform frameworks have some way to accommodate these issues, but the amount of work required to do so can be considerable.

Then, of course, there’s the issue of support. How often are cross-platform releases lagging behind native platform releases? Are platform-specific integrations (widgets, etc) supported or need custom work?

Any assessment of FIE is more of a “vibe” than a quantifiable metric. I can’t imagine how you’d get a reasonably objective measure of it. At the same time, it makes sense, it’s “real”, and it matters.

Native platforms have first-party tooling, finely-tuned development and execution environments, with few features that aren’t easier to implement or integrate. Google and Apple are very invested in making great apps for their platforms as easy as possible.

Generally speaking, then, FIE is highest for native development. Take the following chart. It’s comparing Compose for Android to React Native and Flutter. They’re not “real” numbers. It’s, as stated, more of a “vibe”, but I think most devs would say “that’s reasonable”. Flutter and React Native take longer to implement the same thing, but of course, then you have both platforms (ish).

Chart comparing efficiency of different frameworks

So cross-platform is more efficient than native? Maybe, assuming nothing changes. That’s rarely how product development works.

When building product features, the specs and designs aren’t perfect. They’re often missing features and ignore issues that might come up for the real product. Designs tend to lean towards the “happy path”.

I call this effect “fauxgmented reality”. Designs that work well for the example case provided by the designer, leaving the developer to deal with what happens in the “real world”.

That happens. A lot. When it does, there’s often rework involved. If a given feature takes longer for a cross-platform framework, that feedback came later, and the rework cost more.

Those are mostly communication or “imagination” issues. Those happen even when the product owner knows up front how a feature should work, and that they definitely need it.

In real product development, “iteration” is common. After seeing and using a feature, there are often changes. It’s also common for features to be completely dropped, or completely redesigned.

I won’t beat a dead horse here. You get the concept. Implementing software is rarely a direct path. Some amount is “waste” generated by communication issues, incomplete feature design, feedback, or simply dropping the feature altogether. Within each of those cases, work is thrown away. For new products, it is common for more work to be tossed than what winds up in the “final” product.

While that is “waste” in terms of effort that doesn’t wind up in the complete feature, it’s necessary to arrive at a better outcome. It’s the cost of product development.

The only true “waste” in this context, is the extra effort required by an inefficient development framework. Take the more extreme case, of an entire feature dropped after user testing.

Chart comparing efficiency of different frameworks

In the simple case, that’s not just extra development time, but longer total product development time. Less capacity for feature iteration, longer time to market, or both.

Second Platform Effect

Which platform takes longer to build for? Android? iOS? It’s a trick question. The first platform takes longer.

That obviously assumes you don’t have the native mobile teams doing the same thing, at the same time, expending similar effort to independently learn the same product lessons. Even if you ultimately decide to stick with “fully native dev”, this is a topic worth considering.

The “Android Advantage”

Touchlab started around 2010/2011. We only built Android apps. It was a good time, because virtually all mobile shops in NYC only built for the iPhone. Basically all “startups” wanted iPhone first, and many skipped Android altogether, until they couldn’t. That meant most of our work was “replicating” an existing iPhone app.

The potential client generally expected Android dev to cost about as much as iPhone dev. That’s a reasonable assumption. However, building an app that replicates an existing app, with the source code, and access to the developers, is much easier than building it the first time.

Now, just because a potential client assumed similar costs didn’t mean they’d be willing to pay them (and they’ll rarely tell you the cost anyway). Most assessed their Android need as less urgent than iPhone, and budgeted less accordingly. Still, though, since the second platform is easier, the second build doesn’t “cost” as much as the first.

On one project, the client wanted to start with both. An iPhone consultant came in, and we all had a meeting. Both I and the iPhone dev said it was better to build one platform first, but neither one of us really explained “why”. Clearly this person understood the situation. Then we both proceeded to make the case for the “other” platform to be built first. I wonder what the potential client thought about that.

iPhone preference won out. The client had an iPhone. All of his friends had an iPhone.

I honestly don’t remember if we actually got the project, but I remember the meeting.

The first platform has all of the technical issues to solve. Server APIs are rarely “complete”, and often not documented. Architecture decisions often take their own iteration. Then the issues described in the earlier section. Product and design refinement, feedback, edge cases, etc. Most of that can happen on whatever platform is functional first.

The second platform can essentially skip over all of that extra work. That, of course, assumes you actually use the first platform as a model. You definitely should.

I’m not suggesting that you build and release one platform first, but that the feature dev can be staggered.

Releasing features on one platform, perhaps behind a feature flag, may make sense for real user feedback. That feature would only be available on one platform, but if that is sufficient to learn what you need to learn, it’s a method you could use to save effort.

Summary

Single platform native dev is more efficient to implement a feature than a cross-platform solution. Development rarely follows a linear path. There’s almost always “extra work”, and it can be considerable.

The second platform requires less work because the “extra work” is done, and you have a functional model to work from.

These observations help provide a more reasonable comparison of cross-platform vs native. Far from “two apps for the price of one”. In quality terms, it’s less than “two”, and in development cost, certainly more than “one”.

It’s a reasonable argument in support of native dev, although there are many other considerations (feature parity, maintenance, etc).

However, in the context of KMP, this view of development efficiency can be applied to KMP development strategy, to take advantage of the benefits while avoiding the disadvantages.