TOPページへ

日記帳(2004.08)

日記Indexへ


2004/8/29()

久しぶりにPerlでスクリプトを書きました。
いわゆるcgiというやつ。
前にそれらしきものを書いたのは約2年前のことで、その後Cに手を染めたからか、昔のスクリプトを今見直すと愕然とする内容でした。

超読みにくい。

なんつっても全てグローバル変数で書かれてるから関数(Perlだとルーチンですね)毎に切り出して読むと意味がさっぱりわかりません。
怪しげな記述を読んでいるとどうにもCで書き直したくなる。実際、毎回インタプリタが動かなきゃならんPerlよりはCで実行可能ファイルを作ってしまった方がサーバの負荷も軽いんだろうし、けど今回のcgiも文字列の判定を多用することを考えるとCだとメンドクセ('A`)
言語の機能で文字列の比較ができる、正規表現が使える。もうね文字列メインで扱う以上はCで書く気なんて起きません。

しかしここのところCのことばっかり考えていたせいか、グローバル変数の多用が気にかかってしょうがない。
ので、今回はひたすら変数の局所化を行い全て引数と戻り値で渡すことにしました。

これが後々災いの種となるとは。

ルーチン数26 (メイン除く) というそこそこ立派なスクリプトが仕上がり、作成するうちにだんだんとCGI/Perlの流儀を思い出しました。
そう徐々に。
これがイカンのですなぁ。

たとえ個人用とでもきちんと仕様書を作るべきだ。
でないと首尾一貫のルールができない・・・というか・・・できませんでした。

グローバル変数の何が悪かろう、と今では思ってます。
たかだか26のルーチンで整合が取れなくなる程度の管理はすまい、それよりも引数渡しされたデータをコピー、さらにサブルーチンに引数渡ししてコピーを繰り返すオーバーヘッドをこそ気にすべきでは?と。
webサーバってのは自宅鯖や企業の自前鯖でもなければ一般的に誰かと共用ですからリソースは極力食わないべきです。
加えて、後述しますが閲覧時に動作するCGIであるならば不特定多数が閲覧するというwebの特性上、見に来た人の数だけのプロセスが多重起動するわけで、重ければその倍数だけ負荷を増やしてしまいます。
そりゃもう、負荷を気にするならインタプリタなんて使ってんじゃねぇよという気持ちはありますが、前述の通りコーディングの容易さには勝てませんですた。

Perlでは基本的に参照渡しです。
引数として渡した値は、サブルーチン内で別の変数(まぁその場合は普通ローカル変数)にコピーして使わない限りは、サブルーチン側で引数を弄ること即ち呼び出し元の変数を直接弄るってことになってしまうんです。
ま、呼び出し元の変数を一時的にローカライズして使う手段 (local宣言はPerl4から可能) は別にあるんですけど、それだってグローバルスコープの変数をコピーしてることに変わりは無いです。

なのでCの自動変数(スタックに積まれるやつ)的な感覚で用いるには my で宣言したレキシカル変数(lexical)を使います。(my宣言はPerl5から)
しかしそれすらも、ルーチンを抜けた時点で開放されるとは限らないんです。
Cの場合、ある関数の中で宣言した変数、またそれに向けたポインタがあったとして、関数を抜ける時にそのポインタを戻り値で返すなんてのは無意味ですよね。
抜けた時点でポインタの向いてる先が開放されてしまっているから。
(Undefにならずに何かが見えてしまうことが逆に厄介だと思いますが)

けどPerlで局所変数へのポインタ(リファレンスといいますが)を戻り値で戻してやると、呼び出し元からきちんと読めてしまう。
いや読めてしまうってより読める。そういうもんです。
よく理解してないんですが、参照カウンタによるガベージコレクタとかいうやつがメモリ領域を管理しているそうで、完全に参照するルーチンが無くなった時に初めて(勝手に)開放するんだとさ。
構造的にスタックじゃないんですね。
シンボルテーブルには登録されるのかされないのか、されないんでしょうけどアドレス的に似たような場所にあってそれを見せる/見せない/有効/無効を別に管理してるんでしょうね。

てかさ、ルーチン内で何か回す時のカウンタだとか、本当に一時的に取っておく値ならまぁローカル変数にしますけど、CGIで主に使うのはブラウザから渡されたリクエストの内容、これですよ。
これをいちいちサブルーチンのサブルーチンのサブルーチンに値渡しなんてしてらんなくて、じゃぁポインタ渡しするかっていうとそんな面倒なことしなくてもグローバル宣言しておけば最初から読めるじゃない。
ポインタ渡しの悪いところは結局参照元が判らなくなってデバッグが面倒になることでいちいち指定するくらいなら「皆知っていなさいよ」と宣言しておけばいいじゃない。

Perlだからグローバルで良い、という意味ではないです。
あぁぁぁぁぁそれもちょっとあるかも。。。。
まぁ俺の場合は、途中で「CGIオンPerlの流儀」と言ったのは意味があって、CGI程度の用途では変数のローカライズに大した意味は無い、という結論に達したということです。
そもそも重複して困るほどの変数を持つ意味が無いんです。

というのも、通常のローカル動作のアプリだったらですね、ユーザがボタンAを押した、これを変数に格納し、次にユーザがボタンBを押した、この時、前にユーザがAを押したかどうかは変数の値を参照すれば判りますしそれによってBを押された時の動作を分岐させることも容易です。



ことHTTP上の通信が前提となるCGIプログラミングの場合、ユーザがBを押した時点で前にAを押したかどうかなんてわかりっこないんですわ。
具体的にはbunbuntownのTOPページをユーザがロードし、その後日記のリンクをクリックする。
通信上はどうなるかというと、ブラウザがTOPページを要求し、webサーバがHTMLデータを送って終わりです。
そこでもうTCPのコネクションは切っちゃいます(※)から、その後日記のGETリクエストはwebサーバにとっては全く新しい無関係のリクエストであってどこの誰からとか関係ありません。

※・・・「切っちゃう」と言った方がすんなり受け入れ易いかな〜と思って書いてますがこれはウソで、実際にはhttp1.1では切るとは限りません。
本質は、リクエストの度に別プロセルで起動するのでCGIにとっては別の通信と同じって事です。

そりゃ、その気になればブラウザがリクエストに含めてくる環境変数のリファラを見て呼び出し元のページを知ることはできますが、それはブラウザがそう申告しているだけであってサーバ側の変数ではないです。
webサーバにとって別の呼び出しとなれば、当然CGIも別プロセスとして起動する、従って前のプロセスがいくら口を開けて待っていようとも (そんなプロセスはOSに殺されるでしょうが) 永遠に何も入力は来ません。
HTTPではセッション管理ができない、といわれるのはそういう意味です。

だから、ボタンBが押された時にサーバに送るデータの中に、「前にボタンAを押しているか」というデータを含めて送ってやらないといけないんです。
となると手続きとしてシーケンシャルに 「前にAを押してBは押さないでCを押してDを押して・・・」 などと延々冗長化させるわけにも行きませんので、自然とスクリプトは擬似ステートマシンになります。
入力に従って状態を遷移させていくわけです。
「今の状態」+「操作」を受け取って「次の状態」+「選択可能な操作」を出力する。これの繰り返しです。

先ほど前の状態を覚えていることはできない、と言いました。
従って前の状態は非表示の情報としてリクエストに含めたりするわけですが (※) サーバ側で強引に実現しようと思えばできないことはありません。
プロセスが終了する際に保持していた変数は揮発してしまいますが、だったら終了する前に揮発しないメモリに書き出せばよろしい、つまりはファイルに書き出すんですな。
もっとも激しく遅いシステムになってしまいますが。

※・・・この場合、前のボタンを押したかどうかをリクエストに含める(=HTML中に埋め込む)方式では、途中でブラウザを閉じてしまうと再開できません。
これに対処するにはcookieを毎回書き換えるという手法を採ります。
ただcookieもクライアント側に保存されるわけで(拒否されたら保存されないわけで)サーバ側で変数を持つわけではありません。

というわけでCGIプログラミングとしては、
・コピー回数を極力減らす。
・変数自体を極力減らす。(どうせ取っとけないんだから)
という前提においてグローバル変数をバリバリ使っていけばいいんじゃないかと、個人的にはそう思ってます。

もちろん、組織立って大きなシステムを組むような場合、そうでなくても他人がコードを目にする場合、さらには他人が保守しなければならない状況、要するに会社で仕事としてコーディングするならば、コーディング規約は確立するべきです。
たとえある局面で非効率であったとしても、作成→評価→保守のトータルの工数を抑える為には突出したカリカリチューンは不可です。
しかしですね、そういうルールというのは環境毎にあるはずで、個人で持っていてもしょうがないんですね。それはただのクセ。
個人で遊ぶんだったら、ハードの動作クロックにビッタリ合わせるためにアセンブラでnopを入れまくったって全く問題ないんですよ。
自分の中で移植性がどうの再利用がどうので「常にこうするべきだ」なんて普遍的なルールを決め打ちして首を締めるこたぁないと思います。

話を戻しますが、「閲覧時に動作するCGI」 という表現について。
たとえば掲示板など、世の中の多くのスクリプトは閲覧時 (クライアントが掲示板を見に来た時) にも起動し、ログファイルを読み出して(時には並べ変え)、他のリソースも埋め込んでHTMLデータを生成し、webサーバに渡します。要するに結構な仕事をします。
書き込み時にももちろん動作します。

一方で (俺の好みはこっちですが) 閲覧時には仕事をしないCGIもありえます。
というのは、−あくまでも掲示板を例に採りますが− 書き込み時に表示用のHTMLファイルを生成してしまい、閲覧時はwebサーバがそのファイルをクライアントに渡すだけ。
CGIは呼ばれません。
チャット化している某有名大手ならいざ知らず、通常の掲示板であれば (書き込みアクセス数) <<<<[超えられない壁]<<<< (閲覧のアクセス数) ですから書き込み時に多少重い動作をしてでも閲覧時の負荷を減らす方がより合理的だと思います。

ただしこの方式にも欠点が有ります。
閲覧時の内容が書き込み時に確定しているので「投稿者別にソート」とかスレッド表示、とかとか、見た目の変更を後から行うことができない事です。
やろうとするとものすごいクライアントサイドスクリプト(※)を仕込むか結局CGIを起動するかです。
ちなみにものすごいクライアントサイドスクリプトを仕込んだ場合、生成するファイルサイズもでかくなるでしょうから閲覧時の軽快な動作も損なわれるでしょう。
俺はweb上のコンテンツに見栄えを求めないので書き込み時に決め撃ちでのファイル出力を多用します。

この場合の書き込み時の負荷増についてですが、XML式にデータと表示が分離していればその問題も軽減されます。
しかしHTMLで行う限り、表示したHTMLから投稿データを読み出すことは非常に困難で、ログと表示用ファイルを別々に生成しかつ不整合が起きないようにロックしていなければなりません。
これが書き込み時の重さの原因です。

※・・・ブラウザ上で動作するスクリプト言語のこと。主にJavascript。
というのも厳密にはウソで、現在web上で 「Javascript」 と思われて常用されているのはほぼ JScript なんです。
javascriptはネスケが開発した言語ですが、仕様を公開していたのでこれをMicrosoftが丸ごとパクって作ったのがJScriptです。
挙句IE独自仕様まで追加しているため 「IEで動いたのにネスケで動かない」 コードが存在することになりました。
まさに「勝てば官軍」です。



2004/8/27(金)
職場で 「おりんぴっくのせいで寝不足で」 と言ったら 「ウソつけ!興味ないクセに」 と言われました。(-ω-)

まぁアジアカップの中国批判を引き合いに出さずとも、国際試合なんてどう取り繕っても国威発揚の場だよね?
本人達が個人の研鑚の為に臨んだとしても日の丸振って応援してりゃーね。
どうも代理戦争ってやつは熱くなれないんです(´・ω・`)

うわ、左翼っぽい?

イデオロギーの話はさておき、前回と比べるとすごい躍進ですなぁ!
女子柔道なんてもうね、始まる前はマジで 「フ〜ン」 だったから余計にびっくりしました。

スポーツ観戦好きな人にはグーで殴られそうだけど、基本的に 「テメーがテレビ越しに熱くなっても結果に影響ねぇよ(笑)」 と思って 「結果とダイジェストだけ見れればいいよ」 という人なんですが、先週は実況やってるチャネルにロックでした。



2004/8/20(金)

トラックボール半月使用時点でのインプレ。
通常のポインティングに支障が無い程度にはなれました。

ボールがでかいだけあって大きく動かす時にはゴローリと、細かいポインティングには指先でクイっと、あ、擬音で書くのは表現力が乏しい証拠だと誰かが言ってましたね。ソノトオリデス(´ω`)

良い点はさておき、気になる点だけ書いておきましょう。

スクロールリングの感触がよろしくない
マウスで言えばホイールに該当する部分で、ボールの周囲のリングを回すわけですが、これがなんかプラスチック同士を擦りながら移動している感じで違和感があります。
が、主観です。

左右同時クリックが困難
滅多にする操作ではありませんが、左右のボタンが離れている為に同時クリックが難しいのです。
新しいマウスを導入した時、必ずやるのがマインスイーパー。
これによって的確なポイントとクリックに慣れるんですが、同じくらいに同時クリックを多用するんですね。
今回は無理でした。

ボールの扱い
トラックボールというのは言わばボール式のマウスをひっくり返して使うようなものです。 カーソル操作の要となるボールを素手で操作するわけで、汚れが気になります。
これは光学式なのでそれほどデリケートではないと思うんですが。
個人的に手で触る部分が脂でぬめるのがとっても嫌いなので、無頓着な知り合いがスナック菓子を食った手で俺のマウスやキーボードに触るのは許せません。
ゲームのパッドとかね。
衛生が云々というわけじゃないす。感触が嫌なだけ。

で、まぁ会社でこんなもの置いておけば目立つのは確実なわけで、いない間に勝手にボール弄られたりしてるんだろうなぁと思う。

後は自分の指輪でボールに傷がつくんじゃないかと、それも心配です。

ところで良い点として、場所を取らない。これですYO
そりゃデカイっすよ?マウスとしては考えられんほどの大きさがあります。が、画面の端から端までカーソルを飛ばしたい時も掌で撫でるだけ。
イイ(・∀・)!!


2004/8/12(木)

「ITにまつわる15の俗説」というコンテンツがITmedia(旧ZDnet)の各サイトからリンクされていたので見てみました。

都市伝説というか、誤解や古すぎる常識を引きずった俗説をこきおろすのはいいんですが、
たとえば6番目のヤツ

「WindowsをシャットダウンせずにPCの電源を切ると大変なことになる。」

→「やってみたけど壊れなかったぞ、こんなものは都市伝説だ」

(゚Д゚)ポカーン

書き込み中のデータがあれば壊れる、システムの状態を定期的にチェックしているのなら不整合が生じる。不整合があると立ち上がらないシステムであれば起動不能に陥る、ただし最近のOSであれば直前のチェックポイントまでロールバックし得る。
それだけじゃないすか。
物理的に稼動するデバイス(HDD)などが物理的に破損するかどうかはデバイスの造りであって、それを特定せずに「30回電源を落としてみたが大丈夫だった!平気だ!」とは愚かしい限り。
実は3番目のやつもほとんど同じ事を言っている。だから実際には14の俗説でしかないですよ。

他にもある一人のパイロットが 「今まで携帯電話による機器障害には遭ったことが無い」 と証言した、だから携帯電話が航空機の機器に影響を与えるなんてウソだとか言っちゃってるわけですが (まぁそういう意見を紹介してるだけですが) 根本的に話にもならない内容ばかりでした。
一つ一つ反証しようと思ったけどそんな価値もなく日記のネタも無く。


2004/8/3(火)

今週は夏休みなのです。

娘は先月くらいから物を握ることができるようになり、お腹にかけていたタオルを両手で握って顔の上に持ってきてしまう。
見てる分にはかわいいし、タオルだから呼吸の妨げにもならないだろうからいいんだけど、うれしい半分、どんどん目が離せなく。

今日は多摩境のアカチャンホンポでベビーカーを購入。
ダンボールの箱は「いらない」と店員にお返しし、スーパーの駐車場で組み立ててすぐに大活躍。
いえぁ。


一方、俺個人の買い物はというと、トラックボールを買いましたよ。
あっ!なんですかその目は。
もうマウス中毒ではないです。実 用 本 位。

これです。
Kensingtonのトラックボールといえば、・・・Windowsユーザには無名?なのかもですがMacユーザには超有名。のはず。
というかトラックボールといえばここ。
この形にあこがれてたんですけどね。

今回俺が買ったのは光学センサですが、先代の機械式も激しくイイ!会社の主任が私物を持ち込んで使ってるんですが、非常にいいんですよ(*´д`)

ま、実はトラックボールって初めてだし、夏休み明けてから会社で慣れるまで使ってみて、それから感想を述べますわ。

もう一個は、7/13の日記で言っていた電源タップ。
これのWCH2436ですなぁ。
お店で探しても、どんなに頑張ってもWCH23**しか置いてないので、行きつけのホームセンターで取り寄せてもらいました。
ぐぐって唯一出てきたアキバのショップにもメールで問い合わせしたんですが、返事無いので。まぁ今さら来てもお断りしますが。

WCH2436
挿して捻って固定、わかりますか?

挿して
挿して

捻って
捻って固定。これが欲しかった。

裏返すとマグネットが埋め込まれています。
事務所で使う場合は便利なんですが、うちの木のデスクでは無用の長物。
どころか磁力というのはモノによっては害を成すことも多いため摘出しましょう。

挿してコジって
こんな時、やっぱり電工の構造はよくできていて適当な (ホントはマイナスドライバの方がよさげ) モノを突っ込んでコジれば

摘出!
カコっときれいに外れます。
これで完了。

ちなみにこのハサミ、俺が小学校1年生の時のお道具箱セットに入っていたヤツ。
もう切れ味なんかは全然ダメですが、ぶった切る用途なんかには使えるためいまだ現役(*´д`)b