プログラミングを学ぶ上で私は比較的優等生を走っている。
周囲の人の中には変数の使い方、設定方法がよくわからない、という人もいるので、せめてもの助けになればと思って変数の解説を書こうと思ったらなんか変なストーリーになったけどまぁいいや。ブログに載せておこう。
以下、そのときの記述をそのまま。
宋に狙公なる者有り
宋の国に狙公という猿好きの老人がおりました。彼は、一人のプログラマを雇っておりまして、このプログラマはなかなか優秀な若者でありました。彼は「猿飼育プログラム」というプログラムを組み、それによって狙公の飼っている大勢の猿たちの世話を適確にこなしていました。
さてある日のこと、彼は「猿飼育プログラム」に一つの機能を追加実装することにしました。名付けて「猿に芋機能」です。追加する部分のフローチャートを抜き出してみると、こんな感じです。【図001】
「猿に芋をやる」この上なくシンプルな機能です。ボタンを押すと芋が1個、猿の檻の中に転がり出る仕組みです。狙公は喜びました。
しかし喜びは長くは続きません。狙公はじきにこう言いました。「猿どもがもっと欲しい、もっと欲しいとせがむので、結局何回もボタンを押す羽目になっている。一度ボタンを押したら3つ芋が出るように改良してくれ」
最初、プログラマは以下のフローチャートを検討しました。【図002】
「だめだだめだだめだ。こんな腐った設計があるもんか」とプログラマは吐き捨てるように言いました。あなたは「それのどこが悪いの?」と不思議に思うかもしれません。しかし、プログラマは気むずかしい生き物です。彼らにはいくつかの不文律があります。「同じ文字を2度書かない」というのもそれです。彼らは、同じ文字を2度コード内に書くのは冗長でだらしない、という考え方をするようなのです。できるだけコードをコンパクトにまとめようとします。
しばらく考えて、彼はリテラルを導入することにしました。【図003】
<
「どんなもんだ、やればできるんだ」彼は得意満面です。たしかにこれなら、同じ語句を繰り返すことなくすっきりしています。
ところがしばらくすると、狙公は猿に与える数を5個にする、と言い始めました。この時になって、面倒が持ち上がります。プログラムの中の「3個」を「5個」にすればいいだけなのですが、「猿飼育プログラム」全体は膨大な量になっており、どこに「3個」と書いたのだか、見つけるのが一苦労です。リテラルは、後から探すのが大変なのです。
そこで彼はまた狙公が変更するかもしれないから……と定数を使うことにしました。【図004】
こうして定数「saru_imo」にしておけば、後から追跡が可能です。変更も宣言部で5を3にするだけ。これならもう大丈夫……かと思いきや。
狙公「猿にやるのがいつも5個では融通が利かん。数を変更できるようにできんかな」
主人の言うことを実現するのがプログラマ。彼はしょうがないので変数を導入することにします。【図005】
キーボードから入力することで芋の数をいつでも変更できるようになりました。これで狙公も満足するでしょう。
しかしここで終わっては故事成語になりません。狙公は今度は「朝には3個、夜には4個芋をやりたい」と言い出しました。if文を使えばわけないことです。【図006】
「朝3個夜4個」と数字まで仕様要求に書いてあるんだから、キーボードから入れる必要はないだろう、と判断して、変数にはリテラルを代入することにしました。でもまぁこれを読んでいる皆さんは、ほら、朝三暮四って知ってるでしょう。
お察しの通り、狙公は「猿が文句を言うから、朝4個夜3個にするわ」と言ってきました。猿がお前の主人なのか? 俺の主人は猿以下か? 言い返したい気持ちをぐっとこらえてこそのサラリーマンです。プログラマは考えました。このジジイ、どうせまた何か気まぐれで変更するに違いない。先手を打って、リテラルを変数にしといた方がよさそうだ(定数でもいいけどね)。朝の数と夜の数を変数にしちゃおう。【図007】
変数が3つに増えました。これで狙公が朝の数をいくつに変更しようとも、宣言部を書き換えるだけで済みます。楽勝楽勝。誰もがこれで終わりだと思ったことでしょう。しかしバカは常に予想外の事件を引き起こすものです。
狙公「日付によって与える芋の数を変えたいんじゃ。 五十日 (5や10がつく日)には朝の芋を5個夜の芋は2個。4のつく日は朝1個で夜6個。あと25日は給料日だからお祝いで朝5個夜5個」
もう呆れてものが言えませんが、この仕様要求は面倒です。日によって与える数を変えたい……だと? プログラマはついに配列に手を出すことに決めました。【図008】
0〜30までの31個の配列を朝と夜、それぞれに用意します。それぞれ日付に対応した「芋の数」を記録しておいて、呼び出してくれば与える芋の数がわかります。31個の芋の数を決めるのは狙公にやらせればいいでしょう。
こうして、プログラマは「猿に芋機能」を極めることができ、名人の名をほしいままにしたのですが、猿の言いなりになっていた狙公は勢い衰え、ある日突然突然変異によって高い知能を持つように進化した猿たちの反乱に遭って滅びてしまいました。プログラマの行方は誰も知らない。長いこと旅に出て反乱のことを知らなかった旅人が、長旅から戻ってきて崩壊した自由の女神像を前にここが故郷だとわかって呆然とするのは映画史上に残るネタバレ禁止事項なわけですが、さすがにもう時効でしょう。
時はかわって、21世紀。あなたは凄腕のプログラマです。あなたのところに今日もやっかいな依頼が舞い込みます。「猿に芋をやる機能を実装して欲しい」そう言われたら、あなたはどのように変数設計をしますか?
- 【図001】男は黙って芋をやる
- 【図002】何度でも芋をやる
- 【図003】リテラルで一行処理
- 【図004】定数で爽やかに
- 【図005】1変数でキーボード入力
- 【図006】1変数で代入
- 【図007】3変数で細やかに設計
- 【図008】配列でバリバリ
どの設計をしても間違いというわけではありません。与えられたシチュエーションによります。ただ、一般に前提なしに訊かれたら、プログラマは【図005】〜【図007】辺りを想定するだろうと思います。私はまぁ【図005】〜【図006】辺りで手を打ちます。参考になりますでしょうか。
変数の設計を入出力の観点から整理
これは役に立つかどうかよくわかりませんが、利用する変数を、いくつかのグループに分けるとすると、「入力側」「設計上必要なもの」「出力側」に分けることができそうな気がします。
仮に、占いのプログラムに必要そうな変数を考えてみます。
入力側は「これを訊かないと占いが始まらないでしょ」というパラメータです。水道料金シミュレーションなら「水道の使用量」ですし、動物園の料金なら「入場者数」ということになります。
出力側は「結果として何を見せたいか」です。出力側は計算式の結果をそのまま出力することもできたりするので(document.write(hensuu*2+1)など)、必ず出力用の変数が必要というわけではないのですが、一応候補にはなります。
演算中に必要な変数というのが一番わかりづらい部分で、これは実際、手を動かしてフローチャートを書きながら整理していくことが多いです。計算に必要な前提情報(kihonkin、per1Lなど)、制御に必要なカウンター変数、などがあります。
こうした整理も念頭に、考えてみてはいかがでしょうか。
おまけ
今回フローチャートを描くのにはyEd Graph Editorを使いました。
フローチャートに特化したソフトで、MacでもWindowsでも使えます。英語のソフトですが、非常に使いやすくて便利です。このソフト自体はJavaで描かれているようです。
今回は以上です。ご静聴ありがとうございました。