lombokは、JavaでのアクセッサやtoString、equalsなどボイラープレートなコードをコンパイル時に生成してくれるライブラリです。
ただ、こういったコードの生成は、IDEを使えば自動で行えるので、わざわざlombokを導入するまでもないと考えることもできますが、ぼくはlombokを導入するべきだと考えて、lombokを使うようにしました。
このとき「lombokを導入するべき」と考えた理由を書いておきます。
lombokとは
lombokは冒頭でも書いたように、Javaのアクセッサなどを生成してくれるライブラリです。
Project Lombok
import lombok.*; @Setter @Getter @AllArgsConstructor @NoArgsConstructor @ToString public class LombokSample { private String foo; private int bar; public static void main(String[] args) { LombokSample ls = new LombokSample("ee", 12); System.out.println(ls.getFoo()); System.out.println(ls); } }
NetBeansでの導入
Mavenプロジェクトの場合は、次のようなdependencyを付け加えれば、特になにもせずにlombok対応できます。
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>0.12.0</version> <scope>provided</scope> </dependency>
Antプロジェクトの場合は、ダウンロードサイトからダウンロードしたlombok.jarをライブラリに追加して、プロジェクトプロパティの「ビルド > コンパイル」カテゴリにある「エディタでの注釈処理を有効にする」のチェックをいれます。
実は、lombokの存在はもっと前から知っていたのですが、エディタ対応しているとは知らず「エディタ上でエラーになるんじゃ意味ないよな」と避けていたのです。いくらコンパイル時にとおっても、エディタ上でエラーになっていては作業できないですから。ということで、エディタ対応しているとわかって即導入しました。
lombokを使ったほうがいい理由
では、lombokを使ったほうがいい理由ですが、一言でいえば「ミスがなくなる」です。
ぼくはアクセッサがらみのミスを2度経験して、lombok導入を決めました。
どのようなミスかということになりますが、まずミスとして「作成時ミス」「変更時ミス」「削除時ミス」という分類ができます。このうちの「作成時ミス」はIDEでの生成でもなくすことができますが、「変更時ミス」「削除時ミス」はなかなかなくすことができません。
それぞれのミスについてみてみます。
変更時ミスの回避
生成したフィールド、アクセッサの名前を変更するとき、フィールドをアクセッサを別々にリファクタリング機能で変更したとき、名前を打ち間違えてエラーが発生するということがありました。Javaコード内では動作として問題がなかったのですが、JSFでの式言語での動きで気づきにくい不具合が発生していました。
まあ、これはフィールド、アクセッサをセットで名前変更するリファクタリング機能を使えばよかっただけなのですが、だれか他の人が同じミスをすることも考えれるので、lombokを導入するきっかけになりました。
アクセッサ以外にもtoStringやequalsなど変更時に手が回らないことが考えられる部分はあります。このようなところでもフィールドの同期が自動的にとれるlombokを使うとミスが減らせます。
削除時ミスの回避
2人でコードを書いていたあるとき、少しロジックの入ったgetterが単純なgetterに変更されてしまうことがありました。共同作業者に聞いてみると、フィールドを複数追加してアクセッサを作るとき、アクセッサの並び順がフィールド記述順にしたいため、一度すべてのアクセッサを消して生成しなおしたということでした。そのときにロジックが入っているものを一緒に消してしまった、と。
たしかに、このロジックを自分で書いていなければ、やりがちです。
Javaのアクセッサの難点は、特別なロジックの入っているアクセッサが単純なアクセッサの森に隠されてしまうことです。一緒に削除したというのも、結局アクセッサの森にロジックがまぎれてしまっているためです。lombokによって不要な森が消えることで、作業性があがります。
@ToStringでの循環参照に注意する
lombokを使ったことで実行時不具合が出るということが、少なくともひとつ考えられます。
toStringの循環参照の問題です。
データベースのマッピングでは、次のように明細データをもつクラス構成をとることがあります。
@ToString class Foo{ List<FooDetail> details; } @ToString class FooDetail{ Foo parent; }
このとき、toStringで文字列化が行われると、toStringが循環的に呼び出されてスタックオーバーフローします。
次のように@ToStringアノテーションにexclude属性を指定して、循環参照を切っておく必要があります。
@ToString(exclude = "parent") class FooDetail{ Foo parent; }
これが問題なのは、自動生成するようなtoStringが呼び出されるのは正常系コードではなく例外系コードであるということです。それも、自分で書いたコードで呼び出すのではなく、例外メッセージの中で使われることが多くあります。
そうすると、テストしにくく、なんらか別の問題が出たときに顕在化するという、ちょっとやっかいな問題になります。
フィールド名変更が少し面倒
実のところ、lombokを導入すると、アクセッサ付フィールドの名前変更が面倒になります。
というのは、フィールド名を変更すると自動的にアクセッサも名前がかわるのですが、自動生成されたアクセッサを利用している部分までリファクタリング機能が及ばないからです。
IDEの対応の問題なので、NetBeans以外では問題ないかもしれませんが。IntelliJはプラグインの説明に「adds support for most features.」とあるので、対応しているのかも。
で、現状どうしているかというと、名前変更するフィールドのアクセッサをIDEでの生成でわざわざ作って、その上でフィールド名をリファクタリング機能で変更し、その後でアクセッサを消す、というちょっとナンセンスなことをやっています。