Locked History Actions

wicket/Problems

文字列による結合問題

Wicketは非常に便利なフレームワークであるが、もちろん問題が無いわけではない。 特に大きな問題は、現代のIDEでは扱いにくい「文字列」による指定が様々な場所で前提となっている点である。 Wicketの考え方はこれまでのウェブ開発の常識を打ち破った革新的なものであると個人的には思うのだが、 それとは不釣合いなおかしな仕様が見受けられるのはとても残念である。

wicket:idの問題

htmlにおいて

<div wicket:id="something"></div>

というWicketのためのIDを埋め込んでおき、Java側ではそれを

 add(new Label("something", "これはテストです"));

などとして参照しなければならない。htmlとJava上のコンポーネント生成を結びつけるだけならば良いのだが、この文字列によるwicket:idはJavaプログラム中のあらゆるところに現れてしまう。例えば、フォームのフィールドに対する値の設定・取得、さらにはWicketTesterによるテストの際にもこの文字列が必要になる。

当然のことながら、IDEはこれらの二つが同じものを示していることを認識していないので、リファクタリングとしてこれらのIDを変更する際にはいちいち手作業で確認を行う必要がある。

もちろんテストを走行させてみればエラーの検出はできるし、それを受けて修正すればよいことであるが、しかし現代的な開発環境においてはこれは退化としか言えない。現代のIDEにおいては、変数や定数の名称を変更すればそれを参照するすべてのソースに反映されるようになっているのである。Wicketではこのような機能が全く使えない。

ただし、Wicketのベストプラクティスとして、そのような事柄が推奨されているのかどうかわからないが、以下のようにJava側で定数を定義し、それを使いまわすことは可能である。

 public static final String ID_SOMETHING = "something";
  ....
 add(new Label(ID_SOMETHING, "これはテストです"));

少なくともこれ位はやっておくべきだろう。

PropertyModelの問題

この機能は使わなければ良いだけだが、一応触れておく。 PropertyModelは、指定されたPOJOの指定された名称のプロパティ値を取得するというものである。

public class Something {
  public String getValue() { return "hello"; }
}
....
Something something = new Something();
add(new Label("label", new PropertyModel<String>(something, "value")));

ドットで連結することにより、さらに「奥の」オブジェクトの値も取得できる。

public class Something {
  public String getValue() { return "hello"; }
}
public class Anything {
  public Something getSomething() { return something; }
}
....
Anything anything = new Anything();
add(new Label("label", new PropertyModel<String>(anything, "something.value")));

これが問題なのは明らかだろう。IDEはプロパティ取得メソッド名の変更は検出できるが、それがどの「プロパティ抽出文字列」と結びついているのか知らない。

CompoundPropertyModelはさらにひどい。POJOのプロパティ(プロパティとは名ばかりで実際は単なるメソッド呼び出し)とhtml上のwicket:idを暗黙的に結びつけてしまうのである。ruby界隈であればこのようなおかしなことがまかり通るのであろうが、卑しくもJavaなのである。なぜ強い型付けの言語なのかを考えてもらいたいと節に思う。

CoCを否定するわけではないのだが、使いどころを間違えるとひどい目にあいかねない。

WicketTesterの問題

最初に書いたように、htmlとそれに対応するコンポーネントプログラムは文字列のwicket:idにて結びつけられている。これは今の段階では仕方がない。例えば、Java中に(文字列ではなく)ネイティブな形でhtmlを記述することができれば、IDEは二つの結びつきを認識できるかもしれない。

ところが、テスト用のオブジェクトWicketTesterもそれを前提にしているのは、非常に大きな問題と言える。 少なくともテスターの側ではhtmlは完全に無関係である。htmlの扱いはPageオブジェクトに一任されているからだ。 しかし、このテスターではhtml上で記述されているwicket:idを文字列として指定することが前提となっているのである。

なおかつ、単にwicket:idを指定するならまだしも、目的のコンポーネントが他のコンポーネントの子になっている場合には、

  "someForm:someText"

のように、コロンで区切った形で指定しなければならない(PropertyModelはドットで、こちらはコロンだ)。

こんなことは不条理極まりない。テスターは実際のコンポーネントを作成してそれを操作するのであるから、そのJavaのコンポーネントを参照して、テストのための値の設定や取得ができるべきである。

拡張Wicketテスタを参照のこと。