Diary

事前条件(Precondition)を使おう

Guiceのソースコードを読んでいて、至る所に事前条件をチェックしている部分があった。
たとえばAbstractModuleのconfigureメソッドは次にようになっている。

  public final synchronized void configure(Binder builder) {
    checkState(this.binder == null, "Re-entry is not allowed.");

    this.binder = checkNotNull(builder, "builder");
    try {
      configure();
    }
    finally {
      this.binder = null;
    }
  }

checkStateでメソッドを実行する前のメンバの状態をチェックし、checkNotNullで引数がnullで無いことをチェックしている。
もしチェックに失敗すると、第2引数をメッセージとして持つIllegalStateExceptionやNullPoがスローされる。

ちょっとの手間をかけるだけで頑健なプログラムを作るのに役に立つし、ソースコードを見る側にも「このメソッドが呼ばれたときにどういう状態になっているべきか」がわかりやすくなる。
次作るプログラムは事前条件をチェックするようにしてみよう。

なお、Guice3.0のPreconditionsクラスには次のチェックがある。実際のソースコードはこちら

  • checkArgument
    引数をチェックする。チェックに失敗するとIllegalArgumentException。
  • checkState
    メソッドを実行した際の、インスタンスの状態をチェックする。チェックに失敗するとIllegalStateException。
  • checkNotNull
    nullではないことをチェックする。checkNotNullメソッドの戻り値を使うことで、nullでないことを保証する。チェックに失敗するとNullPointerException。
  • checkContentsNotNull
    Iterableにnullが含まれていないことをチェックする。ArrayListなどはadd(null)を許容するため。チェックに失敗するとNullPointerException。
  • checkElementIndex
    要素のインデックスをチェックする。負のインデックスになっていないか、サイズを超えていないか。チェックに失敗するとIndexOutOfBoundsException。
  • checkPositionIndex
    ポジション(?)のインデックスをチェックする。checkElementIndexと違い、たとえば要素のサイズが5の時に、5のインデックスはOK。チェックに失敗するとIndexOutOfBoundsException。

Preconditionsクラスをコ(ry 参考にすれば、すぐに事前条件を使ってバグの少ないメンテナンス性の高いコードを書くことができるので、是非とも使ってみよう!

ASCII.technologies6月号に寄稿しました

技術誌ASCII.technologies 6月号「Google API大辞典」の一部パートを担当しました。
有名どころからマイナーなものまでGoogleのAPIを解説しているので、GoogleのAPIに興味がある方には良い特集になっていると思います。

購入するとPDFもダウンロードすることができるので、iPadなどでも読むことができるようになっています。

ぜひ購入して読んでみてくださいっ!

Android Marketでダウンロードができなくなったときの対策

Android DevPhone1(Android 1.6)で、Android Marketからアプリをダウンロードしようとしても、すぐにダウンロードが中断してしまい、アプリがインストールすることができなくなってしまった。

検索すると解決策があり、それを実行すると解決したのでメモ。

情報元はAndroid Marketからのアプリダウンロード

  1. 「Setting」->「Applications」->「Manage applications」->「マーケット」->「Clear cache」を選択してキャッシュをクリアする。
  2. 「Setting」->「Applications」->「Manage applications」->「Google Apps」->「Clear data」を選択してデータをクリアする。
  3. 「Setting」->「Data synchronization」を選択して、アカウント情報を入力する。

これでいけた。

Eclipse(TCP/IP Monitor)でHTTPの通信をモニタリング

とあるHTTP通信を行うプログラムを作成していて、その通信内容をモニタリングしたいときがある。
そういうときは通信内容を表示できるプロキシサーバが欲しい。

そんなときにEclipseの TCP/IP Monitorプラグインの出番である。
TCP/IP Monitorプラグインは、「自分の○番ポートに接続があると、設定した×サーバの△ポートへ接続する」機能を持つ。
テスト対象サーバを設定し、クライアントでEclipseを動作させているマシンへ接続すると、通信の中継をしてその内容を表示してくれるわけだ。
テキストや画像を識別し、画像であれば画像を表示することができる。

・インストール方法

TCP/IP MonitorはEclipse WTP(Web Tools Platform)に含まれているので、WTPがインストールされていない場合はWTPをインストールする。
WTPのインストールはこの辺を参照。

・実行方法

TCP/IP Monitorはビューなので、Window->Show Viewを選択し、TCPで検索したら出てくる。出てこない場合はWTPがインストールされていないので、先にインストールしよう。ちなみにShow Viewで開いたDebugの中にTCP/IP Monitorはある。

・モニタリング方法

モニタリングするには、まず設定が必要だ。
ビューの下△のメニューを開き、Preferencesを選択する。

ダイアログが開くので、Addボタンから設定を追加しよう。テストしたいサーバのアドレスとポートを設定し、Eclipseを動作させているマシンの何番ポートをListenするかを入力する。
そして忘れずStartボタンを押そう。

あとはクライアントでEclipseを実行しているマシンの設定したポートへ接続すると、その内容がビューに表示される。

便利!

Niconico Live CheckerにNGワード機能を追加しました

1年以上振りにNiconico Live Checkerをバージョンアップしました。
変更点はNGワード機能の追加です。番組リストから右クリックしてNGワードに追加するか、メニューのツール->NGワードの追加から追加できます。
NGワードを登録すると、コミュニティ名か番組タイトルにそのキーワードを含む番組が放送中リストに表示されなくなります。

ダウンロードはNiconico Live Checkerからどうぞ。

StAX APIの実装による動作の違い

JavaでXMLをパースする際にはStAXを使用している。
Java6標準のパーサでも良いけど、Woodstoxをクラスパスに含めると、内部で勝手にWoodstox実装を使ってくれる。

が!APIが同じなのに 動作が微妙に違うので結構ハマる。

今気づいている範囲では次の3点が違う。
バージョンはJava1.6.0_22とWoodstox 4.1.1

・Java標準の場合、Character部分に実体参照(&など)があると、そこでCharacterが分割される。
なのでStartElementを見つけたら次のCharacterElementのデータを取るだけでは、実態参照の手前までしかデータを取ることができない。
Woodstoxの場合は実態参照があっても分割されない。

・Woodstoxの場合、XMLStreamWriter#writeCharactersにnullを入力するとNullPoが発生する。
Java標準の場合、nullを入力しても何も起きない。

・Java標準の場合、XMLStreamWriter#writeCharactersで”>”が”>”に置換されるが、Woodstoxの場合は”>”のまま
普通は問題ないと思うけど、場合によっては問題になるかも。

カスタムタグからPolymorphicModelなモデルをDatastore.queryすると怒られる

カスタムタグのクラス内でDatastore.queryしたときに、検索対象のクラスがPolymorphicModelだと次のエラーが出る。GAEにdeployすると問題なし。Aはクラス名で、共に同じものが入る。ちなみにPolymorphicModelじゃない通常のモデルだと、カスタムタグのクラスから普通に検索できていた。

IllegalArgumentException The model class(A) is not assignable from entity class(A)

問題はDatastoreUtilのgetModelMetaメソッドで発生する。
PolymorphicModelじゃなければ、classHierarchyListがnullなので問題ない。PolymorphicModelの場合は次のif文でClass#isAssignableFromを用いて本当にサブクラスかチェックしているのだけれど、そこでチェックに失敗し例外が出る。クラス名を見る限り同じ名前なのでなぜチェックに失敗するのかは不明。Slim3はアクセス毎にクラスローダを生成するとのことで、それ関連かな?同じ名前だけど内部的には違ってるとか。

CoolクラスからHotクラスにアクセスした際に出る「CoolBridge使えよ!」と言ういつものエラーではないのでとまどうかもしれないけれど、CoolBridgeを使うことで問題は解決する。

PolymorphicModelじゃ無ければ問題が出ないのが何かスッキリしないけどまぁいいや。

なおSlim3のバージョンは1.0.6。

GAE/Jのローカル環境サーバでDatastore Viewerを使う

Google App EngineにデプロイしたアプリケーションのDatastoreは管理コンソールのDatastore ViewerからDatastoreを確認することができる。

ローカル環境のサーバでももちろんDatastoreの中身を見たい!

そんなときは次のURLにアクセスする。
http://localhost:8888/_ah/admin/datastore

Entityを削除することはできるようだけど、編集する事はできない様子。

情報元はローカル環境でDatastoreのデータを閲覧する方法 for GAE/j

Google App Engineの料金メモ

ググればすぐ出てくるけど、自分用メモ。

課金対象の割り当ての単価

リソース 単位 単価
発信帯域幅 GB $0.12
受信帯域幅 GB $0.10
CPU 時間 CPU 時間 $0.10
保存データ GB/月 $0.15
メール受信者 受信者 $0.0001

課金登録していない場合の無料リソース

GAEのQuota Detailsから。

CPU Time 6.50CPU hours
Requests 43,200,000
Outgoing Bandwidth 1.00GB
Incoming Bandwidth 1.00GB
Total Stored Data 1.00GB
Blobstore Stored Data 1.00GB

CPU時間が意外と厳しい。
課金登録するだけで無料リソースの上限があがるらしいけどそれはどこにあるのか・・・と思ったら次のページの下の方にあった。一番欲しいCPU時間、送受信転送料は課金登録しても無料分は変わらないぽい。

Google App Engine – 割り当て

Redmine 1.1.0のインストール時にMissing the i18n 0.4.2 gem

Redmine1.1.0をCentOS5.5.にインストールした際にちょっと躓いたのでメモ。
Redmine 1.0をCentOSにインストールする手順は同じくCentOS5.5へのインストールドキュメントだったので、一つの問題を除いてこのままうまくいった。

その問題とは # rake db:migrate RAILS_ENV=production を実行すると次のエラーが出力されるというものだ。

Missing the i18n 0.4.2 gem. Please gem install -v=0.4.2 i18n

ネットを検索すると同じようなエラーが出ている人がいたが、その解決方法ではどれも解決しなかった。

で、どうやれば解決したかというと、.bashrcに次の一行を追加した。

export GEM_PATH=/usr/lib/ruby/gems/1.8/gems/

で、解決。

でもGEM_PATH設定しなくてもgem listやputs Gem.latest_load_paths()してちゃんとi18nが見えているのは確認したんだけどなぁ。