ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)

2007年~2011年ごろまで はてなダイアリー に書いてた記事を引っ越してきました。

「"適応障害"という診断をもらった。」の続き。

今の仕事・・・といっても先週から休んでいるので、9/1までやっていた仕事は、今年の4月から始まった。正確には4/7から。
弊社側の構成は、C言語3人にRuby1人。で、Rubyの1人が自分。
料金収納システムなのだけれど、外部システムとUNIXソケットで収納情報をやりとりするコア部分がC言語3人。一部のユーザー向けにWeb画面から収納データを一覧検索できるようになっていて、そのサブ部分が自分。コアとWeb側はサーバ筐体も別で、コア側の常駐プロセスが、コア側のOracleから、サブ側のMySQLにデータをコピーしてくれる。
自分が担当したのは、MySQLから検索してWeb画面で表示するRuby on Railsアプリ。

以降、思いつくままに書くので長くなるしまとまらないので読みたい人だけ。


お金の情報を取り扱うそこのお客としては、従来より有償サポートのある製品を使うという方針だったが、最近は徐々にOSSも使うようになってきたらしい。今回のWebサブシステムとしては母体数が1千万件を越す検索中心のシステムをMySQLRuby on Railsで仕上げようと言うことでそれなりにチャレンジングだったらしい。

っつーかその前に、客側の開発担当で「Ruby on Rails研修受けました」という人が二人いたのだが、期間はわずか3日間。
MySQLについては客側は部門としては使用経験があるが、今回の客側の開発チームとして(そして実際のプログラミングも担当する人間は)使用経験無し。・・・いや、実際には今回のプロジェクトの承認を受けるに辺り、事前に簡単なモックアップを作り「イケル」というのを確認しているようだったので、経験としてはゼロではないようだが・・・。

しかも俺、PHP専門なんですけど。

まぁPerlRubyは囓っているし、その前の仕事ではsymfonyベンチマークを取ったりしているのでRails系のフレームワークについては不安は感じなかった。まぁ3ヶ月の間にsymfony, CakePHP, Akelosととっかえひっかえで同じ動きをするアプリを作っているので、その辺は本見れば分かるだろうレベル。
もともとその辺りの技術をお客様側の開発担当(若手)にも教えて欲しい、共有したい・・・というのがお客様側から聞かされていたので、役に立てるのであれば重畳。と思っていた。

ところがさ、お客側の3日間のRuby研修受けた若手開発者(Aさんとしておく)なのだけど、現行システムの維持の仕事が降りかかってきてしまって・・・本来は自分とAさんで半分こくらいの担当で余裕持ってするはずだったのが、自分が7-8割、Aさんが残りという形になってしまった。弊社側のC言語チームは既に一杯一杯でこっちに回せる余裕もない。
まぁ検索オンリーということもあり、それでもどうにかこなせる分量だったのは幸いだったけど・・・。

外部設計も、内部設計も、開発も、単体試験も、結合テストも、ほぼ自分が7-8割でAさんが残り。

それでもさ、自分の好き勝手に作れれば気は晴れたのかも知れないけど・・・。

「現行システムと見た目まったく変わらないようにして下さい。」

というのがお客の要望。お客の裏に別会社のエンドユーザがいるわけです。それも日本中に散らばっている。なので見た目や使い勝手、検索条件の組み合わせを変えるのは今回のプロジェクトでは予算の問題もあり不可能。もともとお客様の内部的なシステムリプレースというプロジェクトなので、別会社のエンドユーザに対しては見た目を変えられない。

その現行システムなんだけど、1999年-2000年にかけて作られたもので、AppleWebObjectsを使っていた。Java+Oracle
まず、DBのテーブル仕様書が商用環境と違う。さらに商用環境をコピーしてきた開発環境(2000年当時のCompaqマシン)とも違う。
WebObjectsの場合はGUIでDBからの検索条件を組み上げる為、厳密なSQLの仕様書が無い。このため、最も重要な検索条件についてWebObjectsGUIが生成した設定ファイルを読み解いてリバースしなければならなかった。
ついでに言えば、AさんはJavaが読めない。自分は読める。よって現行システムのソースコードの調査は自分一人でやるしかなかった。
テーブルの仕様書で意味不明のフラグが出てきても、その意味を覚えている人が居ない。
DBから取得はするけど、HTMLに表示していないカラムがある。何故かも覚えている人が居ない。
HTML上は列名があるのに、そもそも値の表示すら行っていない列名がある。同上。
更に言えば、商用のWebObjectsサーバの環境設定というかWebサーバの設定も残っていなかった。その影響で、外部設計が終わった後になって「実は商用環境にこんなindex.htmlがあったんですよー。」とかAさんから言われた。

まぁここら辺は直接的な問題じゃないと思う。どこでも良くある話だし、調べれば済む話だ。

他は・・・脱力したときの話としては、想定母体数で動作確認したモックアップの話がある。
プロジェクトの承認を受ける時に、Aさんが苦労して想定母体数を作り、実際とほぼ同様のテーブルを作成して主キー(1カラム)で検索するだけのRoRモックアップを作成していた。scaffoldを使っていた。

が、重要な要件がそのモックアップには抜け落ちていた。

現行システムでは検索結果のレコードを全部セッションに入れて、セッションデータの中でページングしていた。つまり、「検索した時点での」レコードで「前へ」「次へ」が行われないとならない。
これはRoRがデフォルトで想定しているページング動作とは異なる。RoRsymfonyがデフォルトで生成するページングは、その都度SELECTし、LIMIT/OFFSETで表示位置を調整する仕掛けになっている。
Aさんはそのことを知らずに、scaffoldのページングを現行システムと同じくセッションデータの中でページングしているものと思っていたらしい。

さらにこの検索システムでは検索のヒット件数が1,000件とかがざらにあるのだけれど、一応上限値として1,000件を越えたらポップアップメッセージを出すようにしてはいるのだけれど。
逆に言えば1,000件のレコードがセッションに入る可能性があると言うこと。しかも機能毎に検索条件を異にしている為、6機能あるのだが各機能毎に1,000件のレコードを保持しなければならないということ。
それをセッションに入れるとどうなるか、についても懸念があった。

Javaの場合は実装にも依ると思うけど、on memoryでセッションが保持される。つまり生成したオブジェクトがリクエストを跨いでそのまま使われる。それはリクエストの処理が同じプロセスの別スレッドとして処理される性質も関係している筈。
ところがRuby/PHP/Perlの場合、あるリクエストを処理したCGIプロセスなりApacheプロセスが、同じセッションの次のリクエストも処理してくれるとは限らない。プロセス毎に分離されてしまう為、セッションデータはファイルなりDBなりmemcachedなどで永続化される。
言語毎に、内部変数を独特のバイナリデータに書き出してセッションを保存し、セッションIDに応じてまたそのバイナリデータを読み出して内部変数に変換する。そうした変換操作がつきまとってしまう。

そこでもしも数千件の連想配列をIN/OUTすると・・・ということで、実際にお客から貸与されていたThinkPad上でRoRの環境を構築し、ARとsessionストアのエッセンス部分だけを抜き出してやってみた結果、各機能毎に上限値として1,000件を目処に押さえておかないとこの変換処理がボトルネックになる事を指摘したりもした。

これも、Aさんは寝耳に水だったみたい。まぁこれもRubyとかPHPとかPerlでのセッション変数の取り扱いについて、知ってないと分からない事柄なので・・・まぁ、これはスキルを伝達できた、ということでいいかな。

ただこの件では・・・何というか、脱力感を感じた。まぁネガティブ感情を暴露してしまえば「知らずにやってたのかよ!バカが!」というのが正直あった。

あともう一つあったな・・・。REXMLの脆弱性の件。これも結局、お客様側ではなく自分の方が先に検知して、実際にローカルでattackしてみて効果を確認し、対策を打ったのだけれど。これも・・・本当なら、Aさん側で検知して欲しかった・・・。Aさんがわから、「こんな脆弱性があるってニュースサイトに出てましたけど、どうしましょう」と声をかけて欲しかった。
だってさ、今回だけじゃないんだし。
今後もセキュリティに絡んだ似たようなことはあるだろうけど、そのときも誰か外の人から言われないと対処できないのかな?
そもそもOSSが好きじゃなくて、業務命令でOSSを使う人達ってこんなものなのかな?
それならそれで割り切れるけど、なんというか「良いように使われてお仕舞い」的な感覚は。

お客が「OSSをやる」と聞いて自分が求めていたのってなんだったんだろう。