Skip to content

Instantly share code, notes, and snippets.

@deffence1776
Last active April 15, 2021 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deffence1776/eb084a2e2df9c2fd28284e72ee06104b to your computer and use it in GitHub Desktop.
Save deffence1776/eb084a2e2df9c2fd28284e72ee06104b to your computer and use it in GitHub Desktop.
Javaビルドツール入門

ビルドツールの基本

ビルドとは

デプロイ/実行可能なファイルを作成すること。Javaにおいてはjarファイルやwarファイルを作ること

jarファイルとは

Javaで利用するファイル(主にクラスファイル)を圧縮したもの。設定ファイル(manifest.inf)を内部に追加することで実行可能なjarファイルにすることができる。zip形式で圧縮しているだけなので解凍すれば中身が見られる。Javaソースファイルを圧縮する場合もある。
Java8まではStringクラスなどのが格納されていたjarファイルがJRE内部に存在していた。

(改めて)Javaの実行の仕組み

JVM(Java仮想マシン)が起動し、JVMがクラスファイルを読み込んでクラスファイルに記述された命令を実行する。JREの「java」コマンドで実行する。

クラスパス(classpath)

JVMがクラスファイルを読み込む(ロードする)対象のパス(OS上の場所)をクラスパスと呼ぶ。クラスパスはデフォルトではJavaコマンドが実行されたディレクトリとなる。。別の場所に存在するクラスファイルをロードさせたい場合は以下の2つの方法で実行する。

  • javaコマンド実行時に「-classpath」オプションでディレクトリもしくはjarファイルを指定する
  • 環境変数「CLASSPATH」にディレクトリもしくはjarファイルを指定する

あるソースコードが別のクラスを参照している場合、参照先のクラスファイルがクラスパスに含まれていない場合はコンパイルできない。また、実行時にもクラスパスから存在しない場合はエラーとなる。

実演

テストに利用するJUnitもJavaのライブラリなのでクラスパスの設定が必要。EclipseはEclipse独自の仕組みである「.classpath」ファイルにクラスパスの設定が記述され、コンパイルや実行時に利用される。

ツールを使わないJavaプロジェクトのビルド

  • ディレクトリ構成は自由
  • クラスパスによる依存関係管理。どのようなファイルにクラスパスを記述するかは自由
  • ライブラリはダウンロードして配置。ライブラリのバージョンはファイル名で管理
  • テストクラスのコンパイル時とテスト実行時にはJUnitのライブラリをクラスパスに設定する必要がある。

Mavenによるビルドの標準化

Mavenは上記の作る人によって自由に行なっていたビルドのプラクティスをベストプラクティスによって標準化したツール。それ以前はantというビルドタスクの自動化ツールが存在したが、Mavenほど標準化されておらず、かなり自由度が高かった。

依存関係の集中的バージョン管理

  • プロジェクトのメタ情報の管理

    • プロジェクト名、バージョン、作成者情報などを標準的なpom.xmlで管理
      • groupId:組織名
      • artifactId:成果物名
      • version:バージョン
  • ライブラリの集中管理リポジトリ

    • 上記の標準的なプロジェクトの記述に即したリポジトリを構築
    • OSS用のMavenセントラルリポジトリ
    • プライベートリポジトリにはNexusなどのオープンソースリポジトリを利用できる
    • 近年ではgithubパッケージをライブラリに指定可能。
    • ダウンロードしてきて、「~/.m2」配下にローカルリポジトリと設定ファイルが配置される。
  • 宣言的な依存関係管理

    • 設定ファイルでプロジェクト名、バージョンを指定することで自動的にリポジトリからダウンロードして自動でクラスパスを設定する
    • マルチプロジェクトで構成した場合、自作プロジェクトもOSSと同じように記述できる。
  • フェーズによる依存関係の定義。

    • テスト時はテスト用ライブラリが必要だが、本番環境にデプロイするときは不要
  • ファイル配置の標準化

    • ファイルを配置するディレクトリ構成の標準化
    • Mavenのディレクトリ構成
      • ソースコードとリソースファイルでディレクトリを別にする
        • 「Java」ディレクトリと「resources」ディレクトリ。
        • リソースファイルとは、jarファイルの内部にコピーされるファイルのこと。Javaコードでは「ClassLoaderクラス」などからファイルを取得できる。
      • プロダクションコード/リソースファイルとテストコード/リソースファイルを別にする
        • 「src/main」と「src/test」
        • プロダクションコードのコンパイル時/実行時にはテスト用のディレクトリはクラスパスから除かれる。
      • プログラム言語毎にソースファイルディレクトリを別にする
        • Java以外の言語の場合は「src/main/groovy」などのフォルダを作成する
        • Java以外のJVM言語のソースファイルを管理(kotlin,Scala,groovyなど)
  • 検証プロセスとの統合

    • ビルド時には必ず静的検証やテストを実行して、全て成功した場合にしかビルドできない。
    • 通常、正式にビルドする場合は一旦コンパイル済みのコードを削除(clean)してからビルドし直す。以前のバージョンのファイルや手動で配置したファイルなどの影響を排除するため。
      • オープンGWでは手動でファイルを配置して無理矢理動かしているので、ソースをそのままビルドしても動かない。。。
  • 多様なプラグイン

    • さまざまな機能を持つプラグラインが作成でき、ビルドプロセスに統合できる。

Gradle

Mavenの標準的プラクティスを踏襲しつつもより柔軟にビルドタスクの記述が可能なツール。正直好みで選んでよし。

記述はXMLではなく、groovyという言語もしくはKotlinでかく。

継続的インテグレーション/結合(CI)

WF型のプロジェクトでは、細かくチーム毎に部品を作り、最後に結合してテストする、というプロセスを採用することが多かった。結合して初めて問題に気づくことがあったり、動作させるまでに一苦労なので開発者が実際にシステムが動く場面を見るということが難しかったりした。

アジャイル開発が提唱されたときに、提案されたプラクティスが、継続的インテグレーション。毎日ビルドサーバで結合してビルドすることで問題を早期に発見する。ビルドプロセスを洗練させる。現在では当たり前になっては来ているはずだが。。。

例えば、mainブランチにプッシュされると、それがビルドされ、テスト環境でテストが自動的に走るなど。フロントとバックも結合対象となる場合もある。

継続的デプロイ(CD)

CIの次のステップとして、継続的にほぼ毎日本番環境にリリースするというプラクティス。DXの重要な指針でもある。

参考になるリンク

qiita:mavenとはなんぞや

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment