Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSエンジニアがKMPで大規模アプリの ロジック共通化をしてうまくできている話 / iOSDC2021

Kenzo Nirasawa
September 18, 2021

iOSエンジニアがKMPで大規模アプリの ロジック共通化をしてうまくできている話 / iOSDC2021

Kenzo Nirasawa

September 18, 2021
Tweet

Transcript

  1. 自己紹介
 韮澤 賢三(@nirazo)
 株式会社リクルート 
 iOSエンジニア歴約7年
 ホットペッパーグルメアプリ開発チームリーダー兼アプリリプレイ スプロジェクトリーダー
 略歴
 2012年4月

    Webサービス企業に新卒入社 
 2015年11月 リクルートライフスタイル中途入社 
 2019年10月 ホットペッパーグルメ開発チーム参画 
 3
  2. 浅井 徹(@trsxxii)
 株式会社リクルート 
 iOSエンジニア歴 6~7年
 ホットペッパーグルメアプリ KMP開発チームリーダー 
 略歴


    2014年4月 Webサービス企業に新卒入社 
 2019年11月 リクルートライフスタイルに中途入社 
 自己紹介
 4 浅井さんの写真だよ
  3. • ホットペッパーグルメについて
 • Kotlin Multiplatform Projectとは
 • ホットペッパーグルメとKMP
 • 我々の不安要素は実際どうだったのか

    
 ◦ ロジック共通化はうまくできるのか? 
 ◦ ObjCヘッダーでIFが使いづらいのでは? 
 ◦ DBやUserDefaults、Keychainにアクセスできるのか? 
 ◦ iOSの知識に追加でどんな知識が必要か? 
 • まとめ
 アジェンダ
 
 6
  4. リクルートは多数のサービスを運営しています
 7
  メディア&ソリューションSBU 
 HRテクノロジーSBU
 人材派遣SBU
 販促領域
 人材領域
 国内派遣
 海外派遣


    etc...
 選択・意思決定を支援する情報サービスを提供し、
 「まだ、ここにない、出会い。より速く、シンプルに、もっと近くに」を実現する
  5. KMPとは - KMM
 • その中でも、KMPの一つのユースケースである、 iOS/Androidのコード共有を実現することを 
 Kotlin Multiplatform Mobile(KMM)と言う

    
 ◦ 今回説明することは厳密にはKMMに関する内容
 
 • FlutterやReactNativeなどとは違い、 
 ビジネスロジック部分のみを共通化する 
 • あくまでもViewは各プラットフォームで実装する 
 11 引用元:https://kotlinlang.org/lp/mobile/ 

  6. KMPとは - プラットフォーム固有API
 12 • 共通コードはcommonMain、共通化できないようなプラットフォーム固有のコードは、 iosMain/androidMainというフォルダに定義できる ※
 • expectというinterfaceのようなコードをcommonMainに記述し、

    
 actualを使って各プラットフォーム固有のiosMain/androidMainに実際の処理を記述する 
 ※実際にはbuild.gradle.ktsで設定したフォルダ名となるがcommonMain/iosMain/androidMainが一般的 
 androidMain
 iosMain
 引用元:https://kotlinlang.org/docs/multiplatform.html 

  7. KMPとは - iOS開発
 • 共通コードはKotlin/JVMでAndroid/Java Archiveに、 
 Kotlin/NativeでApple Frameworkにビルドされる 


    • KMPでは、Apple Frameworkを作成するGradle Taskが準備されており、 
 これをXcodeのBuild Phasesで設定をすることでiOSアプリの開発が出来るようになる 
 13 Android/Java Archive (.aar / .jar) shared code Apple Framework (.framework) Kotlin/JVM
 Kotlin/Native
 引用元:https://kotlinlang.org/docs/mobile/integrate-in-existing-app.html 

  8. ホットペッパーグルメとKMP
 • 今後の安定した開発のため、コードリニューアル・リアーキテクチャを決断し、 
 クロスプラットフォーム技術の検討を実施 
 ◦ 開発工数の削減
 ◦ 予期せぬOS間差分を防ぐことによる品質の安定化

    
 
 • クロスプラットフォームの中でもKotlin Multiplatformを採用 
 ◦ UIは各プラットフォームに準拠させたい 
 ◦ Kotlinで書けるためキャッチアップの難易度はそこまで高くないと判断 
 17
  9. ホットペッパーグルメとKMP
 • iOS / Android / Shared (KMP担当)の3チーム構成でプロジェクト進行中 
 ◦

    iOS/Androidはそれぞれ最大8名、Sharedは最大4名 
 18 Android iOS Shared フェーズによってSharedからiOS, Androidへ移籍

  10. KMP採用にあたって、我々も不安がたくさんあった
 19 永続化領域やKeychainな どにはアクセスできるのだ ろうか?
 iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? 
 ちゃんとロジック共通化は

    できるのだろうか?(実はif 文がたくさんなんてことは …)
 Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?

  11. KMP採用にあたって、我々も不安がたくさんあった
 21 永続化領域やKeychainな どにはアクセスできるのだ ろうか?
 iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? 
 ちゃんとロジック共通化は

    できるのだろうか?(実はif 文がたくさんなんてことは …)
 Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?

  12. ロジック共通化は結局うまくできるのか?
 25 • 最も差分が出やすいライブラリ使用部分の一部を共通化しない選択をしている 
 • 同じ機能の3rd Partyライブラリを使う場合に、共通部分にinterfaceを持たせて、 
 各アプリコードに実装する判断をした

    
 ◦ 共通化できないものを無理に共通コードには入れない方針 
 ◦ interface提供しているライブラリの数も7種類と少ない 
 ※ネットワークや永続化領域へのアクセスなど主要なものは公式ライブラリを使用している 
 commonMain
 Android専用
 ライブラリ
 iOSアプリ
 Androidアプリ
 iOS専用
 ライブラリ
 interface
 共通コード
 interface提供するライブラリの種類 
 数
 ログ系ライブラリ
 3種類
 社内ライブラリ
 1種類
 3rd Partyライブラリ
 3種類

  13. KMP採用にあたって、我々も不安がたくさんあった
 27 永続化領域やKeychainな どにはアクセスできるのだ ろうか?
 iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? 
 ちゃんとロジック共通化は

    できるのだろうか?(実はif 文がたくさんなんてことは …)
 Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?

  14. ObjCヘッダーでIFが使いづらい?
 大きな問題は発生していないものの、そもそもKotlin <-> Obj-Cの変換時の制約のために、 
 シンプルな実装にできない箇所が存在する 
 • Generics定義が再帰的になる場合、iOSから見るとAnyになってしまう 


    • 無限アンダースコア問題
 • Kotlinのinterface内にメソッドをデフォルト実装するとiOSでは実装を求められてしまう 
 • inline classを解釈できない
 • クラスが階層的に表現できない問題 
 • Enum問題
 29
  15. ObjCヘッダーでIFが使いづらい?
 大きな問題は発生していないものの、そもそもKotlin <-> Obj-Cの変換時の制約のために、 
 シンプルな実装にできない箇所が存在する 
 • Generics定義が再帰的になる場合、iOSから見るとAnyになってしまう 


    • 無限アンダースコア問題
 • Kotlinのinterface内にメソッドをデフォルト実装するとiOSでは実装を求められてしまう 
 • inline classを解釈できない
 • クラスが階層的に表現できない問題 
 • Enum問題
 30
  16. 無限アンダースコア問題
 • KMPではKotlin <-> Obj-C変換にあたり、コンパイル時の名前空間被りを引数名に 
 アンダースコアをつけることで解消している 
 ◦ Issueは上がっているが対応バージョンは未定

    
 ▪ https://youtrack.jetbrains.com/issue/KT-43087 
 • 我々のコードでは全UseCaseがexecute(input: Input)という統一の名前のメソッドを 
 持つという規約があったため、この影響を受けてしまった 
 
 35
  17. KMP採用にあたって、我々も不安がたくさんあった
 38 永続化領域やKeychainな どにはアクセスできるのだ ろうか?
 iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? 
 ちゃんとロジック共通化は

    できるのだろうか?(実はif 文がたくさんなんてことは …)
 Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?

  18. SQLDelightの使い方と共通化可否
 • DBのインスタンス生成コード(各OS1行程度)以外の処理は全て共通化が可能! 
 41 やること概要 やること詳細 共通化可否 スキーマ定義・SQL文定義 スキーマ定義ファイルに

    SQL文を記述 可 DBのインスタンス作成 OS毎に初期化処理を実装 不可 DB操作用コード実装 自動生成されたメソッド経由で DB操作処理を 実装 可
  19. ローカルデータアクセスの共通化可否
 44 • multiplatform-settingsというライブラリでアクセス可能 
 • 暗号化無しの場合はコードを完全に共通化可能 
 • 暗号化有りの場合もオブジェクトのインスタンス生成コード(数行程度)以外の処理は全て共通化が

    可能
 やること概要 共通化可否 UserDefaults, SharedPreference オブジェクトのインスタンス生成 可 オブジェクトへのRead, Write処理 可 Keychain, 暗号化有り SharedPreference オブジェクトのインスタンス生成 不可 オブジェクトへのRead, Write処理 可
  20. Keychain、SharedPreference(暗号化有り)取り扱い時の注意事項
 48 • KeychainはまだExperimentalな機能 
 ◦ とはいえtouchlab※1 のブログでは「数多くのプロジェクトで導入しているが不具合は 
 上がっていない」との記載有り

    
 • Access Groupの設定は未対応
 ◦ 複数Access Groupに対応したアプリでの挙動が保証できない 
 • kSecAttrAccessibleの指定不可
 ◦ keychainへのアクセスタイミングに制限をかけたい場合は使用できないため、iOSアプリで実装する必要 がある
 ※1: KMM開発のエキスパート集団。KMMテンプレートプロジェクトや技術ブログ運営など、KMMに関す る情報を幅広く取り扱っている 

  21. KMP採用にあたって、我々も不安がたくさんあった
 50 永続化領域やKeychainな どにはアクセスできるのだ ろうか?
 iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? 
 ちゃんとロジック共通化は

    できるのだろうか?(実はif 文がたくさんなんてことは …)
 Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?

  22. Kotlinの知識について。
 • KMPはKotlinで記述するのでiOSエンジニアでもKotlinを書く必要がある 
 • しかし、AndroidのUIに関する知識はほとんど不要 
 • ビジネスロジックを書くためのKotlin知識のみが必要 


    ※KotlinはSwiftの言語機能と似ている点も多く、すぐに慣れると思う(個人的な感想です) 
 iOSの知識に追加でどんな知識が必要か?
 52
  23. KMP対応ライブラリの知識について。 
 • 共通コード部分ではKMPに対応したライブラリを使用することになる 
 ◦ それらの多くは、JetBrainsが公式でライブラリを提供してくれている 
 ▪ KtorやSerialization、Coroutinesなど

    
 • これらのライブラリの使用方法などを理解しておく必要がある 
 • ただし、これらは初めから知識をつけておく必要はなく、ライブラリを使用しながら習得すれば良い 
 iOSの知識に追加でどんな知識が必要か?
 54
  24. 参考
 • https://www.recruit.co.jp/service/gourmet/02/index.html
 • https://dev.to/touchlab/encrypted-key-value-store-in-kotlin-multiplatform-2hnk
 • https://kotlinlang.org/docs/multiplatform.html
 • https://kotlinlang.org/lp/mobile/
 •

    https://kotlinlang.org/docs/mobile/connect-to-platform-specific-apis.html
 • https://www.irasutoya.com/2014/09/blog-post_849.html
 • https://carbon.now.sh/
 • https://touchlab.co/
 • https://github.com/cashapp/sqldelight
 • https://github.com/realm/realm-kotlin
 • https://github.com/russhwolf/multiplatform-settings
 • https://github.com/ktorio/ktor
 • https://github.com/Kotlin/kotlinx.serialization
 • https://github.com/Kotlin/kotlinx.coroutines
 61