考える場所

ココロとカラダ、思考する全部

入力チェックの実装と実行

入力チェックはどこに実装してどのようにコールするのがスマートなのだろうか。

エラーの分類

エラーチェックの体系的な分類方法 - とあるコンサルタントのつぶやき - Site Home - MSDN Blogs

この記事を参考にしてエラーの分類を次のように考える。

  • 単項目チェックエラー
  • 複項目チェックエラー
  • 突き合わせチェックエラー

単項目チェックはひとつの入力項目で済ますことができるチェックだ。たとえば必須だとか桁だとか。複項目チェックは複数の入力項目の関係を判定するチェックだ。たとえばどれかひとつのチェックを入れなければいけないだとか。突き合わせチェックは入力項目とデータベースの関係を判定するチェックだ。たとえば顧客マスタに存在する顧客IDだとか。

チェック処理の内容を考えるとこんなところだろう。

DTOとして

まず入力値はDTOであろう。Strusを使う人ならFormと呼ぶのかもしれない。これは呼び方の問題であって、入力値は何かという分類を考えればDTOなのだと思っている。オブジェクトに関する処理はそのオブジェクトがもつのだから、DTOで閉じることができる入力チェックはやはりDTOでもつのがよさそうだ。つまりDTOが単項目チェックと複項目チェックをする。SAStrusでは単項目チェックをアノテーションで表現することができる。また複項目チェックはActionFormがするべしとしている。

検証メソッドは、アクションフォーム、アクションのどちらにも記述できますが、 検証対象のデータを持っているアクションフォームに記述したほうがいいでしょう。
- Super Agile Struts - Feature Reference

ドメインの仕様として

突き合わせチェックはどうだろう。突き合わせチェックはデータベースが絡むので入力値で閉じられる問題ではない。従ってサービスレイヤ上のオブジェクトがリポジトリを利用してチェックするものと考えられる。さらに、次の意味を考えてもサービスレイヤ上でチェックするのが自然である。エンティティとの関係を判定するというのはドメインの仕様であるということだ。

f:id:fukuchiharuki:20150110225531p:plain

疑問

どこでチェック処理をコールするか

単項目チェックと複項目チェックの実装がDTOにあったとして、これを呼び出すのはどこにするべきなのだろうか。ユースケースの中だろうか。あるいはその手前だろうか。

1個のUsecaseの制約として、どこか1つ以上のインターフェース方式からの入力を、どこかの1つ以上のインターフェース方式へ出力して終わる、というようにすると単方向の処理を保てる
- DDD - 持続可能な開発を目指す ~ ドメイン・ユースケース駆動(クリーンアーキテクチャ) + 単方向に制限した処理 + FRP - Qiita

ユースケースの中であってもその手前であっても、ユースケースの制約として一方向であることは保てる。ただし、入力エラーの内容をユーザーに返却するという仕様がユースケースの中とその手前に分散してしまわないだろうか。一方入力チェックのすべてをユースケースの中にした場合、チェック処理でユースケースがいっぱいになってしまわないだろうか。

f:id:fukuchiharuki:20150110225645p:plain

入力チェックエラーをユーザーに返却するというのはユースケースのことであるから、入力チェックのすべてをユースケースの中にするのがよさそうに思える。本質的な処理をチェック処理から分離するためにさらに実装上の工夫が必要だろうか。

項目の書式はドメインの知識ではないか

オブジェクト指向設計としてDTO(入力値)のチェックをDTOがすると考えるのは納得がいく。しかしその内容(桁数やフォーマット、複項目の関係)というのはドメインの知識であるとは言わないのだろうか。ValidatorやVOの形で知識をドメインレイヤに含めて、外側がそれを利用すると考えるのが正解だろうか。あるいは、項目の書式などはインフラストラクチャ(データベース)の制約でしかないのでそもそも外側のことであると考えるのが正解だろうか。