logoDroidKaigi Ninjas
DroidKaigi 2021

DroidKaigi 2021

Example of KMM utilization for full replacement of popular dining app “HOT PEPPER GOURMET”

Recruit Co., Ltd.
Oct 15, 2021

This is an English translation of the original Japanese article.

In September 2020, JetBrains released the alpha version of Kotlin Multiplatform Mobile (KMM). Hasn’t every app development engineer thought “I would like to use KMM to write a common logic” as least once? This article discusses what led up to our decision to adopt KMM for our project to fully replace “HOT PEPPER GOURMET” and what actually happened when we did adopt it and attempt to implement a shared logic.

“HOT PEPPER GOURMET” full replacement project

The “HOT PEPPER GOURMET” app team is completely replacing all code for both iOS and Android with new code.

There are several reasons why we decided to carry out a full replacement. It has been more than 10 years since the app was first released. The source code has become bloated and complex. This has highlighted issues such as a slower development speed and greater difficulty in preventing failures.

For the full replacement project which began in October 2020, we adopted Kotlin Multiplatform Mobile (KMM), which was still in Alpha, and have been working to create a common code for Android and iOS.

Behind the adoption of KMM

Need for cross-platform technology

One of the issues that we wanted to solve with this replacement was the unpredictable differences in features between the operating systems.

Because we had been operating continuously for a long time without preparing precise specifications, many unintentional differences emerged in minute areas of the logic between the operating systems. A prime example is the logs used for analysis. Even with logs that appear to be the same at first glance, many problems arose, such as slight differences in parameters between iOS and Android.

To solve these problems, along with redefining the specifications, we decided to adopt a cross-platform technology with the objective of preventing code differences from arising.

We also were attracted to a technical challenge in that we, as engineers, wanted to solve. We wanted simply to reduce the number of hours spent for development.

KMM or Flutter?

Two options ultimately remained on the table for the cross-platform technology: KMM and Flutter.

We compared the two across a variety of points, but, in the end, the following three factors were decisive in our decision to adopt KMM.

Common scope

In terms of a common scope, Flutter covers all code including UI, while KMM covers all code other than UI.

The policy set for this project was to implement UI in a format suited to each specific platform. In our case, we would have been unable to enjoy the full benefits available with Flutter and also had concerns about difficulties in implementing branches, so a decision was made in favor of KMM.

Recovery methods when problems occur at a level where continuation is no longer feasible

Because this was a large project, we also needed to consider recovery methods should a major issue arise midway in development that was attributable to the cross-platform project.

If a problem arose with Flutter and we were no longer able to continue using it, then we would need to rewrite all code including that for UI. However, with KMM, we would only have to use Swift to rewrite the part shared with iOS, which entailed comparatively less risk.

Hiring and training

Another major concern about adopting Flutter was the difficulty in securing qualified personnel.

Flutter is a relatively new framework and it would be difficult to secure personnel in-house capable of using Flutter. Even if we hired new people, there are not many people who have experience with Flutter in the first place.

If we chose KMM, then engineers experienced with Kotlin would be able to participate in the project at a relatively low training cost, and, as usual, native app engineers would be able to participate with hardly any training cost for both OS components.

In fact, for our project, we welcomed many people with experience in Android and Kotlin to our team using KMM.

Based upon these points, we made up our mind to use KMM, and then made a final decision to adopt KMM after verifying whether we would actually be able to satisfactorily execute development if we actually adopted KMM and what sort of merits we could expect to enjoy.

Architecture and team structure

For the KMM project, there were two conceivable approaches: one is to proceed with a single repository comprising all Android, KMM and iOS code, and the other to create separate repositories for each and import KMM to serve as the library.

Because our replacement project called for simultaneously developing Android and KMM, we chose to go with a single repository so that we would be able to integrate KMM improvements in a way that would save time and effort and as frequently as possible.

The overall architecture is comprised of three layers incorporating clean architecture.

Architecture of the “HOT PEPPER GOURMET” replacement app Architecture of the “HOT PEPPER GOURMET” replacement app

  • Domain layer: holds the app logic and is where the UseCase and Repository interfaces are placed.
  • Data layer: holds access to the data and is where Data Objects and Repository implementations are placed.
  • Presentation layer: holds the UI and related logic and is where ViewModels and Activity/Fragment Views are placed in the case of Android.

The domain and data layers are implemented in KMM and the presentation layer implemented in each operating system.

The teams were also similarly divided into a team responsible for KMM as well as an Android team and iOS team responsible for each operating system, respectively.

The Android and KMM components were devised so that the creation of multiple modules would strengthen dependency and make it easy to preserve clean architecture.

Effect of KMM adoption

As initially anticipated, the domain and data layers were able to be written in KMM, which enabled shared logic and logs to be realized. We didn’t have to worry about the fine details of each operating system. All we had to do was thresh out the KMM method to be able to use logic and logs without any difference in specifications.

In addition, placing some of the complex processes of the presentation layer in KMM as well as other creative devices has further contributed to a reduction in man-hours.

A secondary effect was that the team divisions allowed each OS team to focus on the presentation layer without having to research or coordinate detailed API specifications, and the KMM team could concentrate on the business logic because there was no UI implementation.

Although we were concerned that communication costs might rise as the number of teams was increased, having both OS teams communicate with the KMM team instead of the API team did not increase the number of communication targets. On the contrary, it was quite reassuring to have the KMM team who understands both apps and API, be a go-between with the API team.

In addition, funneling API-related consultations through the KMM team meant that this information was also communicated to the API team, allowing communication with the API team to proceed smoothly.

Demerits of KMM adoption

While no major problems have arisen requiring us to abandon the use KMM, there have been a few minor issues with respect to iOS that have required ingenuity.

For example, the following issues.

  • There were cases where Generics within Generics were determined to be Any.
  • Methods with the same name and same argument names cannot be used.
  • Default implementations of interfaces are unavailable.

Nevertheless, each of these was able to be solved with a little ingenuity and did not escalate into a major problem (for more information, I recommend checking out the “Story of iOS engineers who used KMP to create shared logic for a major app and were successful” which was presented at IOSDC2021.).

Also, when compared to Flutter or other cross-platform technologies, another point, which might seem to be regarded as a demerit, is that UI must be developed for each OS.

Although we chose not to create a common UI, it turned out that, in fact, many UI had the same appearance in both operating systems, and there were times when we thought it might have been better to use Flutter which would have compelled complete sharing.

This was a trade-off that must be made to use technology familiar in both operating systems to implement UI. So, I recommend conducting a careful review prior to starting any project as to which technology to adopt for your project.

In conclusion

In conclusion, we felt that the adoption of KMM for full replacement of our “HOT PEPPER GOURMET” app was a very good choice.

There were no fatal problems, and we were able to implement development while fully enjoying the merits of KMM.

For better or worse, the presentation layer needs to be developed in both operating systems. So, if you are developing an app where you have a limited number of people, one that is small-scale, and would like to create commonalities up to and including UI, then there are probably cases where Flutter or another technology might be better. Still, I feel that there are no cases where KMM per se will turn into a significant debt.

I hope that this example is of help to anyone considering utilizing KMM.

Recruit is currently hiring team members to work with us on many projects. If you are interested, please take a look here.

About the author

Saiki Iijima

“HOT PEPPER GOURMET” Android engineer at Recruit Co., Ltd. and also leader of the Android engineer team for the replacement project.

Recruit Co., Ltd.
Recruit Co., Ltd.
Recruit Co., Ltd. is engaged in human resource and sales promotion in Japan as well as mediation and sales promotion globally. We are focused on creating new value for our society to contribute to a brighter world where all individuals can live life to the fullest.
Go to Corporate Site