思いついたこと(2)

  • JDOはどう考えてもDatastore Low Level APIと相性が悪い
  • Low Level APIはEntityを生で扱うあたりがありえない
  • Javaはかなり厳格にnominal typeを扱うので、Pythonのような無茶がしにくい

というあたりで、モデル記述からエンティティモデルを自動生成するスタイルが妥当かなーと思っていましたが、モデル記述の記法で悩んでました。DSL使えばいいんですが、俺俺言語すぎるのもアレだなと。

ということでJavaの言語内DSLっぽくやればいいんですけど、これはこれで面倒。

  • Beanに規約ベース/注釈ベースで属性書いていくのはあまり好きじゃない
    • getter/setterのドキュメント書くのがめんどくさい
    • getter/setterにミスマッチが紛れ込むかも
  • public fieldに属性書いていくのも好きじゃない
    • リフレクションを経由しないとメタ情報を取得できない

なんとなく思いついたのが、実際に使うエンティティクラスを装飾するんじゃなくて、エンティティ飲めた情報をクラスで定義して、それを装飾すればいいんじゃないかと。

こんな感じ。

@Meta
public class HogeEntityMeta {
    
    public static final Property<Integer> foo = Property.of(Integer.class);

    public static final Property<String> bar = Property.of(String.class, new Constraint<String>() {
        public void validate(String value) throws ValidationException {
            if (value == null) {
                throw new ValidationException("is null");
            }
            if (value.length() > 500) {
                throw new ValidationException("is too long");
            }
        }
    });
}

これをaptで読んで、メタ情報からエンティティクラスを生成する。

public class HogeEntity {
    private Integer foo;
    private String bar;
    public Integer getFoo() { return foo; }
    public void setFoo(Integer foo) { this.foo = foo; }
    // ...
}

実際はドキュメントの生成もしたいので、メタ情報のクラスフィールドにJavadocを書いておけば、エンティティクラスのgetter/setterにも反映されるとかにしておく。

Low Level APIのエンティティからHogeEntityに変換する場合は、data exchange object classもついでに生成してやればいい。逆変換も同様。

これまでは、エンティティクラスのほうに注釈つけるのがよくある手法でしたが、こういうようにメタ情報を注釈そのものにしておいて、そこからエンティティクラス生成するのがよさそうな気がしてきた。