バリデーションを再考する
僕は以前、 「DDDで考えるマイクロサービスのバリデーション」という大それた記事を書いた。
マイクロサービスっていうのが、ちょっと良くわかんない。
整理されてなくて、何が言いたいのかも良く分からないので、
再考した結果を、リライトしてみます。
リクエストパラメタの入力値検証
結論
値オブジェクトを作って、検証しよう。
詳細
プレゼンテーション層では、アプリケーションサービスの引数に渡す値だと考える。
ただ、値が妥当かどうかを判断するには、プリミティブな型だと情報が足りない。
それが、「メールアドレスとして欲しい」のか、「7桁の文字列が欲しい」のかStringじゃ分からない。
値オブジェクトを作って、validかどうか検証した結果、validならアプリケーションサービスに渡せばいいし、 駄目だったら、ユーザーにバリデーションエラーとして返す。
業務処理でのバリデーション
結論
- 引数の値オブジェクトは検証済みが来る想定ですが、念の為DbC的にチェックして、invalidな場合は、例外で落としてもいい気がする
- 例外を通知して、プレゼンテーション層側で、ユーザーに返せる形にする
詳細
入力値としては正しいが、業務上処理できない場合がある。
例えば、「登録済みのメールアドレスでユーザーを登録できない」がある。
この検証は、アプリケーションサービス中で行わないと、業務上、同じメールアドレスを持つユーザーを登録できても良いことになる。
検証に失敗したら、例外をスローして、プレゼンテーション側で、422として返すのか、500として返すのか振り分ける。
入力値がそもそも正しいかは、契約による設計(DbC)的にチェックして弾いちゃっていいかも。
インフラ層での検証
結論
テーブルの制約で頑張る
詳細
結論通り、テーブルの制約で頑張る。
正直、アプリケーションコードで頑張ってバリデーションしても、通り抜ける事はよくある。
チーム開発している大きなアプリケーションは、気付いた時にはトランザクション中で、重たい処理をしていて、メールアドレスが重複してユーザーが登録されたりしている。
メールアドレスにユニーク制約つけて、退会したらメールアドレスをランダムにマスクしたりして、強制的に変更しておく方が誤送信の防止とかにもなるし、安全なはず。