第 10 回プログラミングのイディオム ( 後編 ) 「うん。ケニチ君は確かに優秀だ。思考のプロセスもはっきりしている。だけど、そ のプログラム、本当に単純化する必要があるだろうか ? 」 「どういうことでしよう・・・ ? 」 「つまり、ループ脱出条件を素直に書き出して、その否定を明示的に書くスタイル ではどうだろう ? 」 v 図 3 否定形を明示的に書く 1 0 0 くニ y ) ) w h i [ e ( ! ( 1 0 0 く = x Ⅱ d o_s 0 m e t h i n g ( ) 冫 「そちらのほうが直観的かも知れないですが、やはり単純化できる部分は単純化し ておくべきだと思いますが」 「本当にそうか ? ケニチ君。ケニチ君は、プログラムは単純なほうが良いと信じて いるか ? 」 「ええ。 SimpIe is Best が僕の信条です。プログラムを見通しの良い Simp なも のにすることによって、バグが減るというのは経験的にわかっているので」 「なら、コメントはどうだ ? コメントは少ないほうが良いのか ? 」 「適度な量のコメントならばあるほうが良いと思います」 「ふむ・・・」 早井はなんだか納得のいかない様子だった。「こんな自明なことをなぜ、早井先輩はわ かってくれないのか」という苛立ちをケンイチは感じていた。 185
第 14 回ポインタと参照との関係 「俺が思うに、値型は参照型として扱えなければならないし、参照型は値型として 扱えなければならないと思うのだが、そのへんはどうなってるんだ ? 」 「あの一、意味がよくわかりません・・・」 「まず、確認なのだけど、 C # にはポインタがないよな ? 」 「はい、ありません。 unsafe 文脈の中でのみ使えますが、ないと考えたほうが良い です」 臼魯を写 「では、 b00 にをどうやって表現するんだ ? 」 「それはいつ必要になるんですか ? 」 「ば、馬鹿も一一ん ! ! 」 早井がポップコーン製造機のようになった。 「す、すみません。すみません」 ケンイチは、子供のころ、ジュース瓶の栓を集めるのが友達たちの間で流行ったときに 親父のために買ってあったビール瓶の栓を片っ端から栓抜きで抜いて、こっぴどく怒られ たときのことを思い出した。 「そ、そんなに怯えんでよろしい・・・」 早井は、冷静にそう言った。 b00 ドは C # でどう書くの ? の巻 「ケンイチ君は、他のクラスのメンバである b0 団の値を参照したいと思ったことは ないのか ? 」 「 A というクラスのメンバの持つ b00 値を他のクラスから参照したいのであれば、 リスト 4 のようなプロバティを用意すれば良いのではないでしようか ? 」 279
第 12 回変数の命名規則 「うん」 「早井先輩なら、どう思いますか ? 」 「なあ、ケンイチ君。さっき、ケンイチ君がコールドスリープで 2893 年に行って しまった。あれは、悪い冗談だったが、今から俺とケンイチ君は、時代を 25 年遡 「はい」 ろう。それは可能なはずだ。ケンイチ君、目を閉じてごらん」 スペックも、使用目的も大幅に違う。まだ PC には、ビジネスで使えるか使えない PC との違いがはっきりしている。 「今、我々は 25 年の昔に居る。この時代は、汎用機 ( ワークステーション ) と、 ケンイチの兄の巻 かギリギリの性能とソフトウェアしかない」 として生まれるときに "XOR HL,HL" と言いながら生まれてきたんだ」 「ああ。俺は母親の胎内に居るころからプログラミングをしていたからな。赤ん坊 「早井先輩は、このころから、プログラミングをされていたのですか ? 」 「このころは、 pc は、 " マイコン " と呼ばれることのほうが多かったな」 「はい」 「嘘に決まってるだろ。ははははは。それともケンイチの知り合いに、そんな奴が 「そうなんですか」 「そりゃ釈迦の誕生の瞬間の話だろ。ケンイチ君、悪い冗談だ」 てきました」 「ええ。兄がそうでした。産まれると同時に " 天上天下唯我独尊 " と言って産まれ 居るのかい ? 」 0 221
第 9 回プログラミングのイディオム ( 前編 ) " を間違えることは滅多になくなりましたし、 if の中 「慣れてくると、 で・ = ' を用いるとコンバイラが警告を出してくるようになったからです。だから、 わざわざ不自然な書き方をする必要もないな、と思って今では if (x==a) のように 書いています」 「なるほど。じゃあ、 x が a から b の範囲にあるか (a$xSb かどうか ) を調べると きにはどう書くかな ? ( 図 7 ) 」 マ図 7 aSxSb 0 0 0 ※この塗りつぶし領域が x が満たすべき範囲。 a ′ b のところ黒丸になっているのは、 a と b も含むとい う意味。 「ん一。どうでしよう。 if (X>=a & & x く = b ) とか ? 」 「数直線をイメージしながら、 a 坙 x 坙 b という数学的な表現になぞらえるなら ? 」 「それなら、 if (a<=x & & x く = b ) と書くほうが良いですかね。慣れれば、このほうが わかりやすそうです。 x がある集合内にあるかどうかを判定するような関数があっても 良さそうですけどね」 「 Pasc なら、集合型があって、 if (x in [ a.. b ] ) だとか書けるんだけど」 「あっ。そうなんですか。それ、 C にも欲しいですね」 「うん。でも、ほら。そのへんは慣れの問題でもあるから。 fif (a<=x & & X<=b) 』 という表現も慣れれば、『 (x in [ a.. b ] ) 』のように見えてくるわよ」 「そうですね。慣れてくれば一種のイディオムとして認識できそうですね」 175
0 テパックが 2 らも貰 = 一 , くなるテクニック ひなた先生か教える一 0 を 「はい」 「このプログラムには、仮引数 count とローカル変数 c 、それからメンバ変数 count_ だ。この 3 つが使われている」 「ええ、そうですね」 「ケンイチ君は、ローカル変数は、どう命名していたんだ ? 」 「当時そこは、あまり深く考えてませんでしたね。現代の視点で見れば、このケー スは、仮引数名は c とだけ書くと、インテリセンスにメソッドシグネチャが出てき たときに何を意味する c なのかわからなくなってしまいそうなので、仮引数名を count とするほうが適切だと思いますが」 「だろうなあ。つまり、こういうことだな ( リスト 2 ) ? 」 マリスト 2 仮引数とローカル変数について考えるプログラム 2 void incrementCount(int count){ i nt c count + 1冫 if ( c く 100 ) count , を臼 0 「ええ、そういうことです。ただ、ローカル変数の c というのも、当時の視点として も、やや違和感がありますね」 「どういうこと ? 」 「ある程度、メソッド本体が長い行数になってくると、この手の短い変数名をロー カル変数に割り当ててしまうとバッティングすることがあると思うのです。ですの で、 tmpCount のようなバッティングしなさそうな名前のほうが好ましいかな、と 思うのですが」 「ああ。ローカル変数には、 tmp のようなものを付けるということか」 「はい。ローカル変数は結局、このメソッドを抜けると失われるものなので、この 意味において、すべてが tmp (tempora 「 y : 一時的な ) ですから、こういう命名 230
第 13 回関数の返り値はどうあるべきか 「ああ、そうですね。 int 型を返しているような場合、その int 型が何を意味するのか は説明が書かれてなくて関数名からも推測できなければ、意味を知ることは実装を 読まない限り絶望的になりますね。仮引数名で out int 「 es 回 t などと書かれていれ ば『結果を意味する int 型を返しているんだな』とわかるのに・・・」 「うん。『だから、 VisuaI Studio がどのように改善されようとも、引数で結果を返 すべきだ』と主張する人がいてもおかしくはない。そういう人にケンイチ君はどう 反論するんだ ? 」 「今、話の中でドキュメンテーションがない場合を前提としましたが、ドキュメン テーションがないことを前提とするのがおかしいと思うのです。ドキュメンテーシ ョンは、つねにあるべきだと考えます。 ですので、やはり if (SomeFunc() = = 1 OO ) のように if 式として直接書けないのは デメリットのほうが大きいと考えます」 「そうだろうか ? ソースの可読性という意味でも、それが言えるだろうか ? 次の 2 つのソース ( リスト 17 , 18 ) を見比べてみよう」 v リスト 17 返り値で結果を返す場合とそうでない場合 ( その 1 ) if ( SomeFunc() 0 を 0 「リスト 18 のほうは冗長だけど、「 esu はという変数をいったん経由することによっ て、このソースを読む人は『 1 OO と = = で比較しているのは、 result ( 結果 ) な んだな』とこの部分を見ただけで理解することができる。 対して、リスト 1 7 のほうは、 SomeFunc の返り値が何を意味するのかをこの部分 のソースから知ることはできない。とくにソースを印刷してそれを見ながらソース を目で追いかけようとしたときに、このことが仇になりかねない」 = 100 ) マリスト 18 返り値で結果を返す場合とそうでない場合 ( その 2 ) int result; SomeFunc(result); i f ( re su [ t 257
の 。 1 ーくなるテクニック 「そんなものは、熟練されたプログラマならは無意識のうちにやってのけるはずです」 「確かにそうかも知れない。しかしコピべで済むはずのものを、コピべで済まなくな っている」 「だから、悪いとでも ? 」 「そうだ。最悪のリファクタリングだ。さらに、コピペ元にもう 1 つ条件式が加わっ たとしよう ( リスト 6 ) 。この場合どうなる ? 」 マリスト 6 コピペ元にさらに条件を追加 if ( ( 10 く = bl Ⅱ 10 く = b2 ) & & ( 10 く = b3 ) ) { } e [ se { i n i t ( ) テパッグが ひなた先生が教える 「ええと、先ほどの 3 項のド・モルガン則を適用して・・・リスト 7 のような感じです」 v リスト 7 3 項のド・モルガン則による書き換え i f ( ( bl く 10 & & b2 く 10 ) Ⅱ ( b3 く 10 ) ) { i n i t ( ) 冫 0 「うーん。確かに面倒です・・・」 「だろう ? こんな保守、やらされるほうにすればたまったものではない。 そもそも、これだけ形が違うと、コピべしてきてあることすら気付かないし、この 部分が前者の論理の否定形であることすら気付かない。よしんば気付いたとして も、誰でもこの書き換えをさらっとできるわけでもない。 リスト 2 が気持ち悪いからリスト 3 に書き換える " 単純化 " を Simple is Best だと か言いながらやってしまうなんてことは、プログラマの自己満足に過ぎない。改悪 の極みなんだ」 「かもしれません。しかし、それならば最初にこのソースを書くときにコピべしな いでこの条件式の部分を 1 つの関数として括り出すよう心がけるべきですね。 それが仮に不可能だとしても、コピペするならするで、コピペ元が修正されたときに その修正に同期してコピペ先の変更を忘れずにできるようドキュメンテーションに細 心の注意を払うべきだと思います」 194
第 9 回プログラミングのイディオム ( 前編 ) 「 1 0 の部分が n に置き換わるだけですね」 for(int i = 0 冫 i く n 冫 + + i ) d0 something(); 「このとき、ループ変数 i の取りうる値は ? 」 「ループの中では、 i は O から n - 1 ですね。で、ループを抜けるとき i が n になる ? 」 「うん、正解 ! 」 「でもふだんあんまりそういうの意識しないですね。もう、 n 回まわるループがそう だと思ってるので」 「うん、そうよね」 「そもそも、 i が O から n - 1 までで合計 n 回まわっているのですけれど、それがバッと 出てこないと思うんです。最初、この表現を見たときは、『あれ ? n - 1 回しか回って ないんじゃないの ? 』とか不安になりました」 「そのときは、どうやって n 回まわるループであることを確かめたの ? 」 「 n に小さな数字を入れて成り立つかどうかを試してみたことを覚えています。 たとえば n に 1 を入れて考えると『 i が O から n - 1 まで』っていうのは『 i が O から O ま で』っていう意味になって、ああ、ループ内では i は O を取って、 1 回は実行されて いるんだな、とわかります。 n に 2 を入れて考えると『 i が O から n - 1 まで』っていうのは『 i が O から 1 まで』っていう 意味になって、ループ内では i が O と 1 を取って、 2 回まわるんだなってわかります」 「うんうん。小さな数字を入れて試してみるのは良い方法ね ! ところで、 fi<n 』と いうのは『 i!=n 』ではダメなの ? 「 n 回まわるループにおいてはその 2 つの差異はありませんが、 '<' が 1 文字なのに 対して " ! = " は 2 文字ありますから文字のタイプ量で劣っています。また、『 + + i 』 が『 i + = 2 』のようになった場合に、 fi!=n 』だと正常にループが終了しなくなりま 163
第 13 回関数の返り値はどうあるべきか 臼を 「あっ ! ! これはこれは。ひなた先生。こ機嫌うるわしゅう」 早井は一瞬顔面蒼白になったが、すぐにニコニコ顔に戻った。 「うるわしくない ! 」 「これはまたどうされたんですか ? 」 「別に。どうもしないけど・・・。それより、早井君のほうこそ、最近、やけにケンイ チ君に親切じゃないの。どうしたの ? 」 名「そんなことないですよ」 「いや、そんなことは、ある」とケンイチは思った。最近の早井先輩はやたらと親切で、 このままだと「早井先輩が教えるデバッグが 1 , 024 倍早くなるテクニック」になりそうな 勢いだ。 「早井君のこと調べさせてもらったけど、なに、このふざけた名前。スティーブン・ 早井・出婆具 ? これ、偽名そのものでしよ。出婆具ってなに ? デバッグに掛けて るの ? デバッグが早いの ? だから早井出婆具なの ? とんだお笑いね」 「そ、、それは・・・」 0 「それに氏名だけでなく、年齢、住所、電話番号、出身校、職歴、すべてが嘘。あ なた、一体、誰なの ? 」 「まあ、いいわ。言いたくないのなら」 そう言うとひなた先生は去って行った。あんなに怖い顔つきのひなた先生をケンイチが 見るのは初めてだった。 ( つづく ) 259
第 15 回 バグを憎んで人を憎まず ケンイチは呆れ顔た。 「ち、違うんだ、ケンイチ。最後まで話を聞けい ! 」 「は、はい」 「その装置の実験も兼ねて試用したわけだが、その装置自体が失敗作だったんだ」 「どう失敗だったのですか ? 」 「データ転送が間に合わなくて書き込みに失敗することがあるんだ」 早井は真顔でそう言った。 「 CD - 日ですか・・・」 なんだかどこからどこまでが本当だかわからなくなってくるケンイチ。 「おかげで俺は一部の記憶を失ってしまった。自分の名前すら忘れてしまっていた。テ レビではスティーヴン・スピルバーグ監督がインタビューに出ていたので、俺は自分 の名前を勝手にスティーブン・早いデバッグ、さらにもじって、スティーブン・早井 出婆具と名付けた。 それがすべての始まりだった・・・」 「すべての始まりというか、そこで物語はすべて終わってそうですが・・・」 「ま、まあな」 もはやコーディングができないの巻 「ケンイチはプログラマなんだから、こんな嘘くさい身の上話よりも、プログラム のソースコードのほうがよほど真実に近いものが伝わってくるとは思わないか ? 」 「それはどうでしよう・・・」 293