第 10 回プログラミングのイディオム ( 後編 ) 「ああ。そういう話はある。だけど、そうなっていないソースが世のなかにはたく さんある。この業界にはステップ数 ( # 行数 ) x 作業単価で報酬が決まるという悪 習がいまだに横行しているところがあって、コピべがまかり通る。わざわざコピペ で行数を稼ぐプログラマまでいる。 仮に、作業するプログラマにそこまで悪意がないにせよ、共通の関数に括り出す作 業をするより、コピペするほうがはるかに作業は早い」 「そういうコピべが保守性の悪いプログラムを生み出すんですよね ? 」 「もちろんそうだ。ただし、すべてのプログラムに保守が必要だとは限らない。一度 きりで構わないかも知れない。書き捨てで良いかも知れない。保守するのはプログ ラムを書いた本人ではないかも知れない。さまざまな理由により、すべてのプログ ラムが保守性に優れたものであるべきとは言えないし、そうもなっていない。ケニ チ君よ。ケニチ君は、それらのプログラムに立ち向かう術を知らなけれはならない」 早井が真剣な眼差しでケンイチを見つめる。 「はい」 「ところでケニチ君 ! 」 ケニチ君の本当の名は ? の巻 0 「は、、はい。そうですけど」 「はい、なんでしよう ? 」 「君の名前はひょっとして、ケニチ君ではなく、ケンイチ君ではないか ? 」 ケンイチは少し殺意のようなものが芽生えた。 そうと早く言ってくれよ。がははははは」 「ああ、そうだ、ケンイチ君だよね。なんだかおかしいと思ってたんだ。それなら 195
第 2 回バグの発生点と発現点 早井はあっさりとそう言っ放った。ケンイチにしてみれば、あらぬ疑いをかけられたの だから、「じゃあいいや」と言われてもちっとも「いい」ことはなかったが。 「午前中にやってもらおうと思っていたプログラムのデバッグの仕事があるんだけ ど、正午まであと 30 分しかないな。まあ、 30 分以内にデバッグしてこのメアドに 出しておいてよ」 「えつ。 30 分で、ですか ? 」 「ひなた先生の授業を受けてきたなら、それくらい朝飯前だろ ? 」 「えっと。その。あの」 ケンイチは何と言っていいのか言葉に詰まった。まさか、「にゃんことうさうさについ 「ああ、お客さん、その筋の人なのでね、正午までにできないと指を落としてお詫 びすることになるかもしれないよ。正午までに絶対頼むよ。プログラマなのに指が なかったら仕事に差し支えるだろ ? 芸能人は歯が命、プログラマは指が命、なん ちって」 早井は、どこまでが冗談かも判然としないことをいともあっさりと言い放った。ケンイ チは鳥そぽろ弁当どころの騒ぎではなくなった。 バグが露見した間に停止させよ 問題のプログラムのバグというのは、一見すれば単純そうだった。次の箇所で起きてい ることまでは特定できた。 ( リスト 1 ) マリスト 1 バグが露見する部分のプログラム void gekogeko(Person person ′ Action act){ person.doAct(act); この関数の引数は 2 つある。この関数では person に「ケンイチ」が入っていて、 act に 「人を好きになる」が入っていれば、「ケインチが人を好きになる」処理が行われる。 31
b00 には C # でどう書くの ? の巻 参照型を値型として扱いたいの巻 ケンイチの講義ノート 早井先輩の正体の巻 . get は「 ead と違うの巻 .. 279 28J .. 286 .. 287 . 288 ~ 289 最終回 登場人物紹介 今回のまとめ / 参照透明性 ( 「 eferentialtransparency) バグを憎んで人を憎まず ソースコードから書き手の意志を読むの巻 早井先輩の書いたコードの巻 . もはやコーディングができないの巻 早井先輩の名前の由来の巻 . 望まれていない生命の巻 早井先輩の正体の巻 . 康ニ、旅への巻 . 兄の悲しみの巻 . エピローグ 初出情報 . 290 .. 290 .. 291 .. 292 .. 29J .. 294 .. 299 .. 302 .. 306 .. 307 .. 引 0 新人プログラマ ケンイチ 大学で情報工学を専攻していた , この春に入社したばかりの社会人 一年生。職場で要求される仕事の レベルは高く、ついて行くために 日夜猛勉強をしている。 先輩プログラマ 早井 言動は荒いが根は良い人。 時代はラグビー部主将。関西人で す若手工リートプログラマ。学生 1 人で複数のプロジェクトをこな 特別講師 倉塚ひなた 9 の頃に早井を指導 ) で趣味は食玩集め。 行なっている。早井の師匠 ( 早井が新人 毎週ケンイチにプログラムのレッスンを いる。会社では、プログラム講師として、 まわりからは「ひなた先生」と呼はれて ケンイチの勤める会社の特別技術顧問。
ひなた先生な 第 7 回 テ / ーッグが -ect による くなるテクニック 、グの再現 4 月に入社して以来、みるみるうちに力を身に付けたケンイチ。彼はいよいよデ バッグの極意をも掴み始めていた。しかし、それはまだ具体的な形を成してお らず、ただ思考上の不安定なもやもやとしてケンイチの頭の中に存在している だけであった。 プログラマのお給料って凄いの巻 ケンイチは早々と出社し、特別会議室に向かった。今日はひなた先生の授業のある水曜 日。ひなた先生が来るまでに予習をしておくのだ。 「デバッグを行うための小手先のテクニックではなく、もっと一般的に、プログラ ミングにおけるデバッグの指針を得る方法はないだろうか ? 」 ケンイチは鉛筆を片手に大学ノートへ落書きを始めた。 「プログラムは規模が小さいほうがデバッグがしやすいはずだ。たとえば、 3 つの関 数を呼び出すプログラムの実行結果が自分の期待と異なるとすれば、その 3 つの関 数それそれにバグがないかを検証しなければならない。 これが 1 つの関数で済むなら手間は単純に考えて 1 / 3 だ。すなわちバグがあると疑 わしい領域は少なければ少ないほどデバッグするうえで好ましい ( 図 1) 」 マ図 1 バグがあると疑わしい領域 プログラム バグがあると 疑わしい領域 124
第 15 回 バグを憎んで人を憎まず ケンイチは呆れ顔た。 「ち、違うんだ、ケンイチ。最後まで話を聞けい ! 」 「は、はい」 「その装置の実験も兼ねて試用したわけだが、その装置自体が失敗作だったんだ」 「どう失敗だったのですか ? 」 「データ転送が間に合わなくて書き込みに失敗することがあるんだ」 早井は真顔でそう言った。 「 CD - 日ですか・・・」 なんだかどこからどこまでが本当だかわからなくなってくるケンイチ。 「おかげで俺は一部の記憶を失ってしまった。自分の名前すら忘れてしまっていた。テ レビではスティーヴン・スピルバーグ監督がインタビューに出ていたので、俺は自分 の名前を勝手にスティーブン・早いデバッグ、さらにもじって、スティーブン・早井 出婆具と名付けた。 それがすべての始まりだった・・・」 「すべての始まりというか、そこで物語はすべて終わってそうですが・・・」 「ま、まあな」 もはやコーディングができないの巻 「ケンイチはプログラマなんだから、こんな嘘くさい身の上話よりも、プログラム のソースコードのほうがよほど真実に近いものが伝わってくるとは思わないか ? 」 「それはどうでしよう・・・」 293
0 ひなた先生か教えるフノ、 . ノノ、 ~ ノ - し , - - テパッグが 。電ーくなるテクニック そう言うとケンイチは苦笑いした。ひなた先生は、「ふふふ」と屈託なく笑った。 「このとき、ゲコゲコがバグっているのカナ ? ケンイチ君はどう思う ? 」 「そうですねえ・・・。この場合、ゲコゲコが実行されて初めてプログラムにバグがあ る、意図したとおりに動いていないということに気付いたわけですが、これはバグ が露見したのが、ゲコゲコであったということに過きなくて、バグはもっと以前の 段階にあるかもしれませんよね」 「だよねー」 「バグの発生点 ( プログラマが間違ったコードを書いてしまった箇所 ) と、バグの 発現点 ( バグが露見する点 ) とは時間的、コード的に離れているのが普通ですか ら。だから、バグの発現点から実行されたのとは逆の順番で追いかけていき、バグ の発生点を突き止める必要がありそうですね。この場合、ゲコゲコを呼び出してい るのは、にゃんことうさうさなので、そのどちらかが意図したとおりに動いていな い可能性があると思います」 「ケンイチ君はどちらが犯人だと思うの ? 」 「それは、これだけの情報だけではわからないです。ひょっとすると、わんわんが犯 人かも知れませんし」 と言うと、ケンイチはニャリとした。 都「えー。そんなあ」 ひなた先生は今にも泣き出しそうだった。あとになってわかった話だが、ひなた先生は 無類の犬好きなのだそうだ。 0 呼び出し元の特定の巻 「じゃあ、条件を追加するね。ゲコゲコを実行したときの様子がおかしかったの。 3 回のうち 2 回は美人のお姉さんが出てくるんだけど残りの 1 回は怖いお兄さんが出 てくる。だから、怖いお兄さんが出てきたときに、いったん停止させて、そのとき 28
第 6 回 第 7 回 第 8 回 第 9 回 6 Sparse Matrix による logging やばい ! ! 遅刻かも ? の巻 ケンイチのヒミップログラムの巻 . G00 図 e の Page 日 ank のしくみの巻 PageRank を行列計算で考えるの巻 ケンイチの昼休みの巻 噴火寸前の巻 . 5 分と 5 時間の巻 Sparse Mat 「 ix の実装の巻 ケンイチの講義ノート .. 104 .. 105 .. 105 .. 111 .. 113 .. 114 .. 115 .. 118 .. 122 ~ 123 104 今回のまとめ / Spa ℃ e Mat 「ⅸを使うロギングは本当に役に立つのか ? プログラマのお給料って凄いの巻 バグを絞り込むの巻 . プログラムを変形してバグの原因を絞り込むの巻 . 削ろうにも削れないの巻 早井先輩は健忘症の巻 ヘビー級オブジェクトの巻 . ケンイチの講義ノート 今回のまとめ proxy object によるバグの再現 ケアレスミスはなぜ起きるのか ? 対称性を意識しろ ! の巻 早井先輩は、最近ヘンの巻 再帰的プログラミングの巻 迷路から脱出せよの巻 一緒にお風呂の巻 . ケンイチの講義ノート .. 142 .. 14J 145 .. 152 .. 154 124 .. 124 .. 126 .. 128 .. 1J2 .. 134 .. 1J5 .. 141 142 .. 158 ~ 159 今回のまとめ / スキャンラインアルゴリズム / Visua 旧 tudi0 ミニテク ニック③ ( 識別子の宣言を表、インテリセンスの入力候補一覧を表示 ) ケンイチはうそっきの巻 . プログラミングのイディオム 1 「 n 回まわる fo 「ループ」の巻 プログラミングのイディオム ( 前編 ) .. 160 160 .. 162
0 ー ) つ倍 1 をくなるテクニック テパッグな 「ちょっと素人じみたプログラムだと思いますね。なぜなら、こう書けるからです ( リスト 3 ) 」 ひなた先生が教える v リスト 3 すっきりとした if 文 i f ( bl く 10 ) { i n i t ( ) , 0 をを 0 「リスト 2 のようなプログラムを見たらリスト 3 のように書き直したくなる ? 」 「そりゃあ、なりますね。そのほうがわかりやすいですし、見通しもいいですから」 「うん。それがケニチ君の言う単純化なんだろう ? 」 「ええ」 「ケニチ君。ソースプログラムをコンバイルするとバイナリファイルが生成される が、それもケニチ君の言う単純化かい ? 」 「いや、それは単純化とは少し違うと思います。なぜなら、バイナリファイルから ソースファイルに decomp ⅱ e ( 逆コンバイル ) した場合、完全にソースプログラム が復元されるわけではないからです。すなわち、コンバイルの過程で情報が欠落し ており、コンバイルは不可逆な変換だと言えるからです」 「じゃあ、先の 2 つのプログラムは可逆かい ? 」 「ええ。リスト 2 とリスト 3 とは可逆ですね」 「なるほど。では、ケニチ君は、ソースプログラムからコメントを取り除く場合、こ れはプログラムがシンプルになった、とは言わないか ? 」 「シンプルになってはいると思いますが、コメントを取り除いたあとのソースプロ グラムからコメントのあるソースプログラムに戻すことはできないですから、それ は不可逆な変換です。 不可逆な変換を引き起こす場合、その善悪は難しいと思います」 192
0 プ 2 らうウくなるテクニ ック 「それは、どうしてかな ? 」 「わかりません。あくまで僕の推測ですが、プログラムは上から下に向かって実行 されるので、スタックは下から上に向かって使って消費していけば、プログラムの 末尾部分までフルにメモリを活用できて良いのではないかと思うのですが ( 図 3 ) 」 マ図 3 プログラムとスタックの関係 最下位アドレス - プログラムの末尾 ひなた先生が教えるテパッグが プログラム 最上位アドレス 「ええ。ですので、まっとうなシステムではスタックが伸びてきてもプログラムを侵 食しないように何らかの方法で stack overflow ( スタックあふれ ) を検知する機 構を用意していると思います」 教科書に載っていないスタック構造のヒミツの巻 「じゃあ、ケンイチ君にもう 1 つ質問 ! さっきのケンイチ君のスタックの説明では、棚 に本を積むってことだったよね ? 本の厚みはすべて同じなのかな ? ( 図 4 ) 」 マ図 4 厚みの違う 3 つの本 本 C 「確かに、省メモリの環境や、昔の CPU アーキテクチャでは、そういう設計思想のも のあるよね ~ 。でも、それだとスタックが伸びてくるとプログラムを侵食しちやわな いかな ? 」 本 A 86
0 くなるテクニック テパッグが ひなた先生が教える 「うんうん」 「場合によっては、 f, g, h の呼び出しをコメントアウトにするのではなく、 f, g, h の関数定義自体を、空にしてもかまいません。この場合、明らかにプログラムは 縮退して ( 小さくなって ) いますから、集合 A は縮んだと言えます。 このようにプログラムをコメントアウトすることによって、集合 A , 集合 B , 集合 C は 縮んでいきます。たとえば、さきほどのひなた先生の描かれた図 ( 図 4 ) の左半分 をコメントアウトされてプログラムから切り離された領域、右半分を ( コメントアウ トされなくて ) プログラムとして生き残った領域だと考えることができます ( 図 6 ) 」 v 図 6 コメントアウトによって分離されたニ領域 コメントアウト された領域 コメントアウト されなかった領域 「つまり、プログラムソース上で何らかの処理をコメントアウトする行為自体が、ひな た先生の先ほどの図のようにプログラムの分割を引き起こすと考えることができます」 「さすがケンイチ君 ! えらい ! 」 「でヘへへへ」 ケンイチは顔面の筋肉がわらび餅のようになった。 「ところでケンイチ君、『第一に』って言ってたけど、まだ続きがあるの ? 」 「ええ。あります。この観点において、プログラムソースのコメントアウトと、プ ログラムソースファイルの削除は等価だということです。 たとえば、まることプロジェクトのバックアップを取っておいて、バグ発現までに 130