著作一覧 |
GUIDの表記方法は、{AABBCCDD-EEFF...}だが、実際のバイト配列としてはDDCCBBAA...というようにリトルエンディアンが使われる。
あるテーブルのキーにGUIDを利用しているのだが、ディスプレイ表現(って言うのかな? 可読表現)としては、{AABBCCDD...}のほうを利用しているとき、都合3つの処理を経由してから読み取りが行われるアプリケーションを構成した。
1. パラメータにGUIDを付加したURLを生成し、該当URLへのアンカータグを乗せたHTMLを返送する(ここでは読み込み対象には特別なセキュリティ的な考慮は不要で、人間がGUIDを入れるのは大変だからLINKを生成しているので、GETのクェリーストリングとしてURLに組み込むことに問題は無い。というかwgetでGUIDを指定するシェルもあるし、いざとなればURL直打ちの読み取りもやる必要がある)
2. (Strutsを使っているので)ActionForm#getGuidを通してActionがGUIDを取り、モデルに与える
3. モデルは与えられたGUIDをキーとして読み込む。
で、3でどうやっても読み取りエラー(というかSELECTの結果が0件)となる。ユニットテストではうまく行くのにエラーになる。
ここで、サクッと1と2の過程を疑えば良いのにそうしなかったのは、なぜなのかなぁ。1. ではアンカータグのテキストとしては可視表現、しかしクェリーパラメータとしては後の加工の楽さを考えてニブルを文字列化したもので表現していた。しかし2.の作成時点では、アンカータグのテキストに引きずられて可視表現化されたGUIDからバイト列化する変換をかけてた。そのため、本来のGUIDとは異なる値が渡っていたのだった。
教訓1:GUIDからバイト列への変換関数がまずい。フォーマットが異なる文字列を与えられたら例外を通知すべきだ。(与えられた文字列から単純に{}-を捨てて結果の32文字のニブル表現からエンディアンを考慮してバイト配列に直すように実装していたため、最初からニブル表現でもそのまま処理が通り、単純にエンディアンの交換処理が実行されてしまっていた。文字数や{}の有無でよいから最初にチェックすべきだろう。
教訓2:見た目と異なるデータというのは必ずしも良くない。見た目が可視化表現のため、2.のステップで特に意識せずに変換関数を呼び出している。
教訓3:思いつきで作っていく場合には、入出力くらいメモしておいたほうが良い。1を作った時点では、クェリーパラメータの流れはコンピュータ処理なんだから最初からニブルにしておけば効率的だと考えたのであった。が、2を作る時点でコロリと忘れている。
教訓4:簡単過ぎるプログラムは問題かも。2のActionは実質8行くらいのコードしか持たないのでここに問題があるなんて全然考えつかなかったのは良くない。これが40行くらいあれば、テストプログラムを作ってただろうな、とか早めに見直したかも。
教訓5:テストを信用する。モデルはテストを通ってるんだから、ここに問題が無いのはわかっているのに、(テーブルの扱いにちょっと特殊なことをしているため)ここを疑って無駄な時間を使ってしまった。
特に1と2だ。5は反省点。
ジェズイットを見習え |