オブジェクトとリレーションの狭間...
2009.02.23
というのは、今少しややこしい対応をしているんです。
それはですね、最初はこういうことでした...
申請された内容が、まだ他人から承認されていないのならば、申請者によって取り下げができるようにして欲しい....
まあ、やりたいことは判ります。けども、
「承認アクション」と「取り下げアクション」がもし競合したらどうしよう?
という問題、おそらく「取り下げができるようにしてね!」と依頼した依頼元は想像してないであろう問題が発生するわけです....ここらへん、川上と実装者の感覚の違いなのですがけどもねぇ、実装者としては「少し工数かかります...」と答えざるを得ないわけです。
で、現実的にはそれぞれのアクションの中での、DB周りの処理では、Spring+Hibernate なので、サービス単位でトランザクションが管理されるようになっていて、
トランザクションがかかっている単位(サービス)の中は、アトミックと見ていい
ことになるから、サービスの中で「他の利用者による更新が競合しているか?」について TestAndSet をする格好になるでしょうか。
しかし、ここで、Hibernate がO/Rマッピングだ、という事実がすこし邪魔になります....現実問題として、Hibernate がキャッシュを使って「キーが同じなら、インスタンスが同じ!」という仮定で動くことが、困るんですね。「テスト」ができないんです。
言い換えると、「渡されたインスタンスと同じキーを持つデータが、渡されたインスタンス以降に更新されたものかどうかをチェックする」わけですから、「同じキー」で時系列的に後のデータがあるかどうか?というチェックがしたいわけです...しかし、Hibernate は「同じキーなら同じインスタンス」と捉えてしますのです。これ、考えてみれば、
オブジェクトとリレーションの間の裂け目
にしたいことが転がり落ちちゃった....ということにでもなるでしょうか?
まあ、チェック側を HQL ではなくて、SQL 直でやれば、こっそり「今のデータ」を取ることができて、TestAndSet ができたわけですが、何となく釈然とはしないですね。そもそも
リレーションはオブジェクトではない!
という事実から目をそらすための一時しのぎ...なのかも。オブジェクトデータベースならこういうの問題にならない...かもしれません。
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.23 22:26
灰色の唄を歌おう...(後編)
2009.02.15
今更なんですが、少し前(2006年冬)のアニメ「あさっての方向。」という作品にハマってます...このアニメのBGMで、不思議な現象が起きる時に鳴る曲(光宗信吉作曲)で、木霊が響いていくような特徴的なリズムがあって、それが
回文のようなリズム
を使っているんですね。言い換えると、
リズム的に先頭から見ても末尾から見ても、同じになるリズム
で、現代音楽だとメシアンが「不可逆リズム」と名づけたちょっと面白いリズムです。
しかし、逆に考えてみると実に興味深い現象です。シンメトリーというのは一般的な表現のイディオムで、建物だったらシンメトリカルなのはアタリマエで少しも珍しくはないですよね? しかし、音楽ではシンメトリーは避けられる傾向があります: だってモチーフが動いていきにくいですからね....実際「あさっての方向。」の曲では、最後の音色が別な繰り返しリズムとダブるかたちになっていて、シンメトリカルな印象を薄めています。
で、ですがこのエントリはBCDやグレイコードを扱った「灰色の唄を歌おう...」の後編なんです。グレイコードは任意の表現ビット数に応じて、実はとっても簡単に作ることができてしまいます。その作り方のポイントはですね、
グレイコードはフラクタル図形を作る要領で作れる
ということです。言い換えると、「何ビット目が変化するのか?」ということに着目して各bit別の列を並べると、
2bit 121
3bit 1213121
4bit 121312141213121
のように、無限に成長する列を定義できます。これは中央の値でシンメトリーであり、しかも A-中央値-A の「A」が更に同じ構造を繰り返し持つ構造なのですね。BNFで書くと
<gray> :- <gray> digit <gray>
|- digit
という再帰構造で定義されるわけです(具体的に何ビット目を変化させるか、自体はグレイコードの本質とは独立であることも注意)。
ですから、グレイコードの構造は非常に興味深いものがあります。応用範囲も実はいろいろ広いわけで、たとえば隣り合う兄弟と1bitしか厳密に違わない性質は、遺伝的アルゴリズムの「遺伝子」に使いやすい性質ですし、パズルの解法で再帰的に総当りをする時のカウンタ代わりにも使える面白い技法だと言えます。更には、丸め誤差のない実数値表現とか、算術符号化圧縮とか、デジタルだけども無限に細かい連続値(アナログな実数値)をシミュレートする応用があったりします。応用範囲はかなり広いです....→参考「グレイコードと実数」立木秀樹
このグレイコードを応用した「歌」が、YouTube に上がってますね。その名も「グレイコードカウンタの歌」という画像です。何しているかは上記の説明で判ると思います。要するに 8bit グレイコードの最初から最後まで(256通り)を並べて、それぞれの変化ビットを音として鳴らすというアイデアですね。
ですからこれ、実際には「回文音楽」であり、しかも自己相似なフラクタルですから局所的にも「回文音楽」なのです....スタティックな構造自体はすぐに聞いて取れますから、理解可能な音楽ですけども、やはり動きが決まりきっていて.....という印象は蛇足かな。
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.15 11:09
灰色の唄を歌おう...(前編)
2009.02.13
別に悲観的な内容じゃ全然ないですよ(苦笑)
コンピュータでの「数値表現」は二進数が一般的だ、というのは世間一般での大常識です。とはいえ、昔のコンピュータだと、実は「二進数と言われても?」となるタイプのアーキテクチャがあったのをご存知ですか?(別に実験的なマシンじゃなくて、の話です)
それはですね、IBM1401 という60年代の大ベストセラーマシンですけども、これいわゆる「二進化十進数」(プログラマはBCDという言い方の方が馴染んでます)のアーキテクチャなのですね。このマシンでは(仮にCで書くと....)
int x = 9;
int *p = &x;
(*p)++;
printf( "0x%02x", *p );
は、0x0a ではなくて、0x10 になります(%x が数値的値ではなくて、ビットパターンを表示するとしての模式的な話、ですから真に受けないでね!)。言い換えると、
値を 4bit 単位で使って、それを十進数の1桁として扱う。だから、0x00(0)~0x09(9) は使われるが、0x0a~0x0f の範囲は数値表現としてはまったく使われない。
という「ビットの使い方」がBCDなのです。要するに、
COBOL の数値
と同じで、数値は「固定小数点で両方へ最大の桁数」というフォーマット情報を属性みたいに持って、その桁数の範囲だったら絶対に丸め誤差が発生しない...というものですから、金額計算メインのビジネス用コンピュータでは大きなメリットがあるわけですね。
まああと、7セグLED を点灯するのに、数値表現がBCDだと都合がいいために、LED 表示器が直接 BCD を受けるとか、相互に変換をする汎用ロジックICとか、結構使われるところでは使われる
ビットレベルでの数値の表現
なんですね(まあ負の数の表現法...となるとさらに複雑ですけどね...今回は正の数限定の話です。ちなみに Intel CPU ではインストラクションセットに AAA とかAAD とか AAM とか DAAとか、計算後の値を BCD に補正する命令が今でもあったりします....起源の古い DAA だと 8080 の昔からずっと、ね)。
なんでこんな話をしているか、というと、
コンピュータの中の「自然(ピュシス)」と「慣習(ノモス)」
という大問題の前フリだからです。言い換えると、
コンピュータの技術の中で、恣意的・人為的に決まっている約束事ではなくて、それ自体に意味がある『自然』はあるのか?
という哲学的(ごめん)疑問です。二進数表現でさえ、その表現形が観念上の数としてどれを表すか、という面では
それは約束事なので、それによる....
としか言いようがない世界なのです。ですから、二進数表現ではもっとヘンな、しかし使われるからには合理的な数値表現もあるのです。グレイコードといいましてね、
000(0) 001(1) 011(2) 010(3) 110(4) 111(5) 101(6) 100(7)
が3bit の場合の「グレイコードbit表現(数)」の対応になります。これ、一体何の役に立つのか...というと、実は
グレイコードは、隣り合う数値同士で、1bit づつしか相互に違わない数値のエンコーディング
なのです。一般の二進表現では、
011(3) の次は 100(4) だ
と、数字が1変わるだけなのに、3bit 変わる必要がこの場合あるわけです。このとき、
あれ?コンピュータは間違って 011 → (111) → (110) → 100 と変わる(変化の経路はテキトー)の間で、間違った値を拾っちゃいはしないか???
と悩んだことはありませんか(たとえばスレッドとか割り込み処理とかで...苦笑)? 実はコンピュータの内部(バスで接続されている)に限っては、クロックによる同期がちゃんと行われているので、そういうことはありえない(あったらハード的故障)し、また変化の遅いポートの読み出しなどは、
別なポート(READYとかそういう名前のピン)が変化した後は、そのポートの値が信用できる
という約束でビジーウェイトしながら読み出しをすることも結構ある(デバドラの初期化ルーチンなんてこんな感じのロジック多いですね)わけで、
タイミングによる読み間違いはないはず
なのです。しかし、
連続的に値を読み出し可能なデバイス、たとえば外付けで接続するデジタル温度センサ
だと、一番外側の現実世界に直接接続する界面(インターフェイス)では、クロックによるタイミングなどというものは無効になってしまうのです。ですから、そこでは「連続的に変化する数値を、離散的な値へ変換する」ことをクロックによるタイミングの助けなしにしなければならなくなります....値をいつどんなタイミングで読んでもいいのならば、最小変化幅が 1bit しかありえない、擬似連続な離散コードであるグレイコードを使うメリットが生まれるのですね。
というわけで、
ビットパターンを見て、それが何を示すのか?
と言われても、それが数値である、とわかっている場合でさえ、何の値かは本質的には判らないのです.....すべては約束事の世界なのだから、「規約」判らなければ、何一つ理解できない世界がコンピュータ(というか、情報というもの)なのですね.....
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.13 23:59
宛先のない手紙をあなたに
2009.02.12
って何か歌のタイトルみたいですが.....(苦笑) 仕事で「あれ?」となったメールの話です。
Webアプリ上でアクションがあって、メールを送ります。単にアクションをした人だけではなくて、それに関連する人にいろいろと送ります。ですから、
- To:
- アクションをした人
- Cc:
- 関連する人
という感じで使い分けるのがいいでしょう。でここで、
- 1. To 送信者のメールアドレスが登録されてない...
- 2. To 送信者がメールを受け取らないWebアプリ設定になってる!
- 3. (多言語化対応:)To 送信者と Cc 送信者の使用ロケールが違うのでそれぞれ使うテンプレートが別になるので、別メールで送る...
というケースが起こりえますね。でこのとき、
Cc: しかないメールって届くんだっけ?
と少し謎になりました...あるいは、
Bcc: しかないメールってどう?
という謎ですよね。まあこれ実際には送ってみればOKです。
(やってみる)
うん、届くみたいですね。けど一般にはどうなの???
この問題についてバッチリの解説ページを見つけました。→「メールヘッダにないアドレスになぜ届く?」 要するに、メールヘッダのメールアドレスは、MUA/MTA が SMTP で会話するときの単なる手がかりに過ぎないわけです。そこで「SMTP 的に配送すべきメールアドレス」(エンベロープアドレス)がきっちり決まる(ヘッダを無視してでも、とにかくエンベロープアドレスが正しく指定される)のならば、SMTP サーバはメールを受け取ってしまうのです....まあ、ここらへん実はスパムの常套手段といえば、そのとおりですね。
ですから、受け取ったメールの To: Cc: ヘッダは、「メール送信者が送った内容」(原因)というよりも、「配送された結果」と呼ぶのが適切、ということになります。心配する必要はぜんぜんないんですね...
(けど Bcc だけで指定したら、勝手に To: を補われました...あまり気分的にはよくないですね)
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.12 17:23
プログラミング文章読本~インターフェイスの「読みやすさ」
2009.02.11
仕事で出くわした他人のソースから。
private void sub( MyObj obj, int a, String b ) {
SomeClass sc = new SomeClass();
sc.setA( obj, 8 );
sc.setB( obj, a );
sc.setC( obj, b );
}
実はですね、このコード見たとき、私
あれ??何をこのコードはやっているんだろう???
と、処理の意味が少しも理解できなかったのですね。だって、
- 1. setter ではインスタンス sc に対する副作用として、「sc のプロパティに値がセットされる」はずだ。
- 2. setter の引数である obj は、実質 final であって、SomeClass#setA() などの後も、変更がないはずだ。
- 3. だから、この sub() を呼ぶ前と、呼ぶ後で、計算上の「状態」は実質的に何も変わっていないはずだ...(変わったインスタンス sc は単に捨てられている)
と「インターフェイスから」推論しちゃったわけです。
勿論、このコードについては私の推論が誤ってます: SomeClass#setA() などは、標準的なセッタの前提に従っておらず、引数を加工しちゃう副作用を持ちます。つまり、このコードの書き方は、
誤解を招く、非常に判りづらいコード
なのですね。じゃあ、何が悪いんでしょう?
それはですね、副作用をコードとして明示する、という観点を大きく欠いている、という点なのです。たとえば、こういうコードだったら、何も混乱しません。
private MyObj sub( MyObj obj, int a, String b ) {
SomeClass sc = new SomeClass();
obj = sc.buildA( obj, 8 );
obj = sc.buildB( obj, a );
obj = sc.buildC( obj, b );
return obj;
}
こっちのコードでは、引数に渡したのと同じ変数で、sc.buildA() などの戻り値を受けています。ですから、引数と戻り値で何か状態が変わっている、ということがコードに明示されているわけです。まあ勿論 setter じゃないのに「値がセットされるから setA()」なんてネーミングはやめましょうね。
その考え方でいけば、この sub() というメソッドも、同様に呼び元から見た場合、副作用があるメソッドです。ですから、ちゃんと引数として渡された obj を返す戻り値ありのメソッドに変更されています。
このように「副作用を明示するインターフェイスを作ること」という原則は、非常に重要なものと私は考えています。要するに標準的なセッタでは、
引数には何も副作用がないから、void を返すのだ
と逆に捉えなおしてもいいくらいではないか?などと思います。また、
今までは引数に値を直接セットしても良かったけども、それがまずくなって、コピーしたものをもらえるようにしたい...
と前提が変わったとしてもインターフェイスを何も直さなくてもOKですよね! 実際戻り値を捨てても動作は変わらないのですが、戻り値をあえて受けることで、メソッドの実装詳細(戻り値は引数と同じインスタンスか違うか?)を抽象化できることに結果としてなるわけです...
また、多分こういうケースでは、buildA() によって、SomeClass のインスタンス sc 自体は、何も影響を受けていないことがほとんどでは?とも思われます。つまり、これは
private MyObj sub( MyObj obj, int a, String b ) {
obj = SomeClass.buildA( obj, 8 );
obj = SomeClass.buildB( obj, a );
obj = SomeClass.buildC( obj, b );
return obj;
}
として良いケースが多いでしょう。インスタンスへの副作用がなくても、継承上書きの都合で、インスタンスメソッドであって欲しいこともあるでしょうが、こういうケースでも
public MyObj buildA( MyObj obj, int n ) {
return SomeClass.buildA(obj, n);
}
とstatic メソッドを覆ってやるくらいのことをしてもいいでしょうね....
つまりですね、
まったく同じように動くコードであっても、ちょっとした書き方の違いで、メンテのしやすさ・判りやすさが極端に変わる....
わけで、現実問題として今は
どう動くかコンピュータに伝えるコストよりも、同僚に「どう動くか」伝えるコストの方がずっと決定的
な時代なのです。ですから「読みやすいインターフェイス」を心がけることは重要ですよ!
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.11 16:53
高品位ボーカロイド、存在価値は?
2009.02.08
タイトルはその昔の戸川純の歌のパロです(そういう世代なんで)。
ちょっと使うアテがあって、ボーカロイドを買わなきゃ...ということになりそうです。とりあえずスペックとして
英語(というか、オペラの歌)が歌える
というのが縛りとしてあるので、商品が限られます。ついこの間出たばかりの「巡音ルカ」のウリは「バイリンガル」なのでハマるといえば、ハマるんですが、オペラの歌...というと、実は「PRIMA」というやはり VOCALOID2 の製品(英ZERO-G)があって、この歌凄くいいです.....→デモ
で悩んでしまったんですね。しかし、このデモは一説では
デモデモ詐欺(ジョークです):デモだから、「PRIMA」がベストパフォーマンスのできる音域・チューニングで作られているから、良くて当然だけど、このレベルで作れるかというと難しい....
という話もあるんです。私、困ってしまって、
まあ今までボーカロイドは使ったことがないので、とりあえず例のベストセラー初音ミクの体験版付きムックで、試してみよう...
というのが昨日今日の話です。で今更かもしれませんが体験版インストールでやってみました....
使用感はDTM経験があればそうそう悩まずに使えるレベルですね。SONAR との連携は体験版は ReWire ベースしかできなくて、しかもネタの伴奏が
テンポをこれでもか!というくらいに「盗ま」なくちゃいけないもの...
だったために、どうしてもズレが出ます...VSTi で使う方が良さそうですが、体験版はデータ保存ができないので、実質上これができないんです。ふう、それでも雰囲気はつかめます。
私はアイドル萌えをまったく感じない人なので、初音ミクのああいう売り方、実は苦手だったりします....そういう点では「PRIMA」の落ち着きが好きですが、でも意外に初音ミクはケロケロした声がいい感じです。まあリアルなボイスとは言いがたいですが、それでもちょっとした違和感をキーにした使い道がありそうです....
更に悩みが深まった?かも。
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.08 20:23
私は、「直打ち」が気になる...
2009.02.07
この話題は、現状ではイントラネットで使うような、ログインして使うタイプの「複雑な Web アプリ」の開発者の悪夢なんです。うん、
Web アプリで、自分が表示可能なURLを持った一覧リストが表示されていて、そこからリンクをクリックして「自分の情報」を見る
という流れの処理で、
じゃあ、「自分の情報」を表示するURLではなくて、本来自分が表示できないはずの他人の情報のURLを推測構築し、手で直にアドレスバーに打って、表示.....できちゃう!
という問題の対策、いわゆる「直打ち対策」のことです。とはいえここでは、本当に「手でアドレスバーに入力して...」というものだけではなくて、
送られてきたHTMLの内容をチェックして、「何を送ればいいか」が理解できる状態で、しかもセッションIDなども正しく使うことができて、POSTメソッドによるリクエストをでっちあげることができる
という「シロートじゃないハック」ができる一番広い状態の話でいきましょう。まあ、イントラネット用Webアプリの場合は、
そんなこと言ったって、ヘンにハックして他人の情報を覗いていた不良社員はそのうちクビになる
という現実問題(苦笑)もあるわけです。また、ある程度は、
画面ごとに付与された、「管理者だけ表示可能」というような「ロールベースの画面表示特権」
をうまくセットすることで、防御できることもあります...が、
同じロールのグループに属する他人だと?
やはり問題が起きてしまいます.....あるいは Struts の TransactionToken のように「遷移が正しいか?」をチェックする仕組みもありますが、これ「遷移が正しいか」しか判らない(アドレスバーに手で入れる、という狭い意味での「直打ち」は判るけども...やろうと思えば「模倣」はできちゃいます)ので、この話の解決とは少し違うんです(変更されるはずのないIDの値のハッシュとかからトークン値を生成して、「このIDは選択可能なものとして送ってない」ことが検出できないとダメ)。
ブラウザをはじめとする、ユーザエージェントが送ってくるデータなどというものは、すべて捏造可能で何一つ信用できない
という Web アプリの宿命みたいなものが本質的な原因となるわけです。ですから、面倒とは思っても、イチイチの実際の他人に見られたらイヤな情報表示画面で、
ホントにこのアクセスに対して、中身を開示していいですか???
というチェックを確実に入れないと、本質的な解決にならないわけです。
そうは言っても、現実の開発スケジュールにそういう余裕があるかどうかは別ですし、QAがそういうチェックをしっかりしてくれるかどうか、も別です。
一度ログインしちゃったら、あとは無法地帯
な Web アプリって、 意外に多いように推測されます....私はできるだけそういう事態にならないように警戒心を持って書いてますけどね....
いろいろなフレームワークで、POSTメソッドとGETメソッドを無差別に扱える、という開発上便利な前提って、実はアドレスバーに表示されてはまずいIDが出てしまう原因のひとつのように思います。GET メソッドによる アクセス URL 構築は、つけ込まれる隙が出来がちでもあるので、出来る限り避けた方が無難、なんですけどね(便利なんでついつい...って多いですね)。.
そういえば、1つの店舗に1台しかパソコンがなくて、接客で Web アプリのページを開いたままパソコンの前を離れることがあって....で、ログインされたアカウントさえも、ページ表示をするためには信用できない!という強烈なケースさえあるようです.... ふう。
投稿者 : 杉浦 こずえ | 投稿日時 : 2009.02.07 10:03


