雑な k|m の生態について

その2 - 気づいたら,1週間

2002-05-05

猛暑と TA と,あとスペルミスとか

だ 5 月なのにどうしてこんなに暑いですか。本当に今年の夏はエルニーニョ現象のおかげで涼しくなるのかと問い詰めなければなりません。「男の子」って,誰やねんっ。

しかしこの暑さと TA の不調はきっと関係ないと思います。・・ええ,さっきからネットに接続しようとしても,できないのです。サブクラス化に失敗して,ヘンなところを弄ったからに違いありません。

//////// Base クラス
class Base{
public:
	virtual LRESULT handleMessage(Message *m, bool *handled){
		return 0;
	}
};

//////// Deriv クラス
class Deriv: public Base{
public:
	LRESULT handelMessage(Message *m, bool *handled) {
		if (m->msg == WM_LBUTTONUP) {
			return WMLButtonUp(m, handled);
		}
		return Base::handleMessage(m, handled);
	}
}

現在,VisualC++ で Borland の VCL の真似事をすることにハマっています。それで書いたのがこのようなコード。

handleMessage のスペルを間違えました。

コンパイルは通ります。(これはメッセージハンドラなんだけど)メッセージを処理したくなるまではなんとなく正常に動いているようにも見えます。しかし WM_CLOSE や WM_DESTROY などアプリケーションに関する重要なメッセージまでも処理できないため,もしも標準のウィンドウクラス(BUTTON クラスや EDIT クラスなど)のウィンドウプロシージャをサブクラス化していた場合はとっても致命的な結果に。

こういうミスを無くすため,似たような構文は通常はマクロを使って書きます。ちなみにこのテのマクロは VCL だけではなく,MFC でも似たようなトリッキーなマクロを使ってます。

//////// マクロ宣言
#define BEGIN_MESSAGE_MAP() \
	LRESULT handleMessage(Message *m, bool *handled) {

#define MAP_MESSAGE(_msg_, _method_) \
		if (m->msg == _msg_) return _method_(m, handled);

#define END_MESSAGE_MAP(_base_) \
		return _base_::handleMessage(m, handled); \
	}

//////// Base クラス
class Base{
public:
	virtual LRESULT handleMessage(Message *m, bool *handled) {
		return 0;
	}
};

//////// Der1 クラス
class Der1: public Base{
public:
	BEGIN_MESSAGE_MAP()
		MAP_MESSAGE(WM_LBUTTONUP, WMLButtonUp)
	END_MESSAGE_MAP(Base)
};

//////// Der2 クラス
class Der2: public Der1{
public:
	BEGIN_MESSAGE_MAP()
		MAP_MESSAGE(WM_LBUTTONUP, WMLButtonUp)
	END_MESSAGE_MAP(Der1)
};

これで確かに Der1 クラスとその派生クラス Der2 間での整合性は保たれました。仮にスペルミスがあっても,そもそもコンパイラが弾いてくれたりします。しかし 依然 として Base クラスとの整合性は保たれていないまま。

・・・要するにスペルミスによる事故がイヤなだけなので,無理やりマクロを適用することもできますわな。

class Base{
public:
	virtual BEGIN_MESSAGE_MAP()
		return 0;
	}
};

あっ,汚くなるかと思ったけど,そんなに害悪じゃないっすね。これでいこうかな。

午後 3 時現在の気温: 26 度

[ できないのです ]
皆さんがコレをご覧になっているという事は,私は無事にネットに接続できて,サイトにアップロードできたという事です。あーよかった。
[ 26度 ]
ええっ・・・こんなに暑いのに・・・。オンボロアパートの遮熱性の低さの凄さは異常。

2002-05-04

謂れ無き迫害

の「2ちゃんねる」では,Netscape を完膚なきまで叩きまくる鼻息荒い若人が大勢タムロしています。

各ブラウザのシェアはこんな感じ(k|m調べ)。

潔しっ。

このうち,Mozilla/5.0 を名乗るユーザーエージェントは 1.3%。そして皆さんが目の敵にしている Netscape4 は 1.2%。そしてその他が 2.5%。

むむ,これではいわゆる「Web ソリューション」なんてモンを実行したいクライアントがいわゆる「Web デザイナー」さんに

Netscape4 でも IE と同じに見えるようにデザインしてねっ

などと頭の悪そうな事をヌかす理由が全く不透明になりました。悪徳 SE の口車に乗って数千万円をドブに捨てるようなクライアントでも,ほんの 1% ちょっとのブラウザを捨てきれずにいるのはなぜ? しかも「その他」に分類された Lynx や w3m を相手にしないのはなぜ? ・・・色んな意味でご愁傷様なのでしょうか。

ともかく,このおかげでデザイナーさんたちはいい迷惑。例えば IE では CSS の overflow-x や overflow-y プロパティによって縦スクロールバーと横スクロールバーの表示を個別に自由に設定できますが,Netscape では通常の方法ではどうあがいても不可能です。しかしその日の糧を稼ぐために,瞬間的に発狂しつつ厄介な仕事に挑むデザイナーさんたち。こうして Netscape4 への不満は高まってゆくのです。クライアントへの愚痴はご法度。

Netscape4 を使っている人のほとんどはそもそも,見栄えばかりで中身の怪しい Web サービスなぞ利用したくないと考えているのは,いつまで内緒にしておくべき?

顔を真っ赤にしてプルプルしたい度:933

[ 通常の方法では ]
強烈に複雑で危険な JavaScript を使うことで対処が可能かと。
[ 中身の怪しい ]
そういえば,見栄えと中身のレベルは二次相関っぽいんスけど。あとで研究してみようかな。

2002-05-03

本物のプログラマ

本物のプログラマ

今日紹介する URL は "THE REAL PROGRAMMERS STORIES" の日本語訳プラスアルファ。そう,皆さんよくご存知のアレです。しかし私は,これは決してジョークではないと信じています。

ちなみにリソース中にある,デニス・リッチーとブライアン・カーニハンがコンパイルできることを確認したというこの C コード:

for(;P("\n"),R-;P("|"))for(e=C;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);

現在のコンパイラではコンパイルできない模様。このコードが次のようなコードの断片だったとした場合,VC++5.0 では /P もしくは /E オプションをつければ「コンパイル」のみ可能でした。

void P(void *a){
	return;
}

int main(){
#define R i-
#define e p-
	int i=0, p=0, C=0;
	char *u = "";

	/* これが件のコード */
	for(;P("\n"),R-; P("|"))
		for(e=C; e-; P("_" + (*u++ / 8) % 2))
			P("| " + (*u / 4) % 2);

	return 0;
}

無論ビルドできません。gcc でも見事跳ね返されます。どないやねんね。gehehe...

疲労度:47

2002-05-02

まだまだ Yahoo > Google !?

検索サイトのシェア争いで・・・

「まだ Google って Yahoo を越えてなかったの!?」という意味で驚愕してしまいました。やはり老舗は強いですか。

ちょっと追記:CNET のページが消えてますね。。。テキストで保存はしてあるけど,どうするべきか。。。

信用を無くしたプログラマ

DB の取り扱いで面倒なのが,プログラム内で動的にクエリを生成すること。軽微な仕様変更には耐えられるよう,次のように書いていました。

# DB のフィールド名を順番に
my @gFields = qw(
    CHABC   CHDIS   CHUKI   CHTUE
    CHDKR   CHHIW   CHASE   CHPOW
);

# フィールドの型を順番に
my @gFieldTypes = qw(
    int    char     int     int
    date   date     date    char
);

# フィールド名と型のペア .. 自動生成される
my %gFieldAndType = ();
for (0..@gFields-1) {
	$gFieldAndType{$_} = $gFieldTypes[$_];
}

# (中略)

# UPDATE のための sql を生成
$query = join( ',',
	map {
		# int 型ならば数値であることを保証する
		if ($gFieldAndType{$_} eq 'int') {
			"$_=". ($value{$_} - 0);
		}

		# date 型ならば
		#   データがあればクオートする
		#   なければ NULL
		elsif ($gFiledAndType{$_} eq 'date') {
			"$_=". ($value{$_} ? "'$value{$_}'" : 'NULL');
		}

		# char 型ならばクオートする
		else {
			"$_='$value{$_}'";
		}
	} @gFields
); # end of join()

map 関数は,私たちのコードをスパゲティに変えてしまうのにしばしば役に立ちます。でも便利なのでつい・・・。

このコードはつまるところ,$query"CHABC=0, CHDIS='hoge', CHUKI=1, CHTUE=2, CHDKR=NULL, CHHIW='2002-05-02', CHASE=NULL, CHPOW='foo'" などのような文字列を生成します。int 型ならば必ず数値であることを保証するために 0 を引き,date 型ならばきちんとした値か NULL を,char 型ならば必ずクオートします。中身は %value に依存します。

この例ではフィールドがたった 8 個だからアレだけど,実務では 50〜60 個ってのがザラ,っていうのは皆さんの方がよくご存知のはず。それを考えれば,このコードは適度に短くて明快です。

[ コードをスパゲティに ]
しかしそのスパゲティは実際に食べられないので,何の役にも立ちません。

過ちは突然,目の前をふさいでアレだ

↑のコードとはちょっと離れますが,私は非常に情けない凡ミスを犯してしまいました。本当ならこう書きたかったのに

my $r;
$r = $detabase->exec($query)->getResult();
if ($r != SUCCEED) {
	print "error";
}

こう書いちゃいました。

my $r;
$detabase->exec($query)->getResult();
if ($r != SUCCEED) {
	print "error";
}

$database はデータベースオブジェクト,exec() は指定したクエリを実行するメソッド,getResult() で結果を取り出せます。しかし,$r に戻り値を代入するのを忘れてしまいました。何度クエリを実行しても値が SUCCEED になるワケがありません。

数奇な運命により,なぜかこのまま提出されたソースコード。そして相手先からメール。

DB に値を登録するとエラーが起こるようです。DB は外部から操作が加わると不具合が起こる可能性がうんたらかんたら。UPDATE のクエリを生成する時はフィールド名を明示するようにソースを修正してください。

相手はきっと奇妙な joinmap を見て,そこがエラーの源だと思ったに違いありません。でも違うんです。本当はその先にある,情けない凡ミスなんです。違うんです・・・。

私,信用を無くしましたか。

そして現在,私は大量の "CHxxx = $value{'CHxxx'}" を書かなければならない日々を送っていますとさ。めでたしめでたし・・・。

追記 〜 まあ実際には違ったわけですが

実際にはそのミスがみつかったワケではなくて,私が DB の常識を知らなかっただけでした。2002-06-20 にて解決っ。

2002-05-01

Netscape 6 では動作しません

たもや「2ちゃんねる」からのネタですが,私は生粋のアレなのでご了承ください。次の引用はソフトウェア板「Mozillaスレッド M10」の 221 の名無しさんがまとめた各社 Web サービスの注意書きです。

UFJ銀行
Netscape 6ではご利用いただけません。

エムタウン
Netscape(R)6については動作上の制限があります。

シティダイレクト
Netscape 6は、ご利用できません。

ソニー銀行
Netscape 6 の動作保証はいたしかねますのでご了承ください。

東京三菱ダイレクト
Netscape6以上ではご利用いただけませんので、ご注意ください。

富士銀行エムタウン支店
いずれもNetscape6およびInternet Explorer6.0(Beta)はご利用いただけません。

三井住友銀行One'sダイレクト
Netscape 6.0β及び6.0はご利用になれません。

実際には(少なくとも私には)各社サイトではその記述を見つけられなかったモノもありますが,まあ往々にして各社とも Netscape6 を嫌っているのがよく分かります。

ネスケ嫌い

経験上,Netscape6 が嫌われる原因は次の通り。

シェア

気づいてみたら IE のシェアが 90% 越えてるし。この世は一体どうなっちょりますか。

軽さ

他のブラウザに比べれば,Netscape6 はお世辞にも「軽い」とは言えません。むーん・・・。

オープンソース

その根底である Mozilla は,そーゆーのが好きな有志が集まり,オープンな場においてほぼ非営利目的で開発が進められているソフトウェアです。当然,Mozlla による致命的な問題が発覚しても誰からの補償も受けられません。

厳密に,strict に

ほぼ非営利目的なわけだから,ユーザーの無茶な仕様に応える必要もありません。(こんな事はまずあり得ないけど)ユーザーの多くが「border 属性に 5 がセットされた table を 3 段ネストさせて各 tr 要素内の td 要素が 2 つの場合に限り,その中に記述された div 要素のスタイルシートの overflow を自動で発動して欲しい」と望んだ場合,Microsoft なら当然その要求に応えるでしょう。しかし Mozilla は無視をするでしょう。むしろ,無視する義務があります。じゃないと私は Mozilla を使うのをやめたくなります。

JavaScript is NOT JScript

IE の "JavaScript" って,正確には "JScript" とか言いませんでしたっけ? でも microsoft.com ドメインの中で "JavaScript" が大量に。もうどうでもいいんですか。

JavaScript も JScript もお互いに ECMA 準拠とは言っても,周辺部分や細かい部分で仕様が違えばそれは決定的な判断材料になります。今日も会社の ── 年下なんだけど ── 先輩が「Netscape4.* は img タグで onClick イベントが使えないんだ」と涙をちょちょ切らせていました。あ,死語だ。

[ ほぼ非営利目的 ]
多少は誰かからお金を貰ってると思うんだけどなあ・・・。だって,半端な作品じゃないっすよ? もはや芸術ですが何か?

ぼくらはみんな 冷めている

「e-コマース」や「ネットバンキング」や「ウェブソリューション」などとかっこいい横文字を連呼して,さも「漏れはインフォメーションをフリーにマニュピレートしてるぜー」とか言っちゃってるおいさん達をまれに見かけますが,それを実装する技術者のみんなは意外に冷めてるんですよね。

それは多分,「インターネット」の正体が何なのかを知ってるから。

ホント,こういう仕事をしているとイロイロと考えてしまうんですよ。「なぜたったこれだけのことをわざわざインターネット経由で?」「そこでなぜ Web ブラウザを使いたがりますか?」「こんな部分でこんなにコスト掛けていいんスか?」・・・いえ,こんなお仕事でお金が貰えるんで,私としてはウハウハですが。

[ インフォメーション ]
情報。
[ フリー ]
自由。
[ マニュピレート ]
謎。

2002-04-30

気づいたら,1週間

ぜかこの1週間はネタがいっぱいで,毎日更新してしまいました。私にしてはあまりにも異常な出来事です。

referer を残さないリダイレクト

今年に入ってからでしたっけ? 掲示板サービス「2ちゃんねる」に書き込まれる URL は ime.nu リダイレクトサービスを通すように処理されるようになりました。正確な Referer 情報が残らないということで賛否両論っていうか,「否」しか意見が出てないような・・・。

ただしこのリダイレクト方法は "http://ime.nu/www.foo.net/" のような Referer 情報を残します。単純に HTML の A 要素を用いているからですね。

<a href="http://ime.nu/www.some-server.net/">http://www.some-server.net/</a>

完全に Referer 情報を空にしてしまうようなリダイレクトは,HTTP で提供される機能を利用します。下のコードは HTTP レスポンスヘッダです。

HTTP/1.1 200 OK[LF]
Refresh: 0; URL=http://www.some-server.net/[LF]
[LF]

お気づきの方もいらっしゃるかと思いますが,これはつまり <meta> でよく見かけるアレと同義です。

<meta http-equiv="Refresh" content="0; URL=http://www.some-server.net/">

これにより,少なくとも InternetExplorer と Netscape(Mozilla) では Referer を空にすることができます。なお Lynx では結局 A 要素と同じ処理をされてしまうため Referer が残ってしまいました。また Amaya は Refresh に対応していないようです。

偶然にも,よく使われる IE も NN(Mozilla) も同じようにうまく Referer を消してくれるため,多くのブラウザによる閲覧を想定しない場合には使える技かもしれません。

なお,同じような HTTP の機能で Location ヘッダがありますが

HTTP/1.1 302 Found[LF]
Location: http://www.some-server.net/[LF]
[LF]

これは Referer が残ってしまうようです。

[ Referer ]
正しいスペルは Referrer です。r が一つ余分に必要なんですよね。
[ Location ヘッダ ]
一般的に,例示したコードのようにステータスコード 3xx の場合に用いるようです。

追記 〜 8 ヶ月をかけたボケ

この雑記を読む人の絶対数が少ないからアレだけど,今現在 ( 2003-01-12 ) までで「おかしいな」って思った人いましたあ? ていうか日付を間違えていました。この雑記の日付は 2002-04-29 ではなくて 2002-04-30 ですね。間違いに気づくまでに,8 ヶ月を超えました。

Written by kuri|minima(tkuri@fat.coara.or.jp) - all rights reserved.(warai
このリソースの位置情報は http://www.coara.or.jp/%7etkuri/D/002.htm で安定しています。coara 最強伝説。