[Seasar][Teeda][DBFlute]S2Dxoを使わない選択肢
上記のTeeda + DBFluteのサンプルを見て驚いた。なるほどぉ、こういうDxoを使わないやり方もあったのか!
実に学ぶことが多い。素晴らしいサンプルコードです。
【ポイント1】ForeachにDtoのリストではなく、Entityのリストを用いている
わざわざForeach用にDtoを作成しなくてもいいのが嬉しい。
private List<Book> resultItems;
【ポイント2】S2Dxoを使わずにForeachを実現している
ポイントは currentメソッドですね。一般的なTeedaのForeachの処理としては、フレームワーク側がSetter経由でフィールドにセットした現在行の列の値をGetter経由で読み取ります。一方、この方式では、このcurrentメソッドのおかげで、Foreach用の各Getterメソッドの内部で現在行のEntityを取得できるようになります。各Getterメソッド内でDxoに相当する処理の一部を記述するという訳です。この方法の隠れた利点として、Foreach用のGetterさえ用意すれば、フィールドやSetterを用意しなくても済むということがあげられます。
protected Book current() { if (resultItems != null && !resultItems.isEmpty()) { return (Book) resultItems.get(resultIndex); } String msg = "The resultItems had no item so DON'T invoke this method!"; throw new IllegalStateException(msg); } public String getBookId() { return current().getBookId().toString(); } public String getBookName() { return current().getBookName(); } public String getIsbn() { return current().getIsbn(); }
【ポイント3】NotNullでない関連エンティティのNull対策をif文を使わずに実現している
下記の例では、getAuthorメソッドの代わりにtraceAuthorメソッドを用いている。traceAuthorメソッドはgetAuthorメソッドと異なり、authorがnullの場合には空のエンティティを返します。これによって、getAuthorNameメソッドの呼び出し時に NullPointerExceptionが発生しません。つまり、Null対策のためにif文を使った分岐処理を書かなくても済んでしまいます。
public String getAuthorName() { return current().traceAuthor().getAuthorName(); }
publicフィールドの導入やPage間で重複する処理をAbstractの親Pageに移動することで、さらにコード記述量も減るので、わざわざActionとPageを分離しなくても良いと思う。
追記:
TeedaでForeachを実現するためには、Entityのリストではなく、わざわざ専用のDtoのリストを用意して、さらにDtoの中身と同じアクセッサをPageに用意する方法が一般的です。今はこの方法に、すっかり慣れてしまいました。しかし、Teedaを触り始めた時は、この方法はDRY原則にも反していることもあって少し違和感を感じていました。
でも、今回のDxoを用いない方法ならば、DxoやDtoを作成する必要がないだけでなく、Pageクラスの繰り返し用のフィールドやそのSetterメソッドの記述を不要にし、単なるアクセッサではない、意味のあるGetterをスマートに書くことができる。コード量も少なくなり、可読性も向上する。これならば、これからTeedaを触る人でも、私が触り始めた頃に感じたForeachの違和感を感じることは無いように思えます。
しかし、現段階では、検討が不十分だが、今回のやり方は、参照系のPageでしか有効にならないと思う。PageクラスからEntityクラスに変換する必要のある更新系の処理にはDxoを使う方が楽だと思う。(他にも、まだ、試していないが、プルダウンなどの選択項目用に共通コンポーネントとして LabelValueDxo のようなものを作っておくのは有効かも。)
いずれにせよ、あまりフレームワークの設計者が考慮していなかった(?)と思われるところから、利用者側から画期的な活用方法が生まれるのは面白い。