見出し画像

Dagger 勉強日記(第1話) - Dependency Injection

今年はDaggerを使った開発をするかもしれないので、正月休みで時間と心に余裕があるときにDaggerを勉強してみようと思いました。このNoteはそのメモになります。

この記事自体はチュートリアルではありません。GoogleのオフィシャルチュートリアルCodeLabのDagger編で勉強を進めたときに私が引っかかった場所、特に集中して覚えたり、考えたりした箇所、をまとめたものになります。後で私の会社のメンバーがCodeLabでDaggerを勉強するときに学習効果を高める補助的な資料となるようなものをイメージして書きました。

避けてきたDagger

DroidKaigiなどで数年前からよくトピックになるDaggerですが、まぁ、いつか案件で必要になったらやろうくらいに思って先送りしてきていました。
2年ほど前、あるクライアントから、開発会社がどうしてもバグを直せなくなって行き詰まってしまったアプリがあるので見てくれないかという依頼がありました。
コードを見てみるとDaggerを使ってかかれていました。どのインスタンスがどのタイミングで初期化されているのかコードを読んでいてもよくわからず、デバッガーを使ってインスタンスの初期化のタイミングを見てみたところ、すごい変なところでいろいろなインスタンスが初期化されていてびっくりしました。自分だったらここではまだこれを初期化しなくてもいいんじゃないかというところで初期化されているものが多く、開発者はこれをわかって書いているのかな。。という感想を持ちました。
このプログラムを書いた人は、自分が何を書いていのるかすでにわからなくなっているのでは?、というのがコードから読み取れました。
この案件では行き詰まっている箇所だけを3日使って見てみましょう、ということになったので、行き詰まっている箇所だけDaggerを使わない方法にまず分離し、マルチスレッドとスレッド間でのオブジェクトの初期化と受け渡しに問題があったのでそこを修正しました。
この経験からDaggerに対してネガティブな印象を持ってしまい、その後また2〜3年間Daggerの放置が続きます。


重い腰を上げてのDagger勉強開始

2022年元旦、から4日過ぎた1月4日、Daggerの勉強を開始しました。数ヶ月前にCodeLabを漁っていた時にDaggerのチュートリアルがあることを知って目をつけていたので、そのGoogleのオフィシャルチュートリアル集CodeLabで勉強を始めました↓

見て見ぬ振りをしてきたDependency Injection

CodeLabを読み始めてすぐ、DI - Dependency Injectionという言葉がでてきます。Daggerとセットで登場してくるこの言葉も、今まで見て見ぬ振りというか、知ったフリをしてやり過ごして来た言葉です。
Dependency Injection、という英語から依存関係を注入するということだと思っただけで、その後、何も調べたりしたことのない言葉だったので、まずはGoogleのAndroidの公式ドキュメントでDependency Injectionを説明しているところをしっかり読んでみようと思い、下のサイトをいつもは流し読みする癖をぐっと堪えて最初から最後まで読んでみました。

(私は新しい技術の勉強をするときは本家の情報ソース、英語の情報ソースを当たるようにしています。技術を勉強する前のステップで、その技術を勉強する意味があるのか、その技術を持った人がどんなことを発信しているのか、を調査するときは日本語の情報ソースも見ますが、本腰を入れて勉強するぞと決めたら、できるだけ源流に近い英語の情報ソースを見るようにしています。)

このサイトを読んでみると、今まで思っていたDependency Injection = 依存関係の注入、つまり依存関係の挿入、という部分に間違いはないようでした。
ひとまず今までの知ったかぶりも大きく外してなかったということでホットしました。
今までDI = 「依存関係の挿入」ということはわかっていましたが、じゃあいつ?どのように?という部分については、なにかDaggerと絡めてDIが語られるときはなにか特別なものがあるのだろうと思っていましたが、
上サイトの最初の方に、下のように書かれていました。

There are two major ways to do dependency injection in Android:

Constructor Injection. This is the way described above. You pass the dependencies of a class to its constructor.

Field Injection (or Setter Injection). Certain Android framework classes such as activities and fragments are instantiated by the system, so constructor injection is not possible. With field injection, dependencies are instantiated after the class is created. The code would look like this:

ようやくすると、依存関係が挿入されるのは、コンスタントを介してか、セッターメソッドなどをつかってオブジェクトのプラパティにセットされたとき、と書いてあります。
「なんだ、やっぱり、そうだよな」と内心ホッとしました。

どうやら私達が普段Androidアプリを作る時に自然に行っている依存関係の挿入、もっとざっくりいうとオブジェクトの受け渡し、のことをDependency Injectionと理解して問題なさそうです。

もう少し読み進めると、Daggerというのは、この依存関係の挿入を、自動でやってくれるもの、のようです。
まだ、この”自動で”の意味がつかめませんが、さらに読みすすめると、

There are libraries that solve this problem by automating the process of creating and providing dependencies. They fit into two categories:

- Reflection-based solutions that connect dependencies at runtime.

- Static solutions that generate the code to connect dependencies at compile time.

とあります。
要約すると、自動で依存関係の挿入をしてくれるライブラリがいくつかあり、

  • 実行時に依存関係を挿入するReflection-basedソリューション

  • コンパイル時に依存関係を挿入するStaticソリューション


という2つの流派があるようです。
そして、下に書かれているように、DaggerはStaticソリューション、つまりコンパイル時に依存関係を挿入するタイプのライブラリのようです。

Dagger is a popular dependency injection library for Java, Kotlin, and Android that is maintained by Google. Dagger facilitates using DI in your app by creating and managing the graph of dependencies for you. It provides fully static and compile-time dependencies addressing many of the development and performance issues of reflection-based solutions such as Guice.

(一方、Reflection-baseのソリューションにはGuiceというライブラリが有名なことも書かれています。今回はDaggerだけでお腹いっぱいになりそうなので無視しました。)

ここまでは今までの想定というか知ったかぶりとそんなに違いがなかったので安心して一旦CodeLabのことを忘れて、席を立ちました。

第2話に続く。


追記

CodeLabを終えてわかったのは、この「Daggerはコンパイル時に依存関係を挿入するStaticソリューション」ということです。
CodeLabの演習をしていると、何度も、演習のステップで追加したコードによって依存関係が紐付いていくのがあたかも実行時にダイナミックで行われるんじゃないかという錯覚に駆られます。
演習中も、今作っている依存関係、特にアプリケーショングラフ、という依存関係の中心となるものがでてくるのですが、こういうものが全部コンパイル時に作成されているんだ、というイメージを持って演習をやると理解度が変わってくると思いました。

この記事が気に入ったらサポートをしてみませんか?