mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle-2.9-rc1のリリースノートで訳し忘れてたライブラリーAPI定義について意訳(JDK9にも関連) #gradle

f:id:mike_neck:20151108133321p:plain

意訳には(僕に)定評のあるGradleのリリースノートですが、前回訳した時に、意図して訳さなかったのか、JavaOne開催中でProject Jigsaw関連に合わせるためにその時には書かれていなかったのか、どっちか定かではありませんが、リリースノートの意訳にExplicit declaration of library API with experimental Java software model(JavaソフトウェアモデルにおけるライブラリーAPIの明示的宣言)の訳がありませんでした。というわけで、意訳を書いておきます。

mike-neck.hatenadiary.com


JavaソフトウェアモデルにおけるライブラリーAPIの明示的宣言

現在のJavaソフトウェアモデルでの開発はより強力になりました。それも、ライブラリーAPIを構成するパッケージと依存性を明示的に宣言できるようになったからです。

JVMライブラリーのAPIを宣言できることは次のような利点があります。

  • ライブラリー利用者に不必要に内部で使われるクラスを見せなくて済む。
  • ライブラリーの署名が変更されていない場合に、再コンパイルしなくて済む。
  • JDK9にて登場するJavaモジュールシステムへの移行パスが提示される。JDK9が実行時におこなう分離作業をコンパイル時に先取りすることができる。

JVMライブラリーにふくまれるAPIのパッケージ宣言

ライブラリーのAPIで提供されるパッケージを宣言することができます。それはapi {} ブロックに記述することで可能です。

model {
  components {
    myJvmLibrary(JvmLibrarySpec) {
      api {
        // `com.acme`パッケージが外部に公開されるAPIであると宣言する
        exports 'com.acme'
      }
    }
  }
}

Gradleは自動的にmyJvmLibraryコンポーネント用のAPIのjarを生成します。このコンポーネントに依存するコンポーネントmyJvmLibraryAPIのjarに依存してコンパイルされます(つまり、myJvmLibraryで公開されないクラスはコンパイル時に参照できない)。

API jarが含むクラスは宣言されたパッケージ以下に所属するクラスのみで構成されます。

  • ライブラリー利用者がAPIでないクラスにアクセスしようとした場合にはコンパイルエラーとなります。
  • APIとして公開されていないクラスが変更された場合は、利用者の方のライブラリーの再コンパイルは行われなくなります。
  • APIの署名が変更されないようなAPI変更がなされた場合でも、ライブラリー利用者は再コンパイルの必要性がありません(つまり、実装クラスを変更して、パラメーター名を変更して、プライベートメソッドを追加した場合など)。

JVMライブラリーのAPIを構成する依存性の宣言

公開するパッケージと同様に、ライブラリーのAPIは依存ライブラリーを宣言できます。この場合、依存ライブラリーのAPIはライブラリーAPIに含まれることになります。

APIに含まれる依存性は、これまでのコンパイル依存性定義と同じような方法で宣言することができますが、api{}ブロックの中で宣言する必要があります。

model {
  components {
    logging(JvmLibrarySpec) {
      api {
        exports 'my.logging.api'
      }
    }
    myJvmLibrary(JvmLibrarySpec) {
      api {
        exports 'com.acme'
        dependencies {
          // 'loggng'ライブラリーのAPIが'myJvmLibrary'のAPIに含まれるようになります。
          // 'logging'ライブラリー中の'my.logging.api'パッケージに含まれるクラスが'myJvmLibrary'のAPIとして公開されます。
          library 'logging'

          // ':util'プロジェクトの'calc'ライブラリーのAPIが'myJvmLibrary'のAPIに含まれるようになります。
          library 'calc' project ':util'
        }
      }
    }
  }
}

mainライブラリーがmyJvmLibraryライブラリーに依存する場合、myJvmLibraryAPIおよび、loggingライブラリーの公開APIを参照してコンパイルされることになります。myJvmLibraryライブラリーの非公開クラスや、loggingライブラリーの非公開クラスにmainライブラリーのクラスがアクセスすることは認められません。


以上