先のエントリのコメントでいただいたように、ドメイン駆動設計はよいのだが、FATではなくライトな設計にしたいという観点も確かにあります。
今回は、手で一から書くと何かとコードが煩雑に成りがちのDXOについて考えてみます。
たとえば、DXOしない場合はUIやドメイン、データアクセス(インフラストラクチャ)の各レイヤに、同じ型のモデルを使い回すことになります。このモデルには、各レイヤーの責務が重複して存在することになります。責務の単一原則からしてもそのモデルは変更の影響を受けやすいこともあるし、そもそもレイヤーの整合性を維持するもの難しく、依存関係もカオスになりがち。
なので、DXOはなるべくやったほうがいいというのが私の考え。まぁ、それはわかるけど、DXOってコードを書くのがたるいじゃない、もう少しDXOを楽に実装できないの?って話題です。
S2Utilを使ってDXOする
まず、紹介したいのはS2Utilです(現在開発中?)
S2Utilプロジェクトは,Seasar2からスピンアウトしたプロジェクトで,Seasar2 に含まれていた様々なユーティリティクラスを単独のライブラリとして提供します.
Seasar2 のユーティリティクラスの多くは J2SE1.4 を前提としていましたが,S2Util では Java5以降のジェネリックスや可変長配列に対応するなどの変更が加えられています.
DXOだけではなく、他にも様々なAPIが用意されていて、コーディングの手助けになることは間違いないでしょう。特にジェネリックス対応はうれしいですね。それにSeasar2に依存していないので、SpringのプロジェクトやDIを使わないプロジェクトでも使いやすいのではないでしょうか?*1
S2Utilを使ってDXOするなら、
org.seasar.util.beans.util.BeanUtil
クラスです。
二つのJavaBeansのインスタンスをコピーしたいなら、以下のようにすればDXOが可能です。型が異なっても同名のプロパティは値を変換してコピーしてくれます。
import static org.seasar.util.beans.util.BeanUtil.*;
copyBeanToMap(srcBean, destMap);
copyMapToBean(srcMap, destBean);
static importを使えば、コードの見通しがよくなりますね。
srcBeanを基にDestBeanのインスタンスを生成するなら、以下です。
import static org.seasar.util.beans.util.BeanUtil.*; DestBean destBean = copyBeanToNewBean(srcBean, DestBean.class); DestBean destBean = copyMapToNewBean(srcMap, DestBean.class); Map<String, Object> destMap = copyBeanToNewMap(srcBean);
import static org.seasar.util.beans.util.CopyOptionsUtil.*;
copyBeanToBean(srcBean, destBean, excludeNull());
のようにCopyOptionsを使うと変換の制御ができるようです。CopyOptionsもConverterもカスタマイズできるのでプロジェクト固有の命名規則にもあらかじめ対応することができると思います。それでも、変換できないプロパティについては手動で変換すればよいと思います。あ、斜め読みしただけでよくわかっていませんが、CopyOptions#toBeanDestPropertyNameをオーバーライドすればコピー先のプロパティ名が異なる場合でも対応できそうですね。
他にも使えるライブラリはある
ジェネリックスに対応していませんが、apache commons-beanutils, Spring BeanUtilsもDXOに使えますね。GAEならSlim3にもBeanUtilがあります。
あと、Seasar2にはS2DxoというAPIもあります。こいつはDXOの変換ルールをOGNLで書けるという強者ですw S2DaoのようにDxoインターフェイスが増えますが、プロパティが同名じゃないルールにもさっくりと対応できます。
ということで、典型的なDXOはライブラリを使って実装すれば手間はそれほどかからないと思うんです。S2DxoやS2BeanUtilsを使った案件を数多くやってきましたが、実装コストが問題になったことないですね。それより、DXOをしないでレイヤーを混同したことによる弊害で、カオスになっているプロジェクトはたくさん見てきましたw こういうライブラリやコードの自動生成で、対応するほうがよいのではないかと思います。