私が設計を学ぶ理由

私は、1年と半年くらい前から設計の学習に力を入れている。そのせいか、私生活でコードを書くことがほとんどなくなった。設計の学習をするのは、「設計が楽しい」という理由もあるが、もっと現実的な理由がある。その理由は、コーディングではなくプログラミングがしたいからだ。

プログラミングとコーディングの違い

プログラミングとコーディングの違いはなんだろうか。私が思うに、明確に違ってように思える。それをはっきりさせておこう。 コーディングとは、そのままコードを書く行為を示す。電子機器上ではあるが、物理的なものだ。 コンピューターのプログラミングは、物事を行う手順を組み立ててコード上でそれを表現することだと思う。プログラミングは、大げさに言えば秩序を作る。これは概念的だ。プログラミングは、プログラムの始まりと終わりを決める。そして、その間に何をするのかを決める。

例えば、小学校の運動会はプログラムされている。小学校の運動会の実行計画をそのままプログラムと呼ぶ。最初に開会式を行い、幾つかの競技を順番に進めて、間に何回かの休憩時間を取りつつ、最後に閉会式で終わる。そういう風にプログラムされている。

では、私が行いたいことはどちらだ?コーディングか?プログラミングか? そして、私が普段、仕事で行うべきことはどちらだ?

そう考えた時、私の答えはどちらも「プログラミング」だった。

小学校の運動会のプログラムは、各学年の競技が効率よく行えるよう、考えられて計画されている。応援団のエール合戦が行なわれている裏では、次の玉入れの準備を進めている。準備のために動ける人数と時間が限られているからだ。 私が作るソフトウェアも、そうではなければならない。コンピュータのCPUとメモリ、ネットワークの帯域は限られている。それらを効率よく使わなければならない。ユーザーに無駄な作業をさせないように、画面遷移を考えなければならない。では、コンピュータプログラムの上で、「効率よく行えるよう考える」ことは何に当たるのか。それが設計なのではないだろうか。私はそう考えた。

設計の難しさ

設計は非常に難しい。私が感じている設計の難しさは3つある。1つめは、作成しようとしているソフトウェアに最も適切な設計を考える難しさだ。設計は考える人が10人いれば、10通りの設計が生まれる。設計には、絶対的な答えがない。設計による決定は、トレードオフが基本となるからだ。変化に対応出来る柔軟なソフトウェアは、ほとんどの場合、複雑になる。高速なソフトウェアは、CPUを占有していく。何を重要とし、何を諦めていくか。設計の過程では、このような選択がほとんどになる。

2つ目は、設計を開発中のコードに適用していく難しさだ。適用していく過程では、秩序を保ちつつ、時には柔軟に進化させながらコードを作成し、適用していく。非常に難しい作業だ。チームであれば、その難しさはさらに増す。

そして最後の3つ目は、必要となる知識の広さと深さに起因する難しさだ。おそらく、ほとんどの人はこれが理由で設計につまづき、興味を失っていく。初学者には、これはきつい。例えば、プログラミングであれば、コピーアンドペーストが初学者を助ける。コピーしてペーストすれば、とりあえず、なんだか動くものが出来上がる。コピーアンドペーストだとしても、「Hello,World」がディスプレイに表示されると、楽しくなってしまう。しかし、設計には、これに代わる仕組みがない。

初学者

大抵のプログラミングの初学者は、コピーアンドペーストを大量に行う。別に悪いと言っているわけではない。例えばJavaのコードであれば、コピーアンドペーストで、ある程度の恩恵を受けることができる。コピーアンドペーストしたコードの欠片が、何をやっているかはわからないが、とりあえずそれらしく動く。初心者であるうちは、まずコーディングの楽しさ、何ができるのかを学ぶ必要があるので、これはこれで良いと思う(仕事のコードであれば話は別)。そしていつか、コピーアンドペーストで痛い目を見る。そして、コピーアンドペーストしようとするコードの欠片が、一体何なのかを知ろうとする。それからだ。初学者はそこから、初学者を脱していく。ほとんどの人が、きっとそうだ。それまでは、暖かく見守っていきたい。こういった意味で、コピーアンドペーストによるコードの欠片は、初学者を助けている。初学者がコーディングへの興味を失わないように、とりあえず、先へ進めるようにしてくれる。動かないプログラミングなんて退屈すぎる。「Hello, World」をディスプレイに表示する前に、Importの仕組みなんて覚えなくて良い。おまじないというやつだ。初学者はそれでいい。コピーアンドペーストは、このように適度な恩恵を授けながら、時が経てば警告を与える役目を持つ。「お前もそろそろ初学者ではなくなる時期だよ」と、教えてくれる。

しかし、設計はそうはいかない。そもそも、設計はコピーアンドペーストできない。もちろん、コードの欠片をコピーアンドペーストすることは可能だ。しかし、設計としてはまるで意味がない。とある小学校の運動会のプログラムの一部を、他の小学校の運動会のプログラムの一部としてコピーアンドペーストしても、恩恵はほとんどないだろう。下手をすると、綱引きを2回やる羽目になるかもしれない。しかも連続でだ。

前述したように、設計とは、プログラムの始まりと終わりを決めて、その間の処理を効率的に実行するために計画する。その全体が設計となる。一部を切り取ったところで、その設計は死んでいる。 もちろん、個々の設計は存在する。例えば、GoFのデザインパターンは、個々の設計として機能する。クラスレベル、コードレベルの設計だからだ。それを理解した上で、コピーアンドペーストするのなら良い。しかし、全体的に手続き型で記述された10万行のメソッドで、突然Strategyパターンが出てきても、「ふーん」で終わる。むしろ、手続き型に慣れ親しんだ人からは「突然意味のわからないコードが出てきた」となってしまう。ソフトウェアとして全体が設計されていないプロジェクトに、突然、クラスレベルの設計が出てくれば、誰でも混乱する。そして嫌悪する。これがまずい。「デザインパターンは使えない」という印象を持つ。そしてそのメソッドのコードは20万行を目指していく。

設計は、ソフトウェア全体のスコープで考えるべきだ。これには、クラスレベルの設計、コードレベルの設計、ソフトウェアアーキテクチャをすべて含む。 そして設計はトレードオフだ。これは何も、CPUとメモリに限った話ではない。クラスレベル、コードレベルの設計同士のトレードオフも存在する。変更頻度が高い機能は、デザインパターンを適用し、柔軟にする。一方、変更頻度が低い安定した機能は、あえてハードコードに近いものにする。これにより、「安定した(枯れた)機能を、様々な機能が、様々な形式で利用する」という設計が行える。(例えば、データベースからの読み出し変わらないためSQLをハードコードするが、出力形式はCSVだったり、JSONだったり、独自の形式だったりする等)

これらの理由から、設計には広く、しかも深い知識と技術が必要となる。GoFのパターンを一つ覚えて一箇所だけ適用したところで、恩恵を受けることができない。むしろ邪魔になる。GoFに限らず、デザインパターンはトレードオフが存在する。その利益と不利益を把握し、どれを適用し、どれを適用しないかを選択し、全体として利益になるように組み立てていく。このため、設計者には、全体を把握できるほどのある一定以上のレベルが求められる。つまり、設計による恩恵を受けることができるまで、長い学習期間を耐えなければならない。

この3つの難しい理由だけなら、まだ「設計は難しい」というだけの話で済む。しかし、設計の難しさ3つ目の理由から、困った現象が起きる。「設計不要論」だ。生半可にかじった設計の技法を、ちょっと試してみた人が「こんなもの意味がない」と思ってしまうから、この論が生まれる。 ほぼ確実に、この「試した人」は設計の一部をコピーアンドペーストをしている。意味がないと考えるのも無理はない。そしてそこで学習を止める。設計を広く深く理解した人の設計提案を「ややこしいからやめろ」と言ってしまう。そしてメソッドのコードは30万行を目指す。これにはどうしたらよいのか、私は明確な対策がわからないままでいる。

結論

私は、設計を学んでいる。それは、私がプログラミングしたいからだ。しかし、設計は難しい。私は設計の妙を知る一歩を踏み出したにすぎない。私はもともと、コーディングが好きだ。より良いコードを書きたいと、常に思っている。そして設計を学ぶことで確実に良いコードが書けるようになると確信している。なぜなら、私は1年と半年くらいの間、私生活でコードをほとんど書いていないにもかかわらず、書くコードの質が変化したからだ。2年前のコードと比べると、今の私が書くコードは、意思を明確に表現している。複雑であるべきところは複雑であるという意思を表現し、単純であるべきところは単純であることを表現している。もちろん、それらはまだまだ拙い。ある程度マシになった程度にすぎない。しかし、この変化は嬉しく思う。これらは、新しい言語を覚えれば得られる類のものではない。設計は奥が深く、底なしのように見える。実際、底なしなのかもしれない。しかし、今の私は、設計を知ることで踏み出す次の一歩が楽しみで仕方がない。