【Flutter】flutter(dart)でValueObject

はじめに

ドメインを表現するために、ValueObjectを作ることがあります。
ValueObjectについては以前概要についての記事を書いているのですが、実際にFlutterで開発するときにどのようにしてValueObjectを作るのかを紹介していきたいと思います。

ValueObject(値オブジェクト)とは

ValueObjectについては、この記事で書いています。
システム固有のプリミティブ型(数値や文字列など)のようなものがValueObjectです。
ValueObjectは不変なので、オブジェクトの中身の変化を考慮しなくていいようになります。

FlutterでValueObject

FlutterでValueObjectのクラスを作る場合は、プロパティを読み取り専用にして、イミュータブルなクラスになるようにします。また等価性の比較メソッドなどを追加する必要があります。

ただ、freezedパッケージを使用することで、ValueObjectを簡単に作成することができます。
※freezedは不変のデータクラスを簡単に作成できるパッケージです。
以下、「名前(FullName)」のValueObjectになります。

@freezed
class FullName with _$FullName {
  @Assert('firstName.isNotEmpty', 'ファーストネームが入力されていません')
  @Assert('lastName.isNotEmpty', 'ラストネームが入力されていません')
  factory FullName({
    required String firstName,
    required String lastName,
  }) = _FullName;
}

ValueObjectの中には、firstName、 lastNameの値があります。
これらの値が不変になるようにfreezedを使用して不変のデータクラスにしています。
また、FullNameにドメインのルールを追加するために@Assertのアノテーションを使用しています。
@Assertを使用すると、ValueObject生成時に渡された値が不正な場合は、例外を起こすことができます。
例では名前が空白な人はいないので、空文字などが渡された場合は、例外を起こすようにしています。
freezedを使用しているので、等価の比較をするときは以下のように書くことができます。

void execute() {
  try {
    final fullName1 = FullName(firstName: '太郎', lastName: '田中');
    final fullName2 = FullName(firstName: '太郎', lastName: '田中');

    print("fullName1 == fullName2");
    print(fullName1 == fullName2); // true
  } catch (e) {
    print(e.toString());
  }
}

また、ValueObjectでクラス内に関数を用意したり、拡張関数などを使用して、ドメインの振る舞いを表現します。

@freezed
class Money with _$Money {
  factory Money(int value) = _Money;
}

extension MoneyExtension on Money {
  Money add(Money money) {
    return Money(value + money.value);
  }
}

このようにすることで、このValueObjectがどのような動作をするのかわかるようになり、仕様がコードで表現されるようになります。

まとめ

今回は、Flutter(dart)でValueObjectを作ってみました。開発の中で実際に使っていくようなコードや内容を書いていきたいと思います。

この記事が気に入ったらサポートをしてみませんか?