日々のつぶやき(99/12/1〜)

1999/12/30

口で息を吸うと喉が痛いから、鼻で息をしたいのに、鼻水だらだら状態で口でしか息が出来ない。頭にくるなぁ。今日はわき腹の痛みは薬を飲まなくてもあまり痛くはなかった。おかげで思いっきり鼻をかんだりくしゃみをすることができる。そうか、簡単なことが当たり前にできるってのは、実はとてつもなく幸せなんだなと感じた。

1999/12/28

別に前の日に大酒を飲んだわけでもないのに、朝から頭痛で目が覚める。身体がひどくだるい。どうやら本格的に風邪をひいたみたいだなぁ。まだわき腹の方は痛み止めの薬の効き目が切れるとかなり痛い。

1999/12/27

喉がいたい。咳をしたい。が、咳をすると腹筋がしまってわき腹に痛みが走る。堪え切れなくなって痛み止めの薬を飲むことにした。痛み止めを飲んだらかなりわき腹の痛みが収まった。無理をせず楽な姿勢を取りながらひたすら布団の中で読書。

1999/12/26

わき腹の痛みがひどくなって、やっぱり布団から起き上がれない。自慢じゃないが、滅多にケガをしない私はこの手の痛みに格段に弱いのだ。まあ、寝てれば直るだろうが。

寝ているだけじゃさすがにつまらないんで、ツンドク状態になっていた「宇宙のランデブー」シリーズを読みはじめた。

1999/12/26

風邪ぎみで身体がだるいのと、わき腹の痛みがあってほとんど一日中寝ていた。鼻をかむのもわき腹がいたくて満足にできない。いらいらいらいら。

1999/12/25

同期のTさんの身代わりになって、「5年後の会社のあり方について」の会議に出席。10:30から延々6時間以上開始をしたので、正直疲れた。体調もよくなかったので、会議が終りしだい帰りたかったが、Mac版の詳細スケジュールを作って、Nさんと競技するという仕事が残っていたので、帰るに帰れない。

ところがこのスケジュール作成作業が泥沼にはまり込んでしまって、全然まともなスケジュールにならないので、えんえん時間がかかる。あきれた(?)Nさんは「今日やっておいてくれれば自宅で見るから」と帰ってしまう。かなり遅くまでかかってなんとかつじつまのあいそうなスケジュールになったので、Nさんのメールボックスに送ってから帰宅。明日からはお休みだぁ。(けど、どうせ自宅で何かごそごそお仕事やるんだろうな。)

1999/12/24

二日酔いでグロッキー状態。今日年休を取っておいてよかった。(^_^;

1999/12/23

chomboさんの家で飲んだ。数日前に原因不明の理由で痛めた(どこかにぶつけたらしい)わき腹が痛くなってきた。

1999/12/16

やっとまともにリビジョンとか、ファイルの共有に関して管理が出来る体制になった。ただし、Visual Source Safe(vss)6.0で直接やっては駄目で、一旦Vss5.0(=VC5.0)ベースでソース管理プロジェクトを作ってから、 VSS6.0へコンバートするようにしないと、うまくプロジェクトファイルがリビジョン管理付きで移行できない。このあたりMicrosoftがどんなことを考えているのかよく分からないので何ともいえないが。

Windows版。文字認識結果をRTFに出力するルーチンのチューンをするために、去年書いたコードを読み直してみる。読み直してみると、まず「心の傷」となっている所を見つける。ここは去年、「なんでこんな風に書くんだぁ?」と絶叫して、手をつけるのを止めたところだ。が、時が経てば少しは気持ちも変わるのか、この部分を手をつけてみる気になった。最初読んだ時に、全ての分岐がifとelseの 完全3段ネストだったので…、とてもあの時には読み伏せる気になれなかったのね。簡略コードで書くとこんな感じ。


if (...) {
} else if (...) {
	if (...) {
		if (...) {
			...
		} else {
			...
		}
	} else {
		if (...) {
			...
		} else {
			...
		}
	}
} else {
	if (...) {
		if (...) {
			...
		} else {
			...
		}
	} else {
		if (...) {
			...
		} else {
			...
		}
	}
}
こんなコード、はっきりいってパズルです。このコードを最初に見た時には「これは手に負えないな」と思いましたが、結構この部分がチューニングのアルゴリズムに関係しているんで、意味が分からないといけない。で、注意深く解析してみると、2 x 3 のマトリックスに分類できることが分かる。

1999/12/13〜15

Windowsバージョンの新製品に関るにあたって、いろいろ事前調査したり、前任者のSさん(前任者といっても、彼は私の仕事を引き継いだんだから、この場合は返り咲きというのが正しいかも)と、共同で作業をするために必要なソースファイルの一意性を保証するためのルールとか、そのルールを適用するための作業に追われる。

Visual Source Safe 6.0のソース保守のポリシーは、Ver5.0の頃に比べて、押しつけがましいなぁと感じる事しきり。1つのファイルを各々のプロジェクトで共有する時の柔軟性はVer.5の時のほうが遥かに勝っていると思う。あんなファイル管理に関する押しつけがましいポリシーは止めてほしいよなぁ。

1999/12/10(Fri)

やらなくちゃいけない作業というのは、大雑把には頭に入っていたんだけど、「本当に何を終らせないと機能が全部揃ったとは言えないか?」というのを列挙してみる。で、やってみて、詳細なスケジュールを作るにはやらざるをえないけど、やんなきゃ良かったと思った。詳細な内部仕様が固まっていないので大雑把になっている項目がいくつか。私の仕事のペースだと半日とか1日とかかかりそうだな、という仕事が50件くらい。正直気が遠くなってくる。

うちの課の稼ぎ頭のWindows版のスケジュールが切羽詰まってきて、遅れに遅れているMac版の進捗と考え合わせると、仮にMac版が年度内に出なくても、私がWindows版に手を出すことが妥当だという内々でのコンセンサスが得られた。現状を少しでも冷静に考えれば、いくらなんでも無理だと分かっていたにせよ、Mac版は絶対年度内には出せなきゃ…と思っていた。ところが、とりあえず頭の中で思いつくままにやらなきゃいけない作業を列挙してみるとあの調子だから、「年度内には絶対完成させます」なんて強気なことを言えるはずもなく、ある程度Windows版の方にも関らざるをえなくなった訳だ。まぁ、結構Mac版開発でいらいらしていたのもあるから、その意味では「渡りに舟」という感じもする。

1999/12/09(Thu)

Gradius IV。今日は4面の火山でGame Over。今日はこの面でのTail Gunを使った攻略法を軸にやってみたのだが、TailGunに切り替える前にShieldを張り替えるので手一杯。 早くTailGunに切り替えなくちゃ…、と思っているうちに後ろから攻撃してきた敵のたまにぶち当たって万事休す。

Undo処理の続き。まだデバッグまでは行かないが、なんとか全体がうまくいくようにできたみたいなので安心する。方針を変えたので、最悪全部書き直しだろうなと覚悟していたが、今まで書いてきたアルゴリズムが単純だったので、単なる文字(wJisCode)を操作する時に、拡張されたメタ文字を使うように修正するだけでなんとかしのげた。ある意味、かなり無駄な処理がされるようになったが、どうせそれらは高が知れているので、とりあえず気にしないことにする。気になる遅くなるくらいだったら、最適化する方法はいくらでもあるだろうし。

マシンの時計がちょっとずれていることに気がつく。設定し直しても、リブートすると時計の設定が元に戻ってしまう。高々3分ほどのずれなので気にしなければいいんだが、一旦気になりだすとどうしても止まらない。さんざん調べたあげく、Netwareのサーバーの時間が3分ずれていて、リブートの度にそのサーバー時刻に時間が合わせられていたということが分かる。これってどこかに「サーバーとの時刻を合わせる」設定のOn/Offがあったような気がする。そう思ってさんざん探したがとうとう見つからなかった。どこかで設定したような気がするんだがなぁ。

ただし、編集関連全体を結構修正したのでコーディングだけで今日一日かかってしまった。疲れてしまってデバッグをする気になれない。後は明日以降だな。

Dream Castのバーチャロンを購入。当然ステックも買った。面白いとは思うんだけど、あの展開の速さについていけない…。(^_^;もっとも今日始めてバーチャロンをやったんだけどね。

1999/12/08(Wed)

お昼休みにやるGradius IV。今日初めてモアイ面を突破できた。といってもほとんどまぐれに近くて、火山面、モアイ面で何度か死んでいるんだけど。次の細胞エリアでは、敵の攻撃が全然予測できなくてあっさり撃沈。ふ〜む。

ようやくなんとかUndoを実装できた。全部の編集操作に対してUndoしてみた訳じゃないから、本当に動いているかは怪しいもんだが、機能がはっきりしているパーツの組み合わせでしかないから、動いていなくてもデバッグはそんなに手間がかからないはず。α前の段階では大体こんなものだろうと思う。

で、1つ1つの機能について、ざっと動作チェックをしてみる。特殊な境界条件に関しては今の段階ではテストできないのでちょっと不安な所があるが、大体動いているようだ。Undoまで出来ることを認識結果編集画面の1つのマイルストーンにしていたので、そこまで動いたというのでほっとする。

念のためWindows版と動作を比べてみる。で、重大な見落としに気がつく。Windows版では各々の文字に対する認識状態まで復元しているんだが、私は編集状態が復元できること(つまりは普通のテキストエディタレベルでのUndo)を仕様にしていたので、私のかいたコードでは各文字に対する認識状態のUndoまでは出来ないのだ。まさしくこれが「がちょ〜ん」状態というのか。小手先の修正では全然取り繕えないほどの大きな見落としだったので、呆然としてしまう。今までのコーディングをうまいアルゴリズムも見つからない。ここ数ヶ月かかってかいたコードが全部無駄になるかと思うと目の前が真っ暗になった。いや、仮に全部書き直すことに決めたとしても、一体どうやればいいのか見当がつかない。

かなり長い間苦吟したあげく、結局書き直すことに決めた。今度の方針は、今まで文字コードだけを対象にUndoすればいいと思っていた。これからは文字には認識状態という属性が付いていて、それを1つのメタ文字として、Undoする時にはそのメタ文字を復元するようにする、というものだ。その方針でコーディングしたら、これくらいの計算量が必要だなぁと概算してみると、ここ5年くらいに出たマシンだったら何とか妥協できるくらいの計算量になることが分かった。とりあえずコアになる部分だけをコーディングまでいったら、あっという間に22時(これ以降は深夜残業になるので、うちの会社では上司と組合の許可がいる)を過ぎてしまう。コアの部分が確信が持てるくらいコーディングが進まないと、22時の誤差の範囲で頑張ったけど、全部をコーディングするには至らず、帰宅。本当は今日中にUndo位は終らせたかったんだけどなぁ。

1999/12/07(Tue)

GradiusIV。あのモアイって反則だよな。壊しても復活するんだもん。全然あの面をクリアーできる気にならない。今日も「復活モアイ面」で撃沈。

範囲指定関連の関数のI/Fがちょっとまずいと思った。これまではWindows版の構造を引きずっていて、ある編集位置(キャレットの位置だと思ってくれればいい)を指定する時には決まって、


foo(DWORD dwStartLine, DWORD dwStartColumn, DWORD dwEndLine, DWORD dwEndColumn)
みたいな書き方をしていたんだが、ちょっと考えれば、

typedef struct tagEDITPOS {
	DWORD dwLine;
	DWORD dwColumn;
} EDITPOS;
という構造体を用意しておけば、先程の関数は

foo(EDITPOS StartPos, EDITPOS EndPos);
と書けば済む。(const referenceを使うほうがbettaなのは承知。)見かけ上の複雑さが減るというのはやっぱりメンテナンス上重要なので当たり前に気がついてしかるべきだった。言い訳すれば、オリジナルのWindows版がやさしいことを複雑に書きすぎて、「本当にこんな単純なI/Fに集約できるんだろうか?」とこっちが勝手に疑心暗鬼に陥ったからだと言っておこう。(^_^;この書き換えに少し時間がかかる。

次に、メニューコマンドから、cut、copy、pasteなどを行うコマンドを実装する。このエディタを設計する時に「キャレット移動や範囲選択はDocumentの状態を変えないからViewクラスの仕事」「追加や削除を受け持つのはDocクラスの仕事」と分担を決めた。また、Doc has a Window、Window has a Viewという思想で書いていたので、Object思考の観点から、直接Docクラスと直接Viewクラスとメッセージ交換させるわけにはいかないだろうと思っていたので、DocクラスメンバーとViewクラスメンバーを繋ぐWindowクラスメンバーを実装する。もっともWindowクラスのメンバーほとんどが単にViewクラスメンバーに仕事を押しつけるだけなんだけどね。(^_^;

キャレット関連の情報をDocクラスに移動すればそんな事はしなくていいんだけど、キャレットが左右に動いてもドキュメントには変更がないから、それDocクラスのをconstクラスメンバーに入れられないというのは抵抗がある。「普通」はどうやっているんだろう?やっぱりキャレット位置もドキュメントの一部だとするのかなぁ。

範囲選択がらみのコーディングがある程度終わったので次はUndo関連の処理。今回のUndoの基本的アルゴリズムは「1つ前にやった編集操作を憶えておいて、Undoされた時にはその逆をやる」という単純かつ明確な方針。(^_^;PowerPlantでUndoクラスがあるらしいし、それを使えばうまくいくかもしれないが、うまく行かないかもしれない。大体ドキュメントが全然ないんだから、どう使えばいいか分かんないし。(探せばサンプルプログラムはあるかもしれないけど)今回はとりあえず思いついた方針でいこうと思う。この単純な方針だったのだが、「1つ前にやったのはどんな動作だったのか?」をちゃんと「憶えておく」というのがちょっとした作業になってしまう。例えばPaste作業1つをみても、「範囲選択をしている時にはClipBoard内容とのReplaceで、範囲選択をしていない場合は単なる追加」と枝分かれしてしまうのだ。そもそもアルゴリズムが悪いんかもしれないが。とりあえずUndoに関する情報をちゃんと集められるようなコードを、今まで書いたプログラムに追加して、対応する関数(ただし中身はほとんど空っぽ)を作ったところで今日は終わり。

スケジュールが気になるので、もう一度残っている作業を列挙してみる。数えてみたら60項目以上あった。この中にはとても1weekでは終らないような大雑把なまとめ方をしたものもいくつかある。(まれに10分くらいで出来そうなのもあるが)仮にこれらを1日1つこなしたとして、全部のコーディングが終るのが(休日全部返上で働いて)2ヶ月後。まだ気がついていない項目も結構あるだろう。で、それからdebug地獄はそれからである…。きゅ〜〜〜〜〜〜。

1999/12/06(Mon)

範囲指定した後の、Cut & Paste処理のコーディング。とはいっても昨日までで大体の下請け関数は動いていることが分かったので、クリップボードとの連携さえうまくやればいい。

Macのクリップボード関連API(といっても基本的に4つしかないんだけど)を、使うのは初めてだったので、ざっとコーディングしてみて、そのAPIがちゃんと思ったようなAPIかステップ実行してみることにした。

ところが、クリップボードの内容を取得する関数をGetScrap()をcallするとエラーになって返ってきてしまう。


	//hDataは領域が足りない場合に自動的に大きくなるとドキュメントに書いてあった
	Handle hData = NewHandle(1);
	long lDataSize = GetScrap(hData, 'TEXT', &lOffset);	

エラーの内容を見ると「メモリが足りない」。これはドキュメントが間違っていたんだな、と思い直して次のコードを試してみる。


	//これでクリップボードに入っているデータの大きさが分かる
	long lDataSize = GetScrap(nil, 'TEXT', &lOffset);	
	Handle hData = NewHandle(lData + 1);
	long lDataSize = GetScrap(hData, 'TEXT', &lOffset);
これで試してみたんだけど、やっぱり駄目。それもNewHandle()とか、2回目のGetScrap()でエラーが起きるならまだしも、一回目のGetScrap()の呼び出しで「メモリが足らない」とエラーが出る。アプリケーションを全部終了させて、CodeWarriorだけを起動してやってみても同じ結果。訳が分からない。大体メモリが足りないとかいってもクリップボードに入っているのはせいぜい10バイト程度のデータだ。これでメモリが足らないなんてことはあり得ないじゃないか。

これは何かGetScrap()を呼び出す前に何かおまじないみたいなことが必要らしいと思って、Inside Macintoshやら手元の参考書をひっくり返してみたが、そんなおまじないらしき事は全然書いていない。調べ方が悪いんだろうと思って、再びInside Macintoshに書いてあるサンプルプログラムを読んだりしたのだが、全然手がかりがつかめない。

手元の資料で手がかりがつかめないなら、思いつく解決方法をどんどん試してみるしかない。書いては試し、失敗してやりなおしという作業が何回も続く。まるで賽の河原の石を積んでいるような気分。これが自分の能力の限界だと思うとくやしくて泣けてくる。

何回書き直したか分からないが、たまたまある時にうまくいった。「やった〜!」と思って同じことをもう一度試してみたら今度は駄目。ちょっと冷静になって、「前にやったことと今やったことの差は何か?」と考える。そういえばうまくいった時にはステップ実行するつもりが、間違って単なる実行コマンドをやってしまったんだっけ。まさかと思いつつ、該当コードをステップ実行させて失敗することを確かめ、今度は失敗する直前のコードにブレークポイントを張って、問題の部分が成功したらブレークするように設定してから、実行してみる。…今度は成功した。もう一度ステップ実行。今度は失敗。もう一度ブレークポイントを張り直して、実行。今度は成功。これで原因が分かった。 しかし、タイミングがシビアなAPIじゃないんだから、ステップ実行すると必ず失敗するAPIなんてのは勘弁してほしいぞ。そんなの分かる訳がないじゃないか!これだからMacintoshという奴は…ぶつぶつぶつぶつ

脱力して帰宅。

1999/12/05(Sun)

前日に決めた通り、午後から会社に行って半日分のお仕事。午前中は当然高いびき。(^_^;

範囲指定に関するデバッグをしていたのだが、もうデバッグが終ったと思っていた2〜3週間前に書いた下請け関数にバグがあって、なかなか思うようにデバッグが進まなかった。てっきりここ2日くらいで書いた下請け関数のせいだと思いこんで、まんまと騙されてしまった。「錯覚良くない、よく見るよろし」(C)升田幸三である。また、動作チェックをしなくちゃいけないパターンがとても多いので、思ったより時間がかかった。また範囲指定関連以外で、アプリケーションが異常終了することがあったので、これを修正。PowerPlantのクセみたいなものを理解していなかったためのバグだったので、どうやれば解決できるのか見通しが立つまでにかなりの時間がかかった。結局ライブラリの内部まで読まないと理解できなかったのだ。

今日もちょっといつもの帰宅時間よりは早かったが、一通りデバッグが終ったし「合わせ技1日分」くらいの時間は働いたので、さっさと帰宅。

1999/12/04(Sat)

午前中に起きられなくて、午後から出社。これじゃあ半日分しか働けないので、明日も半日分働いて、合わせ技で1日休日出勤したことにしよう。どうせ家にいても酒飲んでいるだけだし。(爆)

半日頑張って、何とか範囲指定に関するコーディングが19:30位に全部終った。で、これからデバッグをするとなったら下手をすれば今日中に帰れないかもしれない、どうせ明日も半日出社することに決めているんだから…、と思ってさっさと家に帰る。

1999/12/03(Fri)

文字の範囲指定のコーディング。Windows版の移植は完全にあきらめて、内部構造を全体のアルゴリズムが単純になるようにコーディングし直した成果が出てきて、コーディング自体はそれほど難しくない。ところが範囲指定をサポートする下請け関数(1つ1つはすごく単純)を沢山書かなきゃいけなかったり、今までコーディングしたキーイベントハンドラの数が多いので、それら1つ1つに「範囲選択している場合にどうするか」をコーディングしなくちゃいけない。後で実装するUndoのからみもあって、面倒といえば面倒。

結局今日は下請け関数を書いているだけで終ってしまった。明日は一応休みだけれど、会社に行くことにする。

1999/12/02(Thu)

今までは文字の挿入はアスキー文字だけに限っていたのだが、今度は日本語のインライン入力をサポートする部分を書きはじめる。前にTextEditのインライン対応をやったことがあったので、ある程度さくさくコーディングが進む。もっともTextEditの場合と違って未変換文字列とか確定文字列を描画するのはアプリケーションの役割になるので、そのあたりが非常に面倒臭いといえば面倒臭い。とりあえず文字列の描画は後回しにして、IMからのメッセージを受けとる部分までコーディング。で、どんなイベントが実際に来るのか試してみようとしたら…。ローマ字を1文字入れただけでハングアップしてしまう。それもIM経由で文字キーを押した途端、アプリケーションどころかOS丸ごと反応がなくなってしまう。一体どうしてだ?

さんざんコーディングを見直したが、おかしいところが分からない。仕方がないので一旦インライン入力はあきらめて、コーディングしたところをコメントアウト。後でSさんにどこがおかしいのか教えてもらおう。

インライン入力をあきらめてしまえば、日本語が入力された時にはキーボードイベントで上位バイト、下位バイトの順で文字が渡されるので、さくっとコーディングが終了。。自作の下位関数はすべて日本語が渡されても大丈夫なように書いてあったので、これまたさくっと動いた。これでやっと少しはエディタぽくなったかなぁ。

1999/12/01(Wed)

昨日までにコーディングしていた所を実際にコードに組み込んで動かしてみた。多少不具合があったが、単純なパラメータの設定し忘れだったのですぐに直った。

次に認識結果の編集WIndowのコーディング。今まではその部分を手を抜いていて、1文字削除・挿入するたびに全画面分書き直してちらついていたのだが、ここをきちんと書き直して、その部分を本当に必要な部分だけ再描画するという風に書き直す。が、いまいちいい方法、というかさまざまの編集パターンを想定した時に、本当に再描画が必要な部分がどこなのか、自分の中でうまくまとまらない。

こういう時はちょっと気分転換するに限る。Iさんから引き継いだコードに軽くいちゃもんを付けたり、Iさん、S'さんのコーディングの相談にのる。相談を受けているうちに、だんだん頭の中でアルゴリズムがはっきりしてきた。典型的な例で試してみたらちゃんと動いた。よかった、よかった。


1999/10 のぶつぶつ

2000/01 のぶつぶつ

日々のつぶやき 目次

作者(vyama_at_janis_dot_or_dot_jp)への感想・意見など。
spamよけのため、_at_や_dot_は適宜@や.に入れ替えてください。

目次ページ