2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
Koin MPP入門(全1記事)
リンクをコピー
記事をブックマーク
三好文二郎氏(以下、三好):「Koin MPP入門」ということで、お話ししようと思います。チームラボ株式会社の三好と申します。
簡単に自己紹介をします。Androidエンジニアになって3年ちょっと経ちました。主に「Spring」ですが、JVMのserver frameworkも触ります。SNSのアイコンは、シンバルだったりブロッコリー頭だったりするので、ぜひ探してみてください。よろしくお願いします。
まず簡単に「Koin」について紹介します。KoinはDSLで書ける軽量なDIコンテナライブラリです。今日は、すごく難しい使い方を紹介するのではなく、Multiplatformができるようになったので、簡単な使い方を紹介しようと思っています。
Koinは、Androidでよく使われるDIライブラリの「Dagger」とは違って、実行時に依存性のGraphの構築をします。内部では、instanceをhashMapで管理しています。
Android用の拡張、例えばViewModel、Service、WorkManager、Composeなどの対応が進んでいます。Serverでいえば、ケイター用のライブラリもあるのですが、今日はあまり触れません。3.0.0からMultiplatformに対応しました。
最初に基本的な使い方を紹介します。一番左の、sampleModuleという定数を宣言します。その中で、DSLで依存性を宣言していくのですが、singleで囲うとRepositoryのinstanceがsingletonで管理されます。
factoryで宣言すると、Factoryクラスのinstanceが毎回生成されます。あとでもう少し詳しく説明しますが、あるinstanceのlifecycleを、あるクラスのinstanceのlifecycleにひもづける時に、scopeで宣言します。
あるクラスにconstructor injectionをしたい場合ですが、引数は、get、もしくはpage injectionの対応をしています。また、あるクラスの中でフィールドとして使いたい時には、by injectのDelegateで、instanceを引っ張ってきます。
宣言を書いたら、startKoinという関数を呼び出して、先ほど定義したModuleをmodulesの中に書きます。こうすることで、instanceのhashMapで管理してくれるようになります。
次に、Type Bindingについて説明します。Koinは、KClassをよしなにStringのIDにして、それをkeyにしてhashMapで管理しています。
1つのmapに対して、複数のkeyを設定することもできます。一番上のコードでいえば、singel{ServiceImpl()}と宣言すると、ServiceImplクラスのinstanceを取ってくる時にしか引っ掛かりません。
2番目の、singleのジェネリクスのServiceインターフェイスにすると、ServiceインターフェイスでしかServiceImplクラスのinstanceが引っ張ってこられません。
single{ServiceImpl() as Service}というかたちで、型をダウンキャストしてしまうと、Serviceクラスでしか引っ張ってこられません。
single{ServiceImpl()} bind Service、インターフェイスというかたちに宣言すると、ServiceImplクラスとServiceインターフェイスの両方に引っ掛かって、instanceを取得できるようになります。
先ほどあとで少し説明しますと話した、Scopeですね。instanceのlifecycleを、あるクラスのinstanceのlifecycleにひもづけます。scopeのownerクラスに対しては、KoinScopeComponentというインターフェイスがあるので、それの実装が必要です。Moduleの宣言は、右に書いてあるかたちになります。
ScopeOwnerクラスを、コンストラクタで普通にinstanceを生成すると、今だとInstancePrinterというクラスのinstanceを生成して、先ほど作ったScopeOwnerクラスのinstanceを破棄します。
今だとすごくシンプルな書き方をしているので、ほぼ意味はないのですが、一緒にInstancePrinterをKoinのmapから削除できます。
次に、Qualifierです。先ほどKoinはKotlinクラスのmapで管理していると言ったのですが、それに余分な情報を追加してinstance管理させることができます。
付与できる情報は、StringとTypeとEnumの3種類です。namedという関数、もしくはqualifireのジェネリクスでクラスを指定。もしくは、Enumに対して、qualifireという拡張関数が定義されているので、それを使ってEnumを指定して、同一クラスを複数種類管理させることができます。
パッとコード見てもらうとわかると思うのですが、拡張関数とDelegateがすごくたっぷりあるので、特にKotlin側で簡単に使う分にはすごく便利です。
「Swift」からはすごく呼びづらいですね。Swiftから呼びづらいところですが、「Kotlin/Native」は、KotlinクラスからObjective-Cのクラスだったり、Objective-Cのプロトコルだったりします。
その際に変換が入っていて、単純なKotlinクラスではなくなってしまっているので、とても使いづらくなっています。
例えばですが、型でQualifireを作る時は引数がKClassになっています。DIコンテナからinstanceを取得する時には、KClassをkeyにしているので、KClassを指定してinstanceを引っ張ってきます。
Qualifireも同様に、KClassをQualifireに変換するというかたちなので、基本的にKClassが必要になってきます。
そのため、Objective-CのクラスやプロトコルをKotlinのクラスに変換できるkotlinx.cinterop関数が定義されています。getOriginalKotlinClassの引数は、ObjCClass、もしくはObjCProtocolの2種類です。
実際にどう使っていくのかですが、Multiplatform側に、今書いているような拡張関数を作成してみましょう。
ObjCClassを引数に受け取って、そこからKClassに変換して、Koinからinstanceを引っ張ってきて返す、もしくはプロトコルを受け取って、Kotlinクラスに変換して、Koinからinstanceを引っ張ってくるという拡張関数を定義します。
これはSwiftのコードですが、そうすることでKoinのinstanceからスッキリ呼び出せるようになりました。ただ、Force Castを毎回書かなければいけないというのは、少し冗長に感じます。
もう1個、Swift側で拡張関数を書きます。プロトコルの場合は上、クラスの場合は下ですね。簡単な拡張関数を作成すると、もっとスッキリ呼び出せるようになります。
コンテナから呼び出すほうはおしまいです。
Qualifireを作成するのも同様に、ObjCProtocol、もしくはObjCClassを引数にして、もとのKotlinクラスを変換して、それぞれTypeQualifireを作成する関数を書くと、スッキリ呼び出せるようになります。
メインのKoinの使い方の話はおしまいですが、よくある管理方法だと、Multiplatformのリポジトリが別管理になっていて、publishをしたけれど、DIの定義が間違っていてクラッシュすることがあります。それを直すためにもう1回直して、publishしてartifactを出さなきゃいけない、みたいなことがあると思うのですが、Koinは、Android側でModule定義のテストが書けます。
久保出さんの発表でもあったのですが、主要なモックのlibraryがKotlin/Nativeに対応していないので、JVMだけでテストできます。「koin-test-junit4」か「koin-test-jnit5」、「mockito」か「mockk」を組み合わせてテストを書けます。
テストは、KoinTestというインターフェイスがあるので、それを実装して、MockProviderRuleを当てはめる必要があります。
実際のテストですが、下のcheckModelesのDSLの中に、作成したModuleの定義を書いて、JUnitで実行させるだけです。
以上で発表はおしまいです。サンプルは「GitHub」のリポジトリに上げているので、ぜひ見てみてください。パッと動かせるようになっていると思うので、試してもらえればなと思います。
ご清聴ありがとうございました。
司会者:三好さんありがとうございます。1点、久保出さんから質問です。「Mobile.IOS、Mobile.ANDROIDは、KoinのAPIですか?」。これに関してはいかがでしょうか?
三好:いえ、単なるEnumの定義です。ちょっとわかりやすくなかったかもしれませんが、普通の単なるEnumです。
司会者:なるほど、ありがとうございます。
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.12
今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05