
2025.02.06
ポンコツ期、孤独期、成果独り占め期を経て… サイボウズのプロマネが振り返る、マネージャーの成長の「4フェーズ」
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です。
司会者:なるほど、ありがとうございます。
2025.02.06
すかいらーく創業者が、社長を辞めて75歳で再起業したわけ “あえて長居させるコーヒー店”の経営に込めるこだわり
2025.02.03
「昔は富豪的プログラミングなんてできなかった」 21歳で「2ちゃんねる」を生んだひろゆき氏が語る開発の裏側
2025.02.03
手帳に書くだけで心が整うメンタルケアのコツ イライラ、モヤモヤ、落ち込んだ時の手帳の使い方
2025.01.30
2月の立春までにやっておきたい手帳術 「スケジュール管理」を超えた、理想や夢を現実にする手帳の使い方
2025.02.04
日本企業にありがちな「生産性の低さ」の原因 メーカーの「ちょっとした改善」で勝負が決まる仕組みの落とし穴
2025.02.05
「納得しないと動けない部下」を変える3つのステップとは マネージャーの悩みを解消する会話のテクニック
PR | 2025.02.07
プロジェクトマネージャーは「無理ゲーを攻略するプレイヤー」 仕事を任せられない管理職のためのマネジメントの秘訣
2025.01.29
社内会議は「パワポ」よりも「ドキュメントの黙読」が良い理由 Amazon元本社PMが5つのポイントで教える、資料の書き方
2025.01.31
古い手帳から新しい手帳への繰り越し方 手帳を買い換えたら最初に書き込むポイント
2025.01.07
1月から始めたい「日記」を書く習慣 ビジネスパーソンにおすすめな3つの理由