Actionクラスにロジックを書くな!!
新しいプログラマーが来るたびに同じこと言わすなっつぅの!
多分、ネットで引っかからないんだろうな。
だから、書いておくことにした。
もぅ、Shaleや、JSFもあるし今更感は多分にありますが、今更ながら言わされたので。。。
プレゼンテーションロジックは、ActionFormに書くのじゃ!!
その理由を説明していくことにしよう。
まずは、Actionクラスに書く(と思い込んでいる)人の主張も聞いてみよう。
雑誌とか、ネットのサンプルだとActionクラスにロジックを書いている
私も雑誌等に記事を書いたことがあるので分かるのですが、紙面にはページ数という制限があります。よしんば無かったとしても、だらだらと長い記事やページを誰が読むというのでしょう。
基本的に、雑誌やWebページでStrutsを使用したコードを載せる場合は、大抵がStrutsのAPIの使用方法の説明であり、コードデザインのお話にフォーカスをあてている記事は皆無といっても良いでしょう。
このような場合、複数クラスに処理を分けて記述するのは無駄なのです。伝えたいこと(APIの使用方法)を簡潔に伝えるためには、あえてクラス分割をするのは冗長なのですよ。
こーゆーことは、別に記事を書いたことがない人でも、察せられると思うんですけどねぇ。
ActionFormにgetter/setter以外って書いていいんですか?
駄目な理由が全く見当たりません。
こういう人は、POJOにもロジックを持つことを大抵嫌いますね。
POJOって、Plain Old Java Objectの略ですよ。昔からJavaのオブジェクトはデータと振る舞いを持ってましたよ。
後者はともかく、前者の意見からは、その人の考えが全く見当たりません。もっと考えましょうよ。
で、こっからは私のActionFormで書くべきであるという主張を書いていきます。
リファクタリングを進めていけば、ActionFormへの移動は当然の帰結
ちゃんと、ビジネスロジック層とプレゼンテーション層を分けている場合、Actionクラスの多くの処理は、ActionFormオブジェクトからDTO(Data Transfer Object)への移送処理で構成されるはずです。つまり、
HogeDTO dto = new HogeDTO(); dto.setFoo(form.getFoo()); dto.setBar(form.getBar()); :
みたいな感じですね。これらの処理は当然のことながらActionFormが保持しているプロパティに依存しています。
リファクタリング―プログラムの体質改善テクニック (Object Technology Series)
では、このような処理を、「不吉な匂い」と表現しています。つまりリファクタリングすべき処理だと断じています。
このケースは、「メソッドの移動」リファクタリングを行うべきなのですが、イベントディスパッチャーであるメソッドそのものを移動することは出来ないので、まずは、移送処理等ActionFormオブジェクトへ依存度が高い処理を「メソッドの抽出」を行った上で、抽出を行ったメソッドを移動させる。と言うリファクタリングを施すべきです。*1
Actionクラスはテストがしにくい
JUnitを使用したことがあれば、出来るだけ多くの処理をJUnitで簡便にテストをしたいと考えるのは、普通のプログラマとしては当然のことだと思います。
ActionFormにロジックが集中していれば、テストコードとしては、
- ActionFormオブジェクトを生成する
- テスト条件を満たすようにプロパティに値をセットする
- ロジックを実行する
- ActionFormのプロパティの状態やデータベースの中身を検証する
と言う、通常のオブジェクトのテストコードとほぼ同様の記述が行えます。
Actionクラスのexecuteメソッドに処理を記述してしまうと、HttpServletRequest等Mockを作らなければいけないものが増えてしまいます。
近年のプレゼンテーションフレームワークもこの流れ
代表格はJSF。
イベントディスパッチは、完全にコンテナ側に隠蔽されて、プレゼンテーションロジックは、ManagedBeanで記述するようになりました。
数年前セミナーで、StrutsからJSFへのフレームワーク置き換えを実演したのですがあっさり移行できちゃいます。
時代の流れ的にもActionにロジックを書くと言うコードデザインは淘汰されていきつつあるのです。
もー一回言います。
プレゼンテーションロジックは、ActionFormに書くのぢゃっ!!
*1:通常は面倒だから同時にしちゃいます