S2Utilその後

以前
S2Utilプロジェクトが始まりました。 - wyukawa’s blog
でS2Utilプロジェクトのことを書きましたが、今回は開発インフラやその後の動きを書いてみたいと思います。

まずは開発インフラ面から。

SVNリポジトリはこちらです。興味のある人はのぞいてみるといいと思います。
https://www.seasar.org/svn/sandbox/s2util/trunk/s2util/

注意点としてはEclipse3.6でチェックアウトしないとコンパイルエラーになることです。

なぜかというと例外のテストをするためにorg.junit.rules.ExpectedExceptionを使っているからです。
Eclipse3.5だと同梱しているJUnitのバージョンが古いためコンパイルエラーになります。ま、jarを追加すれば大丈夫です。

Hudsonのジョブはこちら
https://www.seasar.org/hudson/job/s2util/

当初はインスペクションやカバレッジもとろうとしたのですが、
FindBugs使うと「[Fatal Error] findbugsTemp.xml:157:51: Character reference "�" is an invalid XML character.」と言われたり、PMDも一見うまく言っているように見えてEclipseプラグインでの実行結果と大きく異なったり、カバレッジとろうとするとうまくとれないばかりでなくテスト件数が2倍になります。というわけで、ちょっと頓挫してます。ま、そのうちやるということでw

次にコードの中身はというと、前回例外とログに関しては触れました。

例外に関しては
NullPointerExceptionなどの標準例外を使っていないわけ - taediumの日記
にならってNullPointerExceptionやIllegalArgumentExceptionのようなJavaの標準例外をthrowしません。

引数チェックは主にAssertionUtil(guava, Google Collection LibraryでいうとPreconditions相当)でやっているのですが、NullArgumentException, EmptyArgumentException, SIllegalArgumentException, SIllegalStateException, SIndexOutOfBoundsExceptionをthrowするようにしています。その他の箇所でも必要に応じてSNoSuchElementException, SUnsupportedOperationExceptionをthrowしています。

新規APIに関してはお約束っぽいCloseableUtil(元の例外を消す可能性があるとのことで例外発生時に実行時例外にラップしてthrowするようなことはしていません。単純にログを出します。)以外に面白いものがあるので紹介します。

それは行単位に文字列を反復するイテレータLineIteratorです。
使用例はこんな感じ。

 import static org.seasar.util.io.LineIterator.*;
 BufferedReader reader = ...;
 for (String line : iterable(reader)) {
     ...
 }

またインデックス付きのイテレータIndexedIteratorもあります。これを使えばこんな感じ。

 import static org.seasar.util.collection.IndexedIterator.*;
 import static org.seasar.util.io.LineIterator.*;
 BufferedReader reader = ...;
 for (Indexed indexed : indexed(iterable(reader))) {
     System.out.println(indexed.getIndex());
     System.out.println(indexed.getElement());
 }

コレクションクラスにも使えます。

import static org.seasar.util.collection.IndexedIterator.*;
 List<String> list = ...;
 for (Indexed indexed : indexed(list)) {
     System.out.println(indexed.getIndex());
     System.out.println(indexed.getElement());
 }

Javaはメソッドの戻り値に複数の値を返せないので、Pythonのenumerateほどスマートには書けないですが、悪くないかなと。

DTOのListをイテレータでまわして偶数、奇数で色分けとかする場合にそこそこ便利なんじゃないかと思います。

普通に書くと

int index = 0;
for(String str : list) {
  ...
  index++;
}

と拡張for文使ってインデックス変数を使うか(この場合変数のスコープが長くなる)、

for(int i=0; i<list.size(); i++)

みたいに旧式の書き方になります。ま、僕もBeanのメソッドを呼び出すぐらいならこのどっちかでいいんじゃねって思ってましたが、需要はありそうなのでLineIteratorを真似てIndexedIteratorを作ってみました。

以上、細かすぎて伝わりにくいかもしれませんがw ご紹介まで。