プログラマの独り言 |
2008.02.15(火) 「受験校別志願者一覧表」について |
ある地域ではどの中学校も例外なく,受験校別に「志願者一覧表」を作る仕事がある。専用の書式を見ると,志願者の個別成績一覧のほかに,推薦・一般の区別/学科/コース/男女別に集計する欄がある。志願者が1枚の用紙の所定の人数を越える場合は複数の用紙に分けなければならない。これはかなり煩雑な作業なので,以前から自動化を望む声が多かった。 専用の特殊な設定をすれば可能である。しかし,「汎用性のある単純な作業の組み合わせで複雑な課題にスマートに対応する」というポリシーに反するのでプログラマーはいやがっていた。いやがる理由はもうひとつあって,現実的にこの資料の意義がが薄れてきているのである。 しかしこの資料作りは,地域別防災組織作りなど他の作業への応用可能なので,可能性を検討してみることにした。 その結果,次の機能やパラメータの追加により可能であることがわかった。@学校略称を"."(ドット)の左側を記述でグループ化する新しいソートの追加。A中見出しファイルに入力したから校名,科,コースの正式名を抜き出して枠に表示する指定。A第二分類の基準になる項目の指定の受け入れ。C1枚あたりの記入人数の上限の設定。D対象校を範囲として,点の右側,男女別など条件を付けた集計。E「n葉中m枚」でm>1の場合に表示を防ぐなど,「条件的非印刷」の指定。 現在プログラムを作成中で,近日中に試作版が公開できそうである。 |
2007.02.12(月) プログラム進化と生物進化の相似について |
杉システムのプログラミングは,現在でもゆるゆると進んでいる。緊急な課題に短時間に対応するために,一時しのぎの追加を行うことがある。大抵は,見苦しいコーディングになっている。そのうち機会を見て,結果的な動作は同じでも,よりエレガントな構造の内に組み込む作業を少しずつ進行させることになる。 それは,整った姿への陶酔というより,保守し易くし,また新しい発展を生み出すために必須の作業である。 最近の進化論は勉強してないので誤解かも知れないが,どうも進化は,始めは環境の変化に対応する個体の適応だったのが,世代を経て少しずつDNA自体の変化として固定されて進むらしい。つまり,DNAはそれ自体の運動が不断に続いていて,その中に個体の適応を最適化する形でフィードバックされていく。(ここで言うDNAの運動とは,細胞の部分の活動という意味ではなく,数百年以上のスパンを持つ論理的な変化を意味する)ソフトウエアの進化にも自ら最適化していく(人間の脳を利用するが)自然法則が存在するはずなので,その仕組みを研究することが,DNAの内部運動を司るアルゴリズムを見つける鍵になるのではないかと思う。 但し,このようなDNAの自己改革のアルゴリズムが解明されたとして,今度はそのアルゴリズム自体はどのようにして獲得されたのかという謎が残る。おそらく数十億年かかっているのだろう。 |
2006.05.21(日) Winnyによる情報流出を考える |
私自身のパソコンは,Winnyとは無縁である。そもそも有料の著作物がタダで手に入いるよ,と言われても先人の格言「タダより高いものはない」を信じるタイプである。WinnyあるいはShareによる情報流出の仕組みは,要するに,共有フォルダとしてネットワークに公開するフォルダの中に,勝手に非共有フォルダ内の適当なファイルをコピーするウィルスがある。そして,ウィルスはごく普通の画像ファイル等を装って容易に感染するということだ。詳しくは,さまざまな場所に解説がある(例えばhttp://event.yahoo.co.jp/winny/about/index.html)。 痛い経験から,企業・役所の管理者はやっと事態の深刻さに気づき,公開すべきでないデータを扱う仕事は,Winnyの入ったパソコンでは行わないようにするという,至極当然かつ初歩的なルールを決めた。 ここで私の感想を述べる。公私混同と,著作権の蹂躙は,同じ根っこ〜ルーズさという根っこがあるのではないかと思う。公私混同とは,公的な性格の仕事に私物のパソコンを使うことに抵抗を感じないことで,する方もさせる方もどうかと思う。データを持ち帰って家で仕事をすれば(いわゆる風呂敷残業),使用者側は残業手当を節約し,設備投資を従業員の私物に置き換えることで減らせる。従業員が仕事の都合上やむを得ずパソコンを購入したのなら,実質的に賃金を奪われたのである。どうして怒らないのか。 もう一つは著作権の問題である。音楽,美術,演劇など創造活動は,どれだけ全身全霊を打ち込み,命を削るものであるか(幸運に偶然のようにできるように見える場合であっても,才能と,それまでの血の滲む努力の結果である)。常人には不可能な価値の創造という行為には,それに見合う対価を支払うべきである。そうしてこそ,価値あるものを共有し,みんなで楽しむことができる。 いずれも,自他の間に築くべき垣根を築いていない,けじめのなさが共通している。他人の創造を尊敬できない人は,私物のパソコンを公的に使っても抵抗感がない。このようなだらしなさが引き起こした問題である,と私は考えるのだが…。 |
2006.04.17(月) delete と delete[] |
C++のプログラミングに関する話題。専門的なことに興味がない人はパスしてください。 new で確保したメモリを開放するのが delete である。ただし,TheString = new char[xx]; などの構文により配列を確保した場合は,delete []TheString; のように"delete[]"を使うことになっている。しかし,実際上,配列を開放するときも,"delete"で通用してしまう場合が多い。じゃ,どこが違うのだという疑問が当然わいてくる。本当の答はもう分かっていて,「処理系によってそれぞれの答えがある。」である。なぜならnew,deleteは一般に使用する基本ソフトの条件に合わせて上書きして使うことが想定されているから。(アセンブリ言語に変換して確かめることができる) しかし,ほとんどはこうするだろう,という想像は容易である。配列といってもその大きさは「1個の要素のバイト数×要素数」で計算できるから,ある大きさを持つ単一のブロックとして確保し,開放すればよい。だから,たぶんどの処理系でも「"delete[]"は"delete"と同じ処理」である。ただし,次の場合を除いて。 それは,デストラクタをもつ構造体(あるいはクラス)の場合である。メモリを開放するするときにさまざまな後片付けの処理をする特別の関数に集めて自動的に実行することにしておくと,プログラムが簡潔になり,保守しやすくなる。この特別の関数をデストラクタという。(同様に,メモリを確保した直後に,自動的にやっておきたい定型的な処理を集めた関数をコンストラクタという)デストラクタを伴う場合はメモリのかたまりを一つ消してこれでOKと,涼しい顔をしているわけにはいかない。確保した配列の要素数に等しい回数,デストラクタを実行しなければならない。この場合はC++のプログラマーに見えないかたちでどこかに記録してあった,1個の要素(クラス)の大きさと・個数と,デストラクタの場所を使用して複数回デストラクタを実行する必要がある。その役割を担うのが他ならぬdelete[]である。(あくまで想像)ひょっとして,deleteで両用できる処理系もあるかも知れない。(単純なdeleteに備えるだけでも,メモリ中のどこかに,newで確保したメモリの先頭と大きさ(と,もしかしてデストラクタのアドレス)の対応表を作らざるを得ない。配列でないnewもnew[]に統合して要素数1で記録すれば,開放関数は統一できる) さすがにそれは特別だろうから,デストラクタをもつ場合の,配列の開放はdelete[]を使うべきだ。 それでは,delete[]が本当に必要な場合にdeleteを使ってしまったらどうなるか? 例えば,クラスがコンストラクタまたは途中で自分自身以外のメモリを確保している場合,デストラクタが片付ける。new[]をdeleteで片付けたつもりでも,deleteではデストラクタが実行されないから,自分が途中で余分に確保したメモリが一部開放されない。それは以後参照できない部分だから,ゾンビになる。だが,それもアプリケーションを終了した時点で結局はすべて開放される。最近のコンピュータのメモリの実装状態では,問題になるほどではないだろう。結局物理的な問題というよりは,プログラム作法の問題だ。「デストラクタを使ってメモリをきちんと始末できないプログラマーは,たぶん他の部分でも問題を起こしている」 |
2005.11.02(水) 真のバックアップとは |
東京証券取引所で11月1日に起こったシステムダウン事故は,最近の巨大システム構築に関わる基本的問題を示唆している。 原因として,事前テストの不足が報道されているが,もう一つ,バックアップの構築に関して想像力の欠如があったと思われる。 巨大システムのソフトウェアを開発中に,予想外の問題が次々に発生してくるのは明らかだ。それらの問題に対して,細大漏らさず誠実に対応しようとすれば納期には遅れ,予算もオーバーするだろう。当然管理者はいやがり,技術者に強烈なプレッシャーをかける。耐え切れずに,未解決な問題が残っているのを承知の上でえいっとばかりにOKを出してしまうこともあろう。 しかし,だからと言って人間関係や道徳心の問題を解決すればすべてOKかと言えば,そうでもないと思う。 プログラムが大きくなれば,問題の発生する確率が指数級数的に増大するので,完全な解決できるまでテストを繰り返している内に,予定稼動期間が終わってしまうかも知れない。また通信に関わる場合,実際に想定される量をシミュレーションするには多数のアルバイトを動因するなど費用が膨大になり,現実的に不可能な場合もあろう。 従って大きなシステムになるほど,不完全さの増大は不可避だ。ここは割り切ってその不完全さを適当な数学モデルで評価し,危険度をリアルに捉え,問題が発生したときの対策を用意しておくべきである。つまり巨大なシステムは,隠された欠陥を内包していることを前提とし,ソフト自体の欠陥を予想したバックアップをすべきである。 一例として,次のアイディアはどうか? @2つの独立したグループに,同一の目的をもつシステムを別個に開発させる。 A両方のシステムを,同時並行で稼動させておく。出力側にはそのうちの一方を接続し,もう一方は監視用に利用する。 B時々(なるべく不定期に)出力側・監視側を役割交換し,両方とも正常に機能することの確認する。これは,切り替えテストを兼ねる。 C万一出力側のシステムがダウンした場合,直ちに監視用だった方を出力側に切り替え,ダウンした側の原因究明と修正作業に入る。 その際,2つのシステムはできるだけ異なるアルゴリズムを使用し,実際の信号の伝達や電源系統の共有部分をできるだけ少なくするとよい。完全に独立しているとすれば,1つのシステムでダウン時間が1年間あたり平均3時間ある場合,2つのシステムのダウン時間が重なり合う確率は1460年に1回か。(ただ,計算には自信がない)旅客機の安全対策(操縦伝達系統の複線化)から学ぶのもよいのかも。システム作成と運用の経費は2倍になるが,特に人命や財産に関わる場合踏み切るべきではないか。 |
2004.09.25(土) データの保護について |
ハードディスク上に置かれたファイルは,ネットワーク環境下では意図せぬ形で外部から読み取られる可能性がある。またコンピュータを廃棄する過程で,物理的に残っていたファイルを読み取ることも可能である。だから学習成績,住所,家族構成などの個人情報はハードディスクに置かないようにすれば,問題は解消する。 しかし,それでは,データに対して高度な処理をしようとすればするほど煩わしい。もしハードディスクに安全にデータを置く方法があれば,それに越したことはない。そこで,個人情報など外部から読み取られてはならないファイルは,暗号化してハードディスクに保存し,担当者だけが解読キーをもって変換して利用できるが,変換できなければ物理的には無意味な文字の塊にしか見えないようにする。そして,解読が完全に不可能でなくとも,解読のために莫大な労力を要し,目的から見てとても割に合わないようなシステムにしておくのがよいだろう。その実現を目指し,現在作業中である。 |
2003.12.31(日) 「人・機械」系とプログラム言語 |
![]() その結果,誤りの確率が増加するが,これは重大なことで,特に人の生命や財産に関わる分野のプログラムでは致命的な問題になる。(例えば大型旅客機の操縦。学習成績の処理はそれに比べれば気楽であるが,こちらも誤りが時に人生を左右する点では同じかも知れない) パソコンに慣れない人は,操作に失敗したとき自分を責めがちである。しかしそれはプログラム使用者の不注意に帰すべき問題ではなく,実はシステム設計上の問題である。特に人との対話でことを進める部分のプログラムの進行は注意深く人の発想に一致させるべきである。 ところが,人間の自然な心の動きは,さまざまな条件の絡み合い複雑怪奇で,線で表現すると相当入り組んだスパゲッティ構造になる。それを適切な変数と関数の呼び出しで表現するのは至難の業であり,C++が予想するオブジェクトの単純な並列・直列構造では本質的にはサポートしきれない。 もっともC++でもうまく工夫すれば相当整理はできるが,例外的な接続を無数に含む状態をより判りやすく適切に表現できるプログラム言語を考えている人はいないのだろうか? |
2003.11.02(日) 「枠間相互演算」への旅立ち |
強力並べ替えの個人文書編集画面は,成績一覧表のようなものにも対応できるようになってきた。さらに進んで表計算ソフトのセル間演算に対応する機能を備えつつある。方法は,機能文字(各「枠」の記述文に埋め込まれ,特定の機能を意味する表示されない文字)にしたから,とりあえず文字をキーボードから入れればこの機能を使える。 要点だけ述べると,計算式は$=( )のカッコ内に書き,枠の値は枠0002などと記述。四則演算は,+-*/で普通に記述。カッコの入れ子はいくらでもOK。関数は当面√だけ用意した。 $=(枠0001/7,2)は,「枠0001」の値を7で割り,答は小数点以下第3位を四捨五入して,小数点以下2桁にするという意味。小数部分切捨ては$=(枠0001/7,0,-1)。[最後の-1は切捨て。代わりに1を書くと切り上げ,0を書くと四捨五入] 今後関数の増加,設定のサポート(マウスで対象枠範囲や,条件を指定等),複写したときの式中の枠番号の自動変換などが課題である。 なお,当然循環参照への防止策を講じてある。従って「枠Aが枠Bを参照し,枠Bが枠Aを参照する」場合も無限ループによる「応答なし」は起こらない。エクセルでちゃんと防いであるのを見て,常々大したものだと感心していたが,実際作ってみたら意外に簡単なアルゴリズムでできた。 |
2003.10.09(木) 背景画像を交換可能にしたことの意味 |
基本画面のデザインは,最初に「とりあえず作った」状態から全く変わっていなかった。これを交換可能にしたことは楽しめるが,実質的な機能改善ではないので,そんな暇があったら本体をもっと使いやすくせよ,という声が聞こえてきそうである。 しかし本当の理由をいうと,杉システムが,従来は個人データとして数値・文字を対象にしてきたが,それに加えて画像データも扱いたいという野望がある。(例えば作品や活動の姿などを記録し,書式にあてはめて印刷するなど)その準備の一環なのである。 |
2003.08.07(木) プログラム作りは鉄道工事に似てる? |
JR中央線の夏は「旅路」という言葉がぴったりである。車窓の景色もハイキング姿の乗客(特に元気な中高年の姿が目立つ)も。 昨日所用で久しぶりに特急あずさとしなのを乗り継いで名古屋に帰ったところ。複雑な地質構造をもつ山岳地帯を通る鉄道だから,そのトンネルの多さが感慨深かった。古い技術の時代に,あらゆる知恵を発揮し,根性でおそらく数多い犠牲を払いながらトンネルを掘り進んだのだ。複雑な断層地帯にぶつかって10m掘り進むのに何ヶ月も費やすこともあったろう。 だが,一度開通してレールが引かれてしまえば,特急は一瞬に通り抜ける。そんなごく短い区間が先人のあらゆる技術と苦心の結晶であったとしても。 で,プログラムを組む人がトンネルを掘り,鉄橋をかけ,レールを引く技術者と労働者だとすれば,ユーザーは特急の乗客か……。などと車上で考えていた。 |
2003.06.29(日) またまたWindows xpでAPI関数の仕様変更?それともバグ? |
2.00.82への更新を余儀なくされた問題について。 リッチテキストエディットコントロールはウィンドウの一種であるが,所属するウィンドウの一部に埋め込んで使っている。これを「子ウィンドウ」という。子ウィンドウが所属する親ウィンドウは,CreateWindow関数でWS_CLIPCHILDRENを指定して作成すると,描画命令がきても子ウィンドウの部分だけ描画されない。(クリッピングという)だから親ウィンドウが書き直されても入力中の文字列はそのまま残る。常識的に考えて、クリッピングは、子ウィンドウをCreateWindow関数でWS_VISIBLE(「作成後最初から表示する」)指定で作成した瞬間から機能しなければならない。実際機能していた。Windows95と98の時代は。 ところがxpでは後から作成したエディットコントロールに対して機能しない。(えっ?)だからデータ選択用画面(WM_ONMOUSEMOVEで親ウィンドウを描画し直している)はマウスに触れた瞬間にエディットコントロールを覆い隠した。(実はその前から表示が不完全である)仮に後から動的に子ウィンドウを作ることは想定されていないとしても,常識的にこれはバグである。 ではどうやってこの困難を回避したか? −−幸いなことにエディットコントロールをMoveWindow関数で移動させると移動先でクリッピング機能が回復するのである(!)。そこでわざと予定と違う場所に非表示で作り,動かして「表示」にするようにした。 昔気質の職人技の発揮は楽しいが2003年になってこれでは何をかいわんやである。 |
2003.03.12(水) Windows xpでAPI関数の仕様変更が… |
バージョン2.00.79への更新の原因になった,「重み」の入力がxpでできなくなっていた問題について。他の入力はほとんど問題ないので非常に不思議だったが,調べて見たら原因がわかった。入力BOXからの文字データの引き取りには'WM_GETTEXT'という機能コードを使う。データが長すぎて受け側のバッファをはみ出すとクラッシュするので通常は事前に'WM_GETTEXTLEN'で長さをチェックして,バッファをオーバーするときには文字数を制限して読み取る。しかし,重みデータの場合は,文字数は明らかに数文字以内である。バッファは4096バイト用意してあるのでノーチェックでOKにした。で,長さ=0でWM_GETTEXTを使えば自動的に入力BOX内のデータの長さ分だけ読み取るはずだった。確かにWindows98までは…。ところがxpでは長さ=0と指定すると「長さ0」の文字列として引き取る。つまり実質何もしない。プログラムでは読み取る前にバッファは空にセットしていたので結果,何を入力しても値0にしかならない。なるほど。 修正方法は,他の場合と同様に,文字数を事前にカウントして調べ,その文字数を指定して読み取ることにした。Windows98以前でももちろん問題は生じない。 |
2003.01.22(水) アクセスカウンターの事故を経験 |
さる17日20時ごろ,カウンタ記録が消失した。確かにあるタイミングでアクセスが連続すると起こり得るが,確率は大変低いと思っていた。バックアップを元に修復できたが,わずかの確率で開くプログラムの穴も塞いでおいた。(今回もHPサイドのプログラミングについての話題でした) |
2003.01.08(水) アクセス数の公開(CGIを使う) |
今までは非公開だったアクセス数を公開することになったので,カウンタープログラムを改造して表示することにした。大抵のHPでは,一桁ごとに画像1個を表示しているのを見て,どうして1個の画像(あるいはテキスト)にしないのかな,と今までは思っていた。ところが,実際にperl言語を使ってカウンター用CGIプログラムを作ってみると,やはり一桁ごとに画像を貼りつけていくのが簡便な方法であることが分かった。因みに画像のためのフォントは,有澤行書を使用した。(今回は杉システム本体ではなく,HPサイドのプログラミングについての話題でした) |
2002.11.15(金) システムの更新も伴うことになったので… |
以下の事情でシステムをマイナーチェンジする必要が生じた。そこで今回はシステムと見本データの同時更新となったので11/03の件は今回は見送る。 さてその事情であるが… 平成15年度用書式には細かな点線が使われていた。ところが,画面である程度を越えて縮小すると点線表示中に止まってしまう!ことが判明。書式作成完了後,次回に作業に入ろうとすると,その立ち上がりは縮小表示なので,最初からいきなり何もできなくなる。そこでその点を修正し,システムをver.2.00.74とし,新年度用書式データを追加した見本データと組み合わせてローダを更新した。 |
2002.11.03(日) 見本データだけ更新するプログラムを作らないと… |
ver.2.00.73お試し版には,参考のため見本データ試験的に平成14年度の愛知県公立高等学校用書式がつけてあるが,来年度(平成15年度)入学者用願書の書式が確定したので,更新しなければならない。現在データの見本だけを送信するプログラムはまだ作ってないのでまずこれを作らなければならない。1週間程度? |
2002.09.17(火) 『杉』システムの更新はここまで来たが… |
「学習成績一覧表」の書式は,某市で中学校用に使用されているものを参考にして,強化された文書書式作成機能の操作テストとして実験的に作成したものであるが,とりあえず見本データに加えておいた。利用するときは,[編集]画面で,「見本利用」を使う。"枠"(表計算ソフトの「セル」に当たる用語)は,全部で2999個(!),ファイルは400キロバイト(全角で20万字ぐらい)以上になった。「これくらいあれば当面大丈夫だろう」と思って当初設定した32キロバイト(64キロバイトのつもりだったがプログラムミスでそうなっていた)を早々と突破して,内部形式(メモリに読みこんだときのデータの構造)の修正が必要になった。(理論上の限界はこれで全角2億文字ぐらいになった) ファイルは,"sotenxx"ファイルなどとは異なり,完全にテキストファイルで記述し,内部的にもテキスト形式のデータで通した。その結果ファイルは大きく,動作は重くなったが,とりあえずそのままにしておく。「メモリの節約,共通動作の繰り返しを避けるためにプログラムを研ぎ澄ます努力は,数年後のメモリの拡張とクロック数の増加によって結果的に無意味になる」という法則を,今回は尊重した。 今回登場した「縦書き」は,横書き用フォントを1文字ずつ分解し,"()"などは回転し,"、。"などは右上へ向かって適当な量並行移動する。半角文字はスペース以外は全角文字扱いにした。ただ,半角数字が2個続き,その前後が数字以外の文字である場合は特別に横並びにしてもよいと思うが,今回はそこまではしていない。(プログラムの練習問題としては面白い) |