エキサイト株式会社エンジニアの佐々木です。2021年アドベントカレンダー5日目を担当します。
サービスを開発している上で、データをなるべくイミュータブルにするというのは、バグを作り込まない上で重要だと思います。Java15でRecord型が導入されていますが、まだ未対応なライブラリがあると思います。今回はLombokでは@With
を使って簡単に実装できます。
ミュータブルなデータ型
ミュータブルなデータ型は、Lombokでは@Data
を使って簡単にできます。
@Data class Form { private final Long id; private final String name; } 使用時: Form form = new Form(); form.setId(1L); form.setName("sample"); form.setId(2L); // form.id が 2にかわる form.setName("sample2"); // form.name が 2に変わってしまう
コード見れば明らかですが、途中でオブジェクトの状態が変わっています。メソッドの引数で渡して、再代入等を特にしていない場合でも変わってしまうので、バグの1つの原因になります。
イミュータブルなデータ型(@Value)
@Value class Form { private final Long id; private final String name; } 使用時: Form form = new Form(1L, "sample"); form.setId(2L); // メソッドが存在しないので、エラーになる form.setName("sample2"); // メソッドが存在しないので、エラーになる Form form2 = new Form(2L, "sample2"); // 代入 or 再代入をする
コンストラクタを使用したときだけ値を設定できるようにすると、1度定義したオブジェクトの状態は途中で変えることができません。途中で変えるには、再度コンストラクタ呼び出しを行い、再代入等が必要です。しかし、引数が少ないときはいいですが、多くなってくると辛くなってきます。そこで@With
が登場します。
イミュータブルなデータ型(@With)
@With @Value class Form { private final Long id; private final String name; } 使用時 Form form = new Form(1L, "sample"); form.withId(2L); form.withName("sample"); log.info("{}", form); // Form(id=1, name=sample); Form form2 = form.withId(2L).withName("sample2"); log.info("{}", form); // Form(id=2, name=sample2);
withId(), withName()
を使用して値変更しても、formオブジェクトの値は変更されていません。setterとは違い、新規オブジェクトが返ってきます。では、@With
がどういう処理をしているのかをdelombokをして見ていきます。
public Form withId(Long id) { return this.id == id ? this : new Form(id, this.name); } public Form withName(String name) { return this.name == name ? this : new Form(this.id, name); }
このようなコードが裏側で実行されています。値が同じ時は自分の参照を返し、値が変更されている場合は、新規のオブジェクトを生成して返しています。これでイミュータブルなオブジェクトになって安全です。
まとめ
Java15でRecord型が導入され、イミュータブルなオブジェクト専用の型が追加されています。状態が変更される副作用を抑えるべく導入されているかと思います。周辺ライブラリが対応するまではLombokを駆使して、ミュータブル、イミュータブルなオブジェクト生成の使い分けをする感じになるかと思います。
最後に
引き続きエキサイトホールディングスのアドベントカレンダーをお楽しみいただければ幸いです。 Calendar for エキサイトホールディングス Advent Calendar 2021 | Advent Calendar 2021 - Qiita
エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。
カジュアル面談はmeetyを公開していますので、よろしくお願いいたします! meety.net
募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com