フレームワークの都合に引っ張られて DB の型を全て VARCHAR にしたりしない

Struts1 系は、画面とのデータのやり取りには基本的に文字列を使用するため、画面上の入力値を受け取る Form Bean のプロパティは String にしておくことが通例。

例えば、1つのチェックボックスで何かの On/Off を表現するような項目が画面にある場合。

Struts1 ではチェックボックスの状態を直接 Form Bean に渡すのが色々と面倒なので、チェックされた時に JavaScript で、何か別の hidden 項目の value に "0" か "1" なり、"true" か "false" なり、チェックされたかを区別するための値をセットし、フォーム送信することが多い。

この hidden 項目は Form Bean に定義してあるプロパティで、上述のような Struts1 の都合に合わせて、String 型で定義してある。そのため、チェック状況はこのプロパティから String 型で、"0" だとか "1" だとかいう文字列で受け取ることになる。

Struts1 系なんて相当古いフレームワークだし、そんなものを使っていること自体どうかしているのだが、とりあえずそういうフレームワーク上の都合がある状態。

一方、そのチェックボックスの状態を格納する DB のカラムは Boolean 型が望ましい。チェックされたかされていないか、で True or False に分けられるからだ。

しかしうちの現場で見ているシステムでは、Form Bean で受け取った値を DB 登録用の DTO に詰め直す際、Boolean 型に変換する作業を横着しようとしたのか、DB のカラム定義が CHAR(1) にされており、"0" か "1" のいずれかが直接文字列として保存されるような作りになっていた。

というか、なんなら Form Bean には DB 登録用の DTO が直接プロパティとして定義されていて、その DTO の中のチェック状況を管理するプロパティに直接 "0" とか "1" とかセットさせるようになっていた。この DTO を直接、DB 更新時のパラメータとして投げ渡していたのだ。画面用の Form Bean と DB 用の DTO (Entity と表現しても良いか) の分離が全くなされていない酷い設計だ。

画面入力された値は String 型のプロパティで受け取る必要がある、というフレームワークによる制約をそのままに、DTO に画面入力と DB 更新の両方の責務を持たせたような作りは混乱を招く。True か False のいずれかしか取らないはずの項目が CHAR 型だと、想定外の文字列が入っていないか常にチェックする必要が出てくるし、大変扱いづらい。

フレームワークの都合に依存するのは、Struts1 の場合 Form Bean (画面入力値) までにし、Action クラスは Form Bean を受け取ったらすぐに型変換用のメソッドを呼んで Model が扱いやすい JavaBeans に直し、実際の処理をする Model に JavaBeans を渡すようにすべきだ。そうすれば、Model は Form Beans に依存しない作りになるし、Boolean であるべきプロパティは既に型変換されていてちゃんも Boolean として扱えるようになってるわけだから、分かりやすくなる。そしてもっと言えば、Model が受け取る JavaBeans と、DB 更新時に使う DTO (Entity) は別々のクラスにすべきだ。基本的には BeanUtils#copyProperties() で詰め替えられるし、特殊な理由で手動での詰め替えの手間が増えようと、そこは分離すべきだ。

だいたい Action クラスにビジネスロジックをビッシリ書いて直接 DB 更新とかやっちゃってるシステムを見てるので、そういう思想になる以前のド素人が書いたんだろな、とは思ってるけど、本来は、なるべく外部の制約を受ける範囲を狭めるように設計すべきだ。