Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
iOSエンジニアがKMPで大規模アプリの ロジック共通化をしてうまくできている話 / iOSDC2021
Kenzo Nirasawa
September 18, 2021
Programming
5
4.4k
iOSエンジニアがKMPで大規模アプリの ロジック共通化をしてうまくできている話 / iOSDC2021
iOSDC2021の発表資料です。
https://fortee.jp/iosdc-japan-2021/proposal/6d170404-d2b6-4379-ad9e-19e304eb7a31
Kenzo Nirasawa
September 18, 2021
Tweet
Share
Other Decks in Programming
See All in Programming
Circuit⚡
monaapk
0
200
Swift Concurrency in GoodNotes
inamiy
4
1.3k
中小企業開発事例から見るサーバーレス
seike460
PRO
4
1.5k
TokyoR#103_DataProcessing
kilometer
0
450
あなたと 「|」 したい・・・
track3jyo
PRO
2
1k
Cloudflare Workersと状態管理
chimame
2
450
状態ってなに?🙃
taro28
0
260
How to Fight Production Incidents?
asatarin
0
140
スタック・オーバーフローに コントリビュートしはじめて良かったこと🐣
takuyakikuchi
1
120
Cloudflare WorkersでGoを動かすライブラリを作っている話
syumai
1
290
子育てとEMと転職と
_atsushisakai
1
330
量子コンピュータ時代のプログラミングセミナー / 20221222_Amplify_seminar _route_optimization
fixstars
0
240
Featured
See All Featured
ReactJS: Keep Simple. Everything can be a component!
pedronauck
657
120k
Streamline your AJAX requests with AmplifyJS and jQuery
dougneiner
128
8.8k
Pencils Down: Stop Designing & Start Developing
hursman
114
10k
GraphQLとの向き合い方2022年版
quramy
20
9.8k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
120
29k
Intergalactic Javascript Robots from Outer Space
tanoku
261
26k
Designing with Data
zakiwarfel
91
4.2k
Keith and Marios Guide to Fast Websites
keithpitt
407
21k
The Pragmatic Product Professional
lauravandoore
21
3.4k
Web Components: a chance to create the future
zenorocha
304
40k
Become a Pro
speakerdeck
PRO
6
3.2k
Statistics for Hackers
jakevdp
785
210k
Transcript
iOSエンジニアがKMPで大規模アプリの ロジック共通化をしてうまくできている話 (株)リクルート 韮澤 賢三 浅井 徹 1
はじめに 2
自己紹介 韮澤 賢三(@nirazo) 株式会社リクルート iOSエンジニア歴約7年 ホットペッパーグルメアプリ開発チームリーダー兼アプリリプレイ スプロジェクトリーダー 略歴 2012年4月
Webサービス企業に新卒入社 2015年11月 リクルートライフスタイル中途入社 2019年10月 ホットペッパーグルメ開発チーム参画 3
浅井 徹(@trsxxii) 株式会社リクルート iOSエンジニア歴 6~7年 ホットペッパーグルメアプリ KMP開発チームリーダー 略歴
2014年4月 Webサービス企業に新卒入社 2019年11月 リクルートライフスタイルに中途入社 自己紹介 4 浅井さんの写真だよ
本発表のゴール 5 Kotlin Multiplatformに興味はあるけど踏み切れない、そんな方の不安を解消し、 iOSエンジニアでもやれるんだという気持ちになってもらう
• ホットペッパーグルメについて • Kotlin Multiplatform Projectとは • ホットペッパーグルメとKMP • 我々の不安要素は実際どうだったのか
◦ ロジック共通化はうまくできるのか? ◦ ObjCヘッダーでIFが使いづらいのでは? ◦ DBやUserDefaults、Keychainにアクセスできるのか? ◦ iOSの知識に追加でどんな知識が必要か? • まとめ アジェンダ 6
リクルートは多数のサービスを運営しています 7 メディア&ソリューションSBU HRテクノロジーSBU 人材派遣SBU 販促領域 人材領域 国内派遣 海外派遣
etc... 選択・意思決定を支援する情報サービスを提供し、 「まだ、ここにない、出会い。より速く、シンプルに、もっと近くに」を実現する
ホットペッパーグルメを開発しています 8
Kotlin Multiplatform Projectとは 9
KMPとは - 概要 • Kotlin Multiplatform Project(以後KMP)とは、Kotlinで記述されたコードを 異なるプラットフォーム用にコンパイルできるプロジェクトのこと
10 引用元:https://kotlinlang.org/docs/multiplatform.html
KMPとは - KMM • その中でも、KMPの一つのユースケースである、 iOS/Androidのコード共有を実現することを Kotlin Multiplatform Mobile(KMM)と言う
◦ 今回説明することは厳密にはKMMに関する内容 • FlutterやReactNativeなどとは違い、 ビジネスロジック部分のみを共通化する • あくまでもViewは各プラットフォームで実装する 11 引用元:https://kotlinlang.org/lp/mobile/
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
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
• 前述したApple Frameworkで生成されるバイナリのヘッダーはObjective-Cヘッダーになっている ◦ iOS開発ではObjective-Cヘッダーを通して、Swiftから使用することとなる • できるだけSwiftらしいInterfaceになるように多くのAttributeが指定されている
KMPとは - iOS開発 14 Swiftから使うための命名 Nullable/NonNull指定
ホットペッパーグルメとKMP 15
ホットペッパーグルメとKMP • ホットペッパーグルメアプリはリリースから10年以上が経過し、開発を継続していくに あたっての課題が浮き彫りになってきた ◦ 10年以上が経過した今も大規模な設計変更等は無く、リリース当初の実装に継ぎ足し開発を 行ってきた
16 ソースコードの 肥大化 ソースコードの 複雑化 開発スピードの鈍化 障害防止の 難度上昇
ホットペッパーグルメとKMP • 今後の安定した開発のため、コードリニューアル・リアーキテクチャを決断し、 クロスプラットフォーム技術の検討を実施 ◦ 開発工数の削減 ◦ 予期せぬOS間差分を防ぐことによる品質の安定化
• クロスプラットフォームの中でもKotlin Multiplatformを採用 ◦ UIは各プラットフォームに準拠させたい ◦ Kotlinで書けるためキャッチアップの難易度はそこまで高くないと判断 17
ホットペッパーグルメとKMP • iOS / Android / Shared (KMP担当)の3チーム構成でプロジェクト進行中 ◦
iOS/Androidはそれぞれ最大8名、Sharedは最大4名 18 Android iOS Shared フェーズによってSharedからiOS, Androidへ移籍
KMP採用にあたって、我々も不安がたくさんあった 19 永続化領域やKeychainな どにはアクセスできるのだ ろうか? iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? ちゃんとロジック共通化は
できるのだろうか?(実はif 文がたくさんなんてことは …) Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?
我々の不安要素は実際どうだったのか 20
KMP採用にあたって、我々も不安がたくさんあった 21 永続化領域やKeychainな どにはアクセスできるのだ ろうか? iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? ちゃんとロジック共通化は
できるのだろうか?(実はif 文がたくさんなんてことは …) Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?
ロジック共通化は結局うまくできるのか? • ホットペッパーグルメのアーキテクチャは以下のようになっている ◦ KMPを使用したロジックの共通化部分は赤枠部分 22
ロジック共通化は結局うまくできるのか? 23 細かい変更はあるもののアーキテクチャ図通りに実装ができており、ロジック共通化もうまくいっ ている。
ロジック共通化は結局うまくできるのか? • KMP対象のビジネスロジック部分のコード行数比率を見ると、ほぼすべてのコードを 共通化することに成功している • commonMainの中にはOSによるif文が存在しているが、それもかなり少ない 24 対象
コード行数比率 commonMain 99.13% androidMain 0.45% iosMain 0.42%
ロジック共通化は結局うまくできるのか? 25 • 最も差分が出やすいライブラリ使用部分の一部を共通化しない選択をしている • 同じ機能の3rd Partyライブラリを使う場合に、共通部分にinterfaceを持たせて、 各アプリコードに実装する判断をした
◦ 共通化できないものを無理に共通コードには入れない方針 ◦ interface提供しているライブラリの数も7種類と少ない ※ネットワークや永続化領域へのアクセスなど主要なものは公式ライブラリを使用している commonMain Android専用 ライブラリ iOSアプリ Androidアプリ iOS専用 ライブラリ interface 共通コード interface提供するライブラリの種類 数 ログ系ライブラリ 3種類 社内ライブラリ 1種類 3rd Partyライブラリ 3種類
ロジック共通化は結局うまくできるのか? 26 細かい変更はあるもののアーキテクチャ図通りに実装ができており、ロジック共通化もうまくいっ ている。
KMP採用にあたって、我々も不安がたくさんあった 27 永続化領域やKeychainな どにはアクセスできるのだ ろうか? iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? ちゃんとロジック共通化は
できるのだろうか?(実はif 文がたくさんなんてことは …) Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?
ObjCヘッダーでIFが使いづらい? KMP側の実装やiOS側の実装の工夫により、膨大な工数やアーキテクチャ変更無く回避可能 28 使いづらい部分はあるものの、そもそも機能が動かない・アーキテクチャが崩壊するといったレベ ルの問題は発生していない
ObjCヘッダーでIFが使いづらい? 大きな問題は発生していないものの、そもそもKotlin <-> Obj-Cの変換時の制約のために、 シンプルな実装にできない箇所が存在する • Generics定義が再帰的になる場合、iOSから見るとAnyになってしまう
• 無限アンダースコア問題 • Kotlinのinterface内にメソッドをデフォルト実装するとiOSでは実装を求められてしまう • inline classを解釈できない • クラスが階層的に表現できない問題 • Enum問題 29
ObjCヘッダーでIFが使いづらい? 大きな問題は発生していないものの、そもそもKotlin <-> Obj-Cの変換時の制約のために、 シンプルな実装にできない箇所が存在する • Generics定義が再帰的になる場合、iOSから見るとAnyになってしまう
• 無限アンダースコア問題 • Kotlinのinterface内にメソッドをデフォルト実装するとiOSでは実装を求められてしまう • inline classを解釈できない • クラスが階層的に表現できない問題 • Enum問題 30
• Kotlin側でGenericsが階層構造になっている場合、iOSから見るとAny(id型)になってしまう Generics階層構造でAny問題 31 Generics Generics in Generics
Generics階層構造でAny問題(解決策) • Results<T, S>のTに入る型をジェネリクスを含むクラスをやめて、ジェネリクスを含まない型に変更 することで回避した 32 Genericsをラップするclassを作成して Resultsに入れる
Generics再帰でAny問題 • Issueが上がっているが対応バージョンは未定 ◦ https://youtrack.jetbrains.com/issue/KT-41847 33
無限アンダースコア問題 • 同名・同引数名のメソッドが複数ある場合、Swiftコードでは引数にアンダースコアが入ったメソッド になる 34 引数名にアンダースコアが入ってしまう 同名・同引数名のメソッド
無限アンダースコア問題 • KMPではKotlin <-> Obj-C変換にあたり、コンパイル時の名前空間被りを引数名に アンダースコアをつけることで解消している ◦ Issueは上がっているが対応バージョンは未定
▪ https://youtrack.jetbrains.com/issue/KT-43087 • 我々のコードでは全UseCaseがexecute(input: Input)という統一の名前のメソッドを 持つという規約があったため、この影響を受けてしまった 35
無限アンダースコア問題(解決策) • 引数名をinputからUseCaseに応じたInput名に変更することで名前被りを防いだ 36 UseCase毎にinputの引数名を変 更
ObjCヘッダーでIFが使いづらい? KMP側の実装やiOS側の実装の工夫により、膨大な工数やアーキテクチャ変更無く回避可能 37 使いづらい部分はあるものの、そもそも機能が動かない・アーキテクチャが崩壊するといったレベ ルの問題は発生していない
KMP採用にあたって、我々も不安がたくさんあった 38 永続化領域やKeychainな どにはアクセスできるのだ ろうか? iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? ちゃんとロジック共通化は
できるのだろうか?(実はif 文がたくさんなんてことは …) Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?
DBやUserDefaults、Keychain、SharedPreferenceにアクセスできる? 39 DB、その他ローカルデータ※ 保存領域への値保存・取得は可能 完全な共通化はできないが、設計次第でほぼ共通化することが可能 保存領域 使えるライブラリ DBアクセス
• SQLDelight • Realm ローカルデータアクセス • multiplatform-settings ※ UserDefaults, Keychain, SharedPreferenceを便宜上まとめてローカルデータと呼ぶ
DBへのアクセス • SQLDelightというライブラリを使い、SQLiteをKMPで利用可能 • RealmもKMPで利用できるライブラリを開発中だが、未だα版でありSQLDelightほど 市民権を得ていない ◦ スター数はSQLDelight:
約4100, Realm: 約300 (8/23現在) • ホットペッパーグルメではSQLDelightを採用した 40
SQLDelightの使い方と共通化可否 • DBのインスタンス生成コード(各OS1行程度)以外の処理は全て共通化が可能! 41 やること概要 やること詳細 共通化可否 スキーマ定義・SQL文定義 スキーマ定義ファイルに
SQL文を記述 可 DBのインスタンス作成 OS毎に初期化処理を実装 不可 DB操作用コード実装 自動生成されたメソッド経由で DB操作処理を 実装 可
SQLDelightの使い方 • DBのインスタンス作成をOS毎に実装 ◦ プラットフォーム毎にDriverが用意されているため、ここは共通化不可 42 expectでdb生成メソッド定義 androidMain
iosMain
SQLDelightの使い方 • sqファイルから自動生成されたメソッドを使ってアプリからDBを操作するコードを書く 43 “テーブル名”Queries経由で、sq ファイルに定義したメソッドを呼 び出せる
ローカルデータアクセスの共通化可否 44 • multiplatform-settingsというライブラリでアクセス可能 • 暗号化無しの場合はコードを完全に共通化可能 • 暗号化有りの場合もオブジェクトのインスタンス生成コード(数行程度)以外の処理は全て共通化が
可能 やること概要 共通化可否 UserDefaults, SharedPreference オブジェクトのインスタンス生成 可 オブジェクトへのRead, Write処理 可 Keychain, 暗号化有り SharedPreference オブジェクトのインスタンス生成 不可 オブジェクトへのRead, Write処理 可
UserDefaults、SharedPreference(暗号化無し) • シンプルにSettingsインスタンスを生成し、put, getするのみ ◦ 共通化も可能 45 Settingsのインスタンスを作成
シンプルにget, put
Keychain、SharedPreference(暗号化有り) • expect classとしてSettings型のプロパティを持つクラスを定義し、OS毎に初期化処理を実装 46 expectSettings変数 iosMain androidMain Settingsのインスタンスの初期化
Keychain、SharedPreference(暗号化有り) • アクセス用の共通クラスからアクセス 47 各プラットフォーム毎にactualで実装 したSettingsが適用される
Keychain、SharedPreference(暗号化有り)取り扱い時の注意事項 48 • KeychainはまだExperimentalな機能 ◦ とはいえtouchlab※1 のブログでは「数多くのプロジェクトで導入しているが不具合は 上がっていない」との記載有り
• Access Groupの設定は未対応 ◦ 複数Access Groupに対応したアプリでの挙動が保証できない • kSecAttrAccessibleの指定不可 ◦ keychainへのアクセスタイミングに制限をかけたい場合は使用できないため、iOSアプリで実装する必要 がある ※1: KMM開発のエキスパート集団。KMMテンプレートプロジェクトや技術ブログ運営など、KMMに関す る情報を幅広く取り扱っている
DBやUserDefaults、Keychain、SharedPreferenceにアクセスできる? 49 DB、その他ローカルデータ保存領域への値保存・取得は可能 完全な共通化はできないが、設計次第でほぼ共通化することが可能
KMP採用にあたって、我々も不安がたくさんあった 50 永続化領域やKeychainな どにはアクセスできるのだ ろうか? iOS開発の知識以外に どんな知識を身につける 必要があるのだろうか? ちゃんとロジック共通化は
できるのだろうか?(実はif 文がたくさんなんてことは …) Objective-Cのヘッダー だ からSwiftから使いづらくて 嫌になるんじゃないだろう か?
Kotlin、Gradle、KMP対応ライブラリの知識が必要。ただし、習得しながら対応を進めることも可能。 iOSの知識に追加でどんな知識が必要か? ※僕たちがKMPを使ったコードリニューアル・リアーキテクチャを1年以上続けてきて感じたことです 51 Kotlin ・コードを書くのに必要 Gradle ・プロジェクトの初期設定 ・Kotlinバージョンアップやライブラリ導入
・Gradle SyncやBuildなど KMP対応ライブラリ ・KMP対応の公式ライブラリなどの使用
Kotlinの知識について。 • KMPはKotlinで記述するのでiOSエンジニアでもKotlinを書く必要がある • しかし、AndroidのUIに関する知識はほとんど不要 • ビジネスロジックを書くためのKotlin知識のみが必要
※KotlinはSwiftの言語機能と似ている点も多く、すぐに慣れると思う(個人的な感想です) iOSの知識に追加でどんな知識が必要か? 52
Gradleの知識について。 • KMPの設定はGradleで行われ、Kotlinのバージョンアップやライブラリ導入などで記述が必要になる ◦ 特に初期段階は、モジュール構成を変更したり、設定を見直したりすることが多くなる • また、Gradle SyncやBuildを使った開発の流れを把握しておく必要もあり
• 基本的なものはチュートリアルやサンプルがあるので、やりながら習得すれば良い iOSの知識に追加でどんな知識が必要か? 53
KMP対応ライブラリの知識について。 • 共通コード部分ではKMPに対応したライブラリを使用することになる ◦ それらの多くは、JetBrainsが公式でライブラリを提供してくれている ▪ KtorやSerialization、Coroutinesなど
• これらのライブラリの使用方法などを理解しておく必要がある • ただし、これらは初めから知識をつけておく必要はなく、ライブラリを使用しながら習得すれば良い iOSの知識に追加でどんな知識が必要か? 54
Androidの機能(SharedPreferencesなど)の知識については・・・ • 知識があることに越したことはないが、 必須ではない • ライブラリを使用する上では、理解しておいたほうが良いだろう iOSの知識に追加でどんな知識が必要か? 55
Kotlin、Gradle、KMP対応ライブラリの知識が必要。ただし、習得しながら対応を進めることも可能。 iOSの知識に追加でどんな知識が必要か? ※僕たちがKMPを使ったコードリニューアル・リアーキテクチャを1年以上続けてきて感じたことです 56
まとめ 57
問題なく実装できている • 多少不便を感じる箇所や運用でカバーしている部分はあるものの、大規模アプリでも問題無く開発 できている ◦ (少なくとも我々のアプリでは)実現できない仕様は現状無い ◦ 想定したとおりのコード共通化ができ、適切な責務分割ができている
• iOSエンジニアでも大きくつまづくこと無く実装できている 58
KMPの導入事例を増やせば情報共有の機会も増える! 踏み切れなかったあなたもぜひチャレンジしてみましょう! 少しずつでも導入してみて、KMPを盛り上げましょう✨ 59
経験者がいないと不安…であれば、 ぜひ一緒に開発しましょう! 60 興味がある方はコチラ!
参考 • 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
Appendix 62
ロジック共通化についての補足説明 63
• 例えば、APIへの認証キーのような共通化できない定義の ものは、expect/actualを使って解決することで共通化でき なくとも可読性が保たれる • 先程のiosMain/androidMainに定義されている大半のコー ドはこのような共通化できない定義自体が記述されている ロジック共通化は結局うまくできるのか? 64
ApiKeyを使用する際は、iOS/Androidを意 識することなく使用できる expect/actual定義
ロジック共通化は結局うまくできるのか? • 例えば、共通部分からFirebase Realtime Databaseにアクセスする場合、RealtimeDatabaseClientと いうinterfaceを使うようにしている • その実装はiOS/Androidに存在しており、インスタンスをinjectする仕組み
65 commonMainはinterfaceを提供 iOSアプリがinterfaceを実装 Androidアプリがinterfaceを実装
ObjCヘッダーによるIFの使いづらさについての補足説明 66
Kotlin側のinterface内にメソッドのデフォルト実装をすると、iOSではprotocolのrequired functionに変換さ れてしまい実装を求められてしまう interface内にデフォルト実装問題 67 Interfaceのデフォルト実装
interface内にデフォルト実装問題 68 iOSではデフォルト実装が適用されず、実装を強制される
interface内にデフォルト実装問題(解決策) • Kotlinの拡張関数機能(Swiftのextensionのようなもの)を使い、デフォルト実装にしていたものを拡 張関数として実装 ◦ interfaceのデフォルト実装だったメソッドをAnalyticsClientの拡張関数として実装すると、iOSで実装を強 制されることが無くなる 69 拡張関数として実装
inline class問題 • Obj-Cでinline class(inline展開可能なクラス)が解釈できず、iOSからはラッパークラスを用意する必 要がある • 日付を扱うライブラリとしてklockを使用しているが、klockのDateTimeやDate, Timeはinline classで
実装されているためiOSで日付時間を扱うことができなかった。 70
inline class問題(解決策) • klockにはinline classをラップしたWDateTimeやWDateが実装されているため、それらをiOSから見え るようにし、iOSからはラップされたクラスを使用するようにした 71
クラスが階層的に表現できない問題 • data classを階層構造にした場合(要確認)、型名が親のデータクラス名と連結された名前になる 72 class > class >
data class
クラスが階層的に表現できない問題 • data classを階層構造にした場合(要確認)、型名が親のデータクラス名と連結された名前になる 73 正しく階層関係になっている outputChildとoutputGrandChildがひと繋ぎに なっている
クラスが階層的に表現できない問題(解決策) • data classを使わないしか解決策は無いが利便性は落ちるため、我々のプロジェクトでは許容とし ている 74
Enum問題 • SharedKotlinEnumのサブクラスになってしまい、NS_ENUMにならない 75
Enum問題 • enumの網羅性を判定できず、defaultの記述が必須となる 76
Enum問題 • NS_ENUMを出力するFeature Requestは上がっているが、対応バージョンは未定 ◦ https://youtrack.jetbrains.com/issue/KT-48068 77
SQLDelightの使い方補足 78
SQLDelightの使い方 • SQLDelightプラグインを読み込んでDatabaseを定義 ◦ 共通モジュールのbuild.gradleに記載(共通化可能) 79
SQLDelightの使い方 • .sqファイルにSQL文を定義しビルドタスクを実行 ◦ SQLDelightがDB操作のためのKotlinファイルを自動生成する ◦ スキーマ定義や使うSQLがOS間で同一であれば共通化可能
80 テーブルのCREATE 各種SQLと、Kotlinから呼ぶ際 のメソッド名定義
SQLDelight補足 • CoroutineのFlowもサポートされているからDBの値の変更監視・通知も実現可能 81