状態遷移図をコードで表現してみる
今回は状態遷移図をコードで表現してみたらどうなるかを書きます。
状態遷移図
お題となる状態遷移図は、以下です。
会員登録サービスにおける入退会のイメージです。
クラス図
これに対応したクラス図は、以下です。
状態遷移図の遷移(矢印)を表現したクラスが会員イベントクラス。
状態遷移図の状態を表現したクラスが会員ステータスクラス。
会員イベントクラス側に、
イベント発生時に実行可能なステータス一覧を定義(possibleStatusList変数)
イベント発生後のステータスを定義(toStatus変数)
の2つから、状態遷移図を表現します。
具体的なコード
それぞれのクラスに対応したコードは、以下です。
楽をするために、Lombokを利用しています。
会員イベントクラス
@ToString(includeFieldNames = false) @AllArgsConstructor public enum UserEvent { JOIN("入会する", new ArrayList<UserStatus>(), UserStatus.JOINED), WITHDRAW("退会する", Arrays.asList(UserStatus.JOINED), UserStatus.WITHDRAWAL_RESERVED), WITHDRAW_CANCEL("退会キャンセルする", Arrays.asList(UserStatus.WITHDRAWAL_RESERVED), UserStatus.JOINED); private final String name; private final List<UserStatus> possibleStatusList; @Getter private final UserStatus toStatus; public void verify(UserStatus status){ if(possibleStatusList.contains(status)){ return; } throw new UnsupportedOperationException(name + "イベント実行時に不正なステータスです。"); } }
会員ステータスクラス
@ToString(includeFieldNames = false) @AllArgsConstructor public enum UserStatus { JOINED("入会済"), WITHDRAWAL_RESERVED("退会予約中"), WITHDREW("退会済"); private final String name; }
簡単な状態遷移図なら、上のようなシンプルなコードで表現できます。
ただ、今回のお題も当てはまるんですが、ステータスはアプリケーションコードとは別に、DBなどで永続化していると思います。その際、アプリケーションとDBでステータスがマッチしない状況が出てきます。
具体的に言うと、退会予約中→退会済の遷移は退会日が過ぎたらの条件なので、
アプリケーション側は、退会予約中と退会済の2つの状態がある
DB側は、退会という1つの状態がある
のような状態になります。
同じステータスでも、アプリケーションとDBで異なれば、誤認識の元になるので、できれば避けたいです。
対応案としては、
退会確定の会員イベントを増やす。→退会確定まで数秒〜数分の誤差が出るので、厳密性が求められるサービスだと厳しい。
DB側にステータスを保持しない。→DBに保持しないので、マッチしないことを考慮する必要なし。
が挙げられると思います。
僕の実際のプロダクトだと、「DB側にステータスを保持しない。」で対応しています。
この話は別の機会で記事を書きます。
ということで、今回は以上です。
シンプルな状態遷移図なら、今回のコードでも対応できるので、ぜひ参考にしてもらえたらと思います。