Gradle使ってて「implementation」とか「runtimeOnly」とかあるけど、これ何が違うんだ??となったのでメモ。
依存のさせ方 | 意味 |
implementation | 依存関係を定義する。一番一般的なもの。 |
api | implementationとベースは一緒だが、依存が伝播する |
runtimeOnly | コンパイルする時には要らないけど、実行時には必要なやつ。 |
compileOnly | 実行する時には要らないけど、コンパイル時には必要なやつ。 |
runtimeOnlyを使う例
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql:42.3.8'
}
- JPAでコード書いたら「コンパイルしないといけないし、実行時にも必要」なのでimplementation
- DBのドライバは実行時にあればいいので、runtimeOnly
compileOnlyを使う例
- Lombokの役割は「我々が書くソースファイルにおけるボイラープレートコード(GetterとかSetterとか)の排除」
- ソースファイルから実行ファイル作る(=compile)ときに自動でGetter Setter作ってもらうだけ。実行時には意味なし。
- なのでcompileOnly
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
}
apiの挙動
// Aモジュールのbuild.grale
// JPAを利用
dependencies {
api 'org.springframework.boot:spring-boot-starter-data-jpa'
}
// Bモジュールのbuild.grale
// Aに依存している
dependencies {
implementation project(':A')
}
この時、BモジュールでもJPAが使えて、関連クラスがimportできたりする。(依存関係が伝播していく)
(Bモジュールの保守チームからしたら、暗黙的に定義されたAの依存関係も意識しないといけないから、めんどくさそう...)
とは言っても、どう使い分ける?
以下、山根の意見です。
- 基本は全部implemetationで良さそう。
- よっぽどの理由がない限り、apiは基本使わない方向が良さそう。(必要になるケースがあまり思いつかない。。)
- runtimeOnly/compileOnly/implementationにするか迷うぐらいなら、基本はimplementationを選択する、で良さそう。ビルドが軽くなるメリットより、判断コストが大きくなるデメリットの方が大きい気がする。正しい依存のさせ方については、「アプリが大きくなって、ビルド時間を短くしたくなってきたら」考えることのような気がする。