Actionクラスにロジックを書くな!!

新しいプログラマーが来るたびに同じこと言わすなっつぅの!
多分、ネットで引っかからないんだろうな。

だから、書いておくことにした。
もぅ、Shaleや、JSFもあるし今更感は多分にありますが、今更ながら言わされたので。。。

プレゼンテーションロジックは、ActionFormに書くのじゃ!!

その理由を説明していくことにしよう。


まずは、Actionクラスに書く(と思い込んでいる)人の主張も聞いてみよう。

雑誌とか、ネットのサンプルだとActionクラスにロジックを書いている

私も雑誌等に記事を書いたことがあるので分かるのですが、紙面にはページ数という制限があります。よしんば無かったとしても、だらだらと長い記事やページを誰が読むというのでしょう。
基本的に、雑誌やWebページでStrutsを使用したコードを載せる場合は、大抵がStrutsAPIの使用方法の説明であり、コードデザインのお話にフォーカスをあてている記事は皆無といっても良いでしょう。
このような場合、複数クラスに処理を分けて記述するのは無駄なのです。伝えたいこと(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)
リファクタリング―プログラムの体質改善テクニック (Object Technology Series)
では、このような処理を、「不吉な匂い」と表現しています。つまりリファクタリングすべき処理だと断じています。
このケースは、「メソッドの移動」リファクタリングを行うべきなのですが、イベントディスパッチャーであるメソッドそのものを移動することは出来ないので、まずは、移送処理等ActionFormオブジェクトへ依存度が高い処理を「メソッドの抽出」を行った上で、抽出を行ったメソッドを移動させる。と言うリファクタリングを施すべきです。*1

Actionクラスはテストがしにくい

JUnitを使用したことがあれば、出来るだけ多くの処理をJUnitで簡便にテストをしたいと考えるのは、普通のプログラマとしては当然のことだと思います。
ActionFormにロジックが集中していれば、テストコードとしては、

  1. ActionFormオブジェクトを生成する
  2. テスト条件を満たすようにプロパティに値をセットする
  3. ロジックを実行する
  4. ActionFormのプロパティの状態やデータベースの中身を検証する

と言う、通常のオブジェクトのテストコードとほぼ同様の記述が行えます。
Actionクラスのexecuteメソッドに処理を記述してしまうと、HttpServletRequest等Mockを作らなければいけないものが増えてしまいます。

近年のプレゼンテーションフレームワークもこの流れ

代表格はJSF
イベントディスパッチは、完全にコンテナ側に隠蔽されて、プレゼンテーションロジックは、ManagedBeanで記述するようになりました。
数年前セミナーで、StrutsからJSFへのフレームワーク置き換えを実演したのですがあっさり移行できちゃいます。
時代の流れ的にもActionにロジックを書くと言うコードデザインは淘汰されていきつつあるのです。



もー一回言います。
プレゼンテーションロジックは、ActionFormに書くのぢゃっ!!

*1:通常は面倒だから同時にしちゃいます