入力データの検証タイミング

「セッターで値が規定外の時って」(1) Insider.NET − @IT
を読んでいたら
http://vsug.jp/tabid/63/forumid/56/postid/1589/view/topic/tpage/1/Default.aspx
で、いろいろ悩んでいたことを思い出した。
Webアプリにおける入力データの検証は、リクエストを受け取った直後に行うのが一般的だけれど、そのタイミングの検証ではDBなどのデータソースに直接変な値が設定された場合に無力となってしまう。データソース自体に変な値が設定出来ない仕組みがあることが理想だけれど、現実問題としては難しい。
でもなんとかしたいので、どうするのが一番しっくりくるかなー。と考えてみる。
データソースが問題なんだから、プログラムで制御出来るデータソースに一番近い場所で対応するのがよさそう。一番近い場所はどこだろう?DB使うんだったらSQL組み立て時かな。
と思ったけれど、どうすればいいのか分からないし全然しっくりこない。一番近い場所じゃなくってデータソースがオブジェクト化されるポイントを見るべきなのか。
そう考えるとDTOの生成時に対応するのがよさそうな気がしてきた。データソースとマッピングしたDTOが検証用インタフェースを実装して、値をセットしたら検証メソッドを呼び出す感じにすればなかなかうまく行きそう。

public interface Validatable {
 public void validate();
}

public class HogeDTO implements Validatable {
 String email;
 public void setEmail(String email) {
  this.email = email;    
 }
 public void validate() {
  if (email=変な値) {
   検証エラー;
  }
 }
}

入力フォームからセットする場合も、DBから読み込んだ場合も、DTOに値を詰め込んだタイミングでvalidate()を呼ぶ。これなら実装の負荷も増えないし、チェックタイミングが分散することもない。問題は検証エラーが起こったときの扱い。例外返す仕様にすると値のチェック結果を綺麗に保持出来ないので、StrutsみたいにError用オブジェクトを返すのがよさそう。

public class HogeDTO implements Validatable {
 String email;
 public void setEmail(String email) {
  this.email = email;    
 }
 public Errors validate() {
  if (email=変な値) {
   検証エラー;
  }
 }
}