「#やってはいけないプログラマーのNG まとめというページがあって何気なく見たら、ちょっと首を捻るものもある」
「たとえばなんだい?」
「そうだな。一例をいくつかピックアップしてみよう」
- /* 後で直す */
- /* この変数は使わないけど消すと動かない */
- /* 警告が出るが問題ない */
- /* ここで例外は起きない */
- /* ヒャッハー!マジックナンバー最高だぜぇ!! */
- gets(buf)
「/* 後で直す */って問題があるだろ。問題があって修正が必要ならすぐ直さないとまずいだろ」
「いやいや。物事には軽重というものがあって、重度な問題と軽度な問題が両方あるとき、重度な問題から片付けないとならない」
「軽度な問題は後で直すことにしてもいいわけ?」
「重度な問題を放置するよりマシだ」
「具体的に分からないよ」
「メッセージに変換ミスで変な表記が入り込んでいるのが軽度な問題。ハングするのが重度な問題。メッセージが間違っていても、とりあえず動くことは動く。しかしハングしたら動いたとは言えない」
「でもさ。間違いは除去すべきだろ?」
「もちろんそうさ。その方が良いに決まっている。しかし、全ての処理をできる時間的ゆとりが常にあるとは限らない」
「だから、後で直すことが起きてしまうわけだね」
「そうだ」
「この変数は使わないけど消すと動かないってのはどうなんだよ。これって深刻なバグがあるって意味じゃないのか?」
「その通りだ」
「じゃあ、こんなコメントを入れないでバグを取るべきじゃないのか?」
「バグを取るためにこういうコメントが入るんだよ」
「意味分からないよ」
「この手のバグはC言語等ではよくあるのだが、たいていは原因が良く分からない深刻なバグになる。バグ取りは長期戦になる。分かったヒントはコメントとして埋め込んでおく価値がある。一週間後にそれが意味を持つこともあるが、その時まで関係者が覚えている保証は無いからね」
「そうか。この変数は使わないけど消すと動かないってコメントはバグ取りのヒントなんだね」
「そういう意味でこういうヒントを入れるケースもある。まあプログラミング言語によるけどな」
「警告が出るが問題ないってのは?」
「警告というには、潜在的なバグの可能性を指摘してくれるもので、できるだけ無視しないことが望ましい。警告が出ないようにソースを修正することが望ましい。しかし、希に警告を回避できない場合がある」
「たとえば?」
「Obsoleteを付けた機能を互換のために呼び出す場合などだな。使って欲しくないからObsoleteが付いているが、互換機能を提供するコードは使って欲しくないコードを呼ぶ必要が生じることがある」
「そうか」
「そういう場合は、#pragmaなどをソースに埋め込んで警告をそこだけ抑止するのだが、処理系によってそのような機能が提供されないこともある。最終手段としてはありだな」
「じゃあ、 ここで例外は起きないっていうのは?」
「事前にバリデーション処理が走っている場合は、例外が起きない前提で処理が進む場合もある。もちろん異常ケースで例外はあるだろうが、それはバグだからまた別の問題だ」
「実際に経験があるの?」
「うん。たとえばさ。文字列を構成する文字が全て"0-9"だと確認された後で、数値に変換するコードを書いたことがある。そこで、書式例外をキャッチしていないのは事前にチェック済みだからだ。もし例外が起きたらバグなので、キャッチしないで素直にプログラムを止めて報告させた方がいい」
「でも、分かりにくいね」
「だから今はTryParseという便利なメソッドがあって、書式間違いで例外を投げないコードを書くぞ」
「C#の話だよ」
「厳密には.NET Frameworkの話だよ」
「ぎゃふん。じゃ、マジックナンバーは?」
「/* ヒャッハー!マジックナンバー最高だぜぇ!! */なんてコメントを入れてる暇があれば定数を1つ定義しろ、と言いたいのも事実だが、出現回数が少なく値が自明なら直接マジックナンバーを埋め込むことも間違いとまでは言えない」
「何もかもいちいち定義したら手間が爆発しちゃうかもしれないってことだね」
「EXEファイルフォーマットの先頭の"MZ"とか、修正する必要が生じる可能性もほぼ皆無だ。直接埋め込んでもあまり害は無いだろうし、知ってる人なら説明を読まずとも理解できる。知らない人はそもそもMZの意味を説明されても分からないかもしれない」
「じゃあ、gets(buf)は?」
「バッファのサイズを指定する引数が存在しないので、容易にメモリ破壊を引き起こすので、『サイバーテロリストさんWELCOME』となっちゃう可能性がある」
「じゃあ、NGでいいじゃん」
「そこは見方が逆なんだよ」
「えっ?」
「gets(buf)がNGだという意見は、gets(buf)を書けば通る環境に生きていることを意味するが、セキュリティ的な安全も意味を持つ環境に生きていることを示す」
「それがどうしたの?」
「つまりさ。C/C++みたいなセキュリティ的なザルを使っている時点で、それがNGだろと突っ込めるわけだ」
「ぎゃふん」
感想 §
「それで君の全般的な感想は?」
「やはり暗黙の上でC言語を想定した意見が散見されるのが気になるな」
「どうしてC言語だとダメなの?」
「もっと新しい言語だと最初からできないようになっている様々な問題が、C言語ではNG扱いになるからだ。つまり、話題に互換性がない」
「じゃあ、C言語ネタそのものがNGってこと?」
「それを語る連中もな」
「落とし穴の隣で作業をするなってことだね」
「そうだ。安全を重視する人なら、そんな場所で作業はしない。それでも作業したら落ちても自業自得だ。その場合のNGは穴に落ちることではなく、穴の近くで作業したことだ」
「分かったぞ。Cという文字は穴が空いてるんだ。Oという文字なら空いてない。C言語よりO言語を使え!」
「なんか違うぞ」
「えー」