ひとつ前の記事では「Gradleの設定やコードをどこに書くべきか」のうち、答えが明確な「build.gradleファイルとbuildSrcディレクトリの使い分け」について書きました。この記事ではまだ自分の中でもよくわかっていない「Gradleでbaseプラグインに書くべきでないconventionとは何か」について書きます。
baseプラグインとは
ここで言うbaseプラグインは、plugins { id "base" }
で使えるThe base pluginのことではありません。Gradleプラグインの設計手法のひとつとして推奨されている「設定より規約」の文脈で登場するものです。「設定より規約」を実現しつつ、(大部分のケースをカバーするであろう)規約が適用できないケースでもプラグインの機能を使えるようにするため、プラグインの規約(conventions)と基本的な機能(capabilities)とを別のプラグインに定義する設計手法です。
例えば java
プラグインと java-base
プラグインの場合、 java
プラグインが規約を提供し、 java-base
プラグインが基本的な機能を提供します。 java
プラグインはjava-base
プラグインに依存することで、java-base
プラグインが提供するtaskやextensionを利用します。
なお公式にはbaseプラグイン「ではない」方のプラグインには固有名詞がないのですが、ここでは記載を簡略化するために「規約プラグイン」と呼ぶことにします。
GradleはConventionという用語を多義的に使っている
ではbaseプラグインに書くべきconventionとは何か。この話題に触れるにあたり、GradleがConventionという用語をいつどのように使っているか確認する必要があります。私の知る限り、大きく分けて以下の3つが存在します:
- ”設定より規約”の文脈でのconventionのこと。一般的な用法。
- 例えば
java
プラグインはSourceSetごとにコンパイルやテストのタスクを作成する。 - プラグインユーザは可能な限り規約に従うことが推奨される。
- プロジェクトの種類ごとに規約をまとめたConvention Pluginsなども存在。
- 例えば
- プロパティを指定しなかった場合に暗黙的に採用される値。default valueのこと。
- 実装上はProperty#convention(Provider)メソッドと内部的に利用されていた"convention mapping" APIがあり、後者は非推奨API。
- これを1の一部と捉えることも可能だが、以降に続く議論の記載を簡素化するために分離して記載。
- プラグイン設定用のconvention
- 例えばJavaPluginConventionなど。
- 現時点では非推奨なため、Extensionを利用する必要がある。
こうなるとよくわからないのが「baseプラグインに書くべきでないconventionはどれ?」です。
1のconventionはプラグインが提供する規約そのものでありbase
プラグインに書くべきでないのは明らかですが、JavaBasePluginやCargoBasePluginは2と3のconventionを含んでいます。
規約プラグインであるJavaPluginやCargoPluginはconventionを持っていることを期待され、実際1や2のconventionを含んでいます。
非推奨となった3のconventionは脇に置くとしても、2の置き場所やそれを決定する判断基準は明瞭に持ちたいところです。
メソッド名に惑わされないのが吉か?
私も2021年7月現在では明瞭な判断基準は持っていないのですが、ポイントはProperty#convention(Provider)というメソッド名に惑わされないことだと思われます。言い換えれば、2のconventionはどこにでも出てくるものだと割り切り、1のconventionを規約プラグインに限定して書くことのみに注力します。そして機能を書く上で必要なプロパティがある場合、baseプラグインでも気にせずにデフォルト値をProperty#convention(Provider)メソッドで設定してしまいましょう。
公式フォーラムに問い合わせてみた
自分的にはわかった気になれましたが、なんかしっくりこないので公式フォーラムに問い合わせてみました。
返信もらえたらこちらのブログ記事も更新します。
2021年9月29日更新: 公式Slackの方で「JavaBasePluginが異色なだけ、普通は1と2と3は全く同じものでbaseプラグインには出てこないべき」というコメントを貰いました。確かに一番シンプルなまとめ方かもしれません。