あるバグの話

僕が大学生だった頃の話だから、たぶん、15年前くらいのことだろうか。
(ツッコミ無用)

アメリカのある放射線治療器で、プログラムのバグで患者が死んだ、そのバグの話が、何かの雑誌に掲載されていた。なんで読んだか覚えていない。指導教授の内山先生が「新医療」という雑誌を購読されていて、研究室ではフリーアクセスで、あれこれ読めたけれども、それだったか、なんだったか。

どういう状況かと言えば、操作画面で、まず、放射線の線源を選ぶ。アルファ線照射とか、ガンマ線照射とか、切り替えられる画面だったらしい。次に、線量を入力する。その線量を入力した後で、Enterキーを押さずに下向き矢印[↓]を押して画面移動をすると、線源が切り替わってしまうという現象が起きてしまったらしい。つまり、医師(か、または日本だったら放射線技師)は、画面上はガンマ線の線量としてある値を入力した、ところが、その線量のまま内部的にはアルファ線照射に切り変わってしまう、という現象が起きてしまった、らしい。

今改めて、そのストーリーを思い出してみて、一般的な機器設計を考えたなら、おそらく、画面上の入力は生物学的効果比(RBE)を乗じた線量当量(Sv;シーベルト)ではなく、線源線量/照射線量(C/Kg)か何かで設定したもので、たぶん、ガンマ線やベータ線のつもりがアルファ線に切り替わった、という感じの現象が起きたに違いない。結果的に、患者に致死量の放射線が照射されてしまった、ということのようだった。

コンピュータプログラミングの経験のある人なら、このストーリーを聞いて、どんなプログラム構造だったか、すぐに見当がつくに違いない。if/else、あるいは、switch/caseなどの「条件分岐」の「組み合わせの想定漏れ」か、あるいはトラップの入れ忘れ、などが重なったに違いない。

このプログラムを書いた方を擁護するならば、当時のコンピュータは、マイクロコンピュータで主記憶32kバイトとかだったし、数千万円もする、こうした医療機器制御用のミニコンピュータでも、プログラムが利用可能なメモリサイズの上限が十数キロバイトとか、今では考えられないほどプログラミングの制約が大きかった。テスト手法なども限られていた。時代が違う。
ただ、当時は「殺人プログラムの危険性」として有名な話だったと記憶している。

JRのチケット発行システムのバグ、も、なんだかこれに近いロジックのチェック漏れじゃないかと感じた。なんだか、バグを出したプログラムの論理構造が眼に浮かぶような気がする。Javaかなぁ。

CやJavaのプログラマの場合、古い人なら大体経験があると思うけれども、

if( 条件 )
{
 条件が成立した時に実行するプログラムX
}

なんていう構造は、よく書くだろうけれも、ついうっかり、これが

if( 条件 );
{
 条件が成立した時に実行するプログラムX
}

とかになっていると、このプログラムXは、条件が成立しなくても常に実行してしまう。たった「;(セミコロン)」一つで、使い物にならないソフトになる。(システムを壊すのは、極めて簡単。たったの一文字書き換えれば、見た目エラーにならないのに、動作はおかしくなる。)こんな程度のバグが見つからずに、数日徹夜したりもした。これだけ抜き出せば簡単そうに見えるけれども、数千行ある中からこの部分を特定するのだから、それほど簡単じゃない。(これは一例ですが。)
最近のIDE(統合開発環境)はだいぶ賢くなってくれていて、こうした凡ミスに警告を投げてくれたりもするんだけれども、「間違い方」によっては、文法エラーにもならないし、見かけ上は「まともなプログラム」で、新人とかだと、全く、論理を辿れないケースもあるかも知れない。

わかりにくい変数名や、紛らわしい変数名は使うな、なんてことを言い出すのはベテランだけ。若手にはなかなかその理由すら通じなかったりする。これは経験の問題かも知れない。

最近、小学生からプログラミング教育を、なんて、やっているけれども、あれは「才能発掘」には役立つだろうけれども、早くからプログラミングの発想法に馴染めば、プログラミングの才能が伸ばせるか、と言えば、私は懐疑的で、論理展開の能力は、素質が半分以上を占める気がする。
大学生の場合だと、1年生でも恐ろしくセンスのいいプログラムを書く学生が毎年3%とか5%とかはいるけれども、長くやってればセンスが身につくとは限らない。だから、「新人だと、なかなか原因がわからない」という表現は、あまり正しくない気がする。センスがない人だと、たぶん中堅でもバグの原因はわからなかったりする。
論理展開能力は「議論」とかしてみたらすぐにわかるし、素質がある人なら「プログラミング学習で身につく文法知識」とかマスターするのに一ヶ月かからない。むしろ、読書(濫読)の方が役立つような気もするんだが。あるいは、ジグゾーパズルとか。
話を戻して。

そんなことがあるから、最近、僕は大学院の授業では、TDD(Test Driven Development; テスト駆動開発)とか、BDD(Behavior Driven Development; 動作駆動開発)に、軽く触れている。平たく言えば、「システムテストを最初に網羅的に書き上げて、そこからプログラムを組みましょう」という、従来とは真逆のアプローチのこと。今までは、仕様書が出来上がってから、システム開発が終わりに近づいてから、必死で「テスト手順書」とかを書き上げた。(この手順書も、「役に立つテスト」にするには素質が必要だという気もする。)そうではなくて、最初に、プログラムの振る舞い(Behavior; 動作)を先に規定して、そこからプログラムに入っていく。そんな方法。
ただ、あまり面白味がないし、地味だし、なぜ大切かは、たぶん院生くらいじゃまだわからない。結果だけ早く欲しがる「経営者」ウケは、あまりしないだろうし。昔っから「急がば回れ」って言うんだけれども。

Rubyでは、結構この辺が定着してきている。Pythonの場合は、ごめんなさい、まだ勉強中。ただ、CとかJavaだと、いわゆる「レガシー」に縛られ過ぎていて、身動きが取れないんじゃなかろうか。きっと、JRでも金融機関とかでも、CobolとかJavaとか、その辺のあまりコード生産性が高くない言語に「レガシー」とかでこだわって、人海戦術で何千万とか何億とか投下して、その上に、テストだけでも何千万とかを上乗せして、力技で解決しようとしているんだろうか。話を聞いてみると、「方法」を洗練させたり、新しいプラットフォームを試すような「冒険」を避けて、レガシーの焼き直しとか、とにかく人海戦術で人を掻き集めて、力技で大金を投入してシステムを仕上げようとしているような、なんだか方向性が違っているような気もする。私には関係ないから、どうでもいいけど。

今日、実は新規案件のお話を伺ってきた。最初「初回お試し」のつもりで格安で仕上げたら、その「初回お試し」料金が定着しちゃって・・・。今回も、高い金額を言ったらたぶん「開発そのものを諦める」感じだから、まあいいかなという金額で、要するに頼みたい側が払える金額で作る、そんな感じになるんだろうけれども。僕がそう言う性格だから、これはこれで、もういい。
もし、同じシステムを大企業が受けたとしたら、たぶん、新人を交えて3人から5人くらいのプロジェクトになるんだろうか。頭数が複数になったら、まず意思疎通に時間が取られる。新人教育なんかも兼ねて、会社としてペイする金額で受注したとしたら、(あまり、こういう墓穴を掘るような話題は書きたくないけれども、)僕が一人で2ヶ月で仕上げる仕事を、3人から5人で短くても4ヶ月くらいでやる感じになるだろうか。給料水準も違うし、大企業の場合には「退職金積立」だの「年金積立」なんかの分もコストに加算して、しかも「利益」を出せる水準で見積もりを出すとしたら、当然、アノくらいの金額になるんだろうな、という予想がつく。試算すると気が滅入ってくるから、やめよう。「年金」かぁ。働けなくなったら、もうあんまり面白くないから、そこまでで、もういい。

そろそろ、非常勤講師を辞めて、システム屋に専念したい、そんな気もしているけれども、やっぱり、大企業との「格」の違いは痛感する。同じものを納入しても、たぶん、金額の桁が違う。いや、それでも、あの大学の教員をやっていた頃よりは、まず気分的に楽だし、仕事が安定すれば、今の方がいいように感じるから、ベストかどうかは別にして、ベターな選択肢だったと納得はしているが。

こういう言い方は、なんだか、やっかんでいるみたいで、あまり良くないかも知れないけれども、大企業が力任せの開発を続けていれば、もう限界に来ているから、たぶん今回みたいなバグの話は今後も増えるような気がする。そうなってくれば、新しいプラットフォーム、新しい環境に挑戦している若い世代にもチャンスが回ってくるような気もするし、僕も、どちらかと言えば、次にチャンスをつかむグループに食い込みたい。新陳代謝が起きようとしている時だとしたら、「特定の条件で、画面がフリーズする」なんていう話を聞くと、「なるほどなぁ」という感想しか出てこない。
(やっぱ、やっかんでるじゃねぇか。)

さてと。これから日付が変わるまでに、一気に基本設計を書き上げる。SEは、一に体力、二に気力。三、四がなくて、五に素質、かなぁ。(個人の感想です。)