« トレーサビリティを確保するための便法 | トップページ | 仕様書の類型化と様式化 »

2013.10.21

「逆方向バリデーション」との付き合い方

 拙作の開発基盤 XEAD Driver には、「逆方向バリデーション」を自動化するための「クロスチェック」と呼ばれる機能が搭載されている。利用事例が増えるにつれて、あらためてその意義や考慮点がわかってきた。ときにはクロスチェックをあえて抑制しておくことも必要になる。逆方向バリデーションとうまく付き合うためのヒントとして説明したい。

 まず、逆方向バリデーションがどんなものかをおさらいしておこう。顧客マスター上に「値引認可区分」があって、これが受注テーブル上の値引額を制約しているとする。値引が認可されている顧客A社について、未出荷分の受注データが存在していて、その値引額が正の値だとする(次図)。

[顧客] 顧客C,顧客名,値引認可区分
+   1234 A社    true

└─…[受注] 受注№,顧客C,値引額, ...
       J256 1234  2000 ...

 このデータ状況で、A社の「値引認可区分」を"false(値引禁止)"に変更したらどうなるか。顧客レコードと未出荷分の受注レコードとの間で不整合が生じる(*1)。ゆえにこのような更新を許してはいけない。少なくとも、何の警告もなく更新を認めてしまうようでは無防備すぎる。ではどうすればいいのかというと、値引額をクリアするか、それが無理ならばこの受注については値引を認めてその出荷完了を待つ、といった手順を踏んだうえであらためて更新するようにユーザをガイドすればよい。

 この場合での"通常"のバリデーションは、参照元である受注レコードの更新操作の際になされる。値引禁止であるような顧客向けの受注に値引額を指定すればエラーになる。これが参照元から参照先に対する"正方向"、つまり"通常"のバリデーションだ。ところが上述したケースでは、顧客マスターの更新操作において、参照元である受注レコードを"逆方向"に検索する形で妥当性が検査される。これが私の言う「逆方向バリデーション(reverse validation)」である。

 逆方向バリデーションは、システム開発の世界ではこれまで奇妙なほど曖昧に扱われてきた。アプリ毎にロジックがしっかり組み込まれることもあるし、あっさり無視されることもある。RDBの外部キー制約の形で対処されることもあるが、それも中途半端なうえに使いにくい(本ブログでの参考記事:DDLレベルの外部キー制約は不要)。結果的に、逆方向バリデーションは業務システムのグレーゾーンのようなものになってしまっている。

 情状酌量の余地はあるのかもしれない。もし逆方向バリデーションの必要性を公式に認めてしまうと、コーディングすべきバリデーションの量が倍かそれ以上に増えてしまう。参照先の更新においても参照元レコードとの関係をいちいち調べなければならないのだから。ただでさえ工数があふれそうなのに、それ以上の手間を増やすなんて勘弁してほしいと誰もが思うだろう。そこで求められるのが、逆方向バリデーションの自動化である。

 XEAD Driverの「クロスチェック」は、逆方向バリデーションを自動化するための世界的にも珍しいしくみだ。クロスチェッカーは、レコードが更新される際に、そのテーブルを結合しているテーブルを調べ、更新レコードとの間で不整合を生じるような結合元レコードが存在するかどうかをスキャンする。そのようなレコードが検出されれば、当該レコードの更新が禁止される。

 その過程に必要なロジックは、リポジトリ(テーブルの拡張定義として組み込まれた結合定義やスクリプト)から動的に構築される。だから逆方向バリデーションのためのコードをわざわざ書く必要はない。言い換えれば、バリデーションに関わる仕様をテーブル側に一元的に寄せ、さらに実行時にそれらを機能定義と動的にリンクする方式をとったゆえに、逆方向バリデーションの自動化が可能になったのである。

 このように合理的かつ有用なしくみではあるのだが、クロスチェックは2つの原理的な課題を抱えている。まず容易に想像できるように、場合によって更新操作のレスポンスを悪化させる。とくに品目マスターや顧客マスターといった、多くのテーブルによって結合されているテーブルだと、クロスチェッカーの構築にもチェック過程にも相応の時間がかかる(*2)。

 もうひとつの問題は、この開発基盤で既存DBを処理したときに生じる。既存DBにはデータの不整合が多かれ少なかれ生じているものだが、クロスチェックによって良くも悪くもそれがあぶりだされる。値を変更しようとしているわけでもないフィールドについてまで、クロスチェッカーは広範囲に不整合を検出してしまう。

 その場合、要求されている更新操作によって不整合が生じるとみなされ、要求が拒否される。DB内でデータの不整合が生じていることを教えてくれるのは有難いのだが、それらをきっちり修復した後でないと単純な修正さえ許されないというのでは、ときには業務上の支障となる。

 この問題に対処するために、最新版ではテーブル毎にクロスチェックの機能を保留できるようになっている。ただし保留したテーブルについては、逆方向バリデーションのロジックがスクリプトとして補完されなければいけない。ゆえに安易に保留することは避けるべきなのだが、それにしてもモノゴトを杓子定規に考え過ぎてもいけない。そういうことをこの事例は教えてくれる。


*1.少なくとも受注時には値引が認可されていたのだから、この状況は不整合ではないと解釈する考え方もある。つまり、値引額は"受注時の値引認可区分"にもとづいて整合的に設定されたのだというわけだ。そうであるならば、値引認可区分はスナップショット属性として受注テーブルにも置かれるべきだ。いずれにせよ、逆方向バリデーションを曖昧にしたままでは不整合が避けられないという一般論としてここでは理解されたい。

*2.構築過程をスキップするために、特定テーブルのクロスチェッカーをユーザのログイン時にプリロードできるようになっている。なお、レスポンスの悪さは困った問題とはいえ致命的ではない。逆方向バリデーションのためのコードを人手で書く代わりに、マシンが自動的にやってくれる。それゆえに時間がかかるとしたら負荷が人からマシンに移行しているということであって、開発基盤の発展の方向性として正しい。当面はプリロードさせるなり、保留してスクリプトを補完するなりの対処をしておけば、遅かれ早かれマシンの性能が向上してレスポンスの問題は解消されるだろう。

|

« トレーサビリティを確保するための便法 | トップページ | 仕様書の類型化と様式化 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 「逆方向バリデーション」との付き合い方:

« トレーサビリティを確保するための便法 | トップページ | 仕様書の類型化と様式化 »