コードの美しさについて

コードが綺麗とはどういうことか、の基準は人によって異なると思う。しかし例えば以下のような関数があまり綺麗ではないという気持ちは、共有できるのではないだろうか。

void func(int N, double*** v1, double*** v2, double** a, double** b, int* c, int* d, int* e, int f, int g, int h);

コードの場合、美しいとは、シンプルであることだ。見ただけですぐに何をしたいかがわかること、要素ごとに纏められていること、名前や型が適切に付けられて意図が伝わりやすいこと、スタイルが一貫していること、そして、可能なら、短いこと。 間違えようのない最小限のことを正しくこなすコードが相互作用しつつ大きく複雑なものになっているというのが理想的に思える。

構成要素をシンプルに保っていれば(そして、その構成要素に適切な名前がついていれば)、可読性、保守性、開発効率はどれも上がる。 小さく単純なものは理解しやすいので可読性が高い。可読性が高いものは多くの人が理解しやすいので修正もききやすい。当然理解しやすいものは書き足しやすいし、それ一つで完結しているものは切り出して他のところへ組み込みやすい。 非常に大雑把に言ってしまえば、そうなっているもののことを美しいコードと呼ぶのだ。

もちろん、複雑で難しいロジックをシンプルなものの組み合わせに落としこむのは難しい。簡単にできるようになるものではないし、十分な技術を持っていても設計に時間がかかることも少なくない。 単純化で根底にあるロジックの本質的な複雑さが魔法のように消え去ることはないし、だからこそシンプルにするのにも限界はある。しかも、その限界ラインの時点で既に非常に複雑なこともある。その見極めも難しい。 それに、書き始める前から完璧に設計することも難しい。最初の設計が上手く行くこともあるが、初めて書く種類のコードの場合、書きながらよりよい方法が見つかっていく場合がままある。 即座に結果が出る必要があるときは、なりふり構っていられないこともあるだろう。そしてこのご時世、結果は即座に要求される。つまり大抵の場合なりふり構っていられない。 だからこそ、汚いコードでも書き始めることを恐れてはならないし、同時に一度動いたコードを書き換えることも恐れてはならない。

動いたコードを書き換えることを恐れないで済むように、テストやバージョン管理システムがあるのだ。要求される挙動を全てテストに書いておけばコードを書き換えることへの恐怖はなくなる。 今まで人類が貯めてきた知見を活用していれば、書き換えるときに何かを間違えてもテストで発見できるし、バージョン管理システムで動いていた頃のコードと比較できる。 これらのツールは、今あるものを壊す勇気を与えてくれるものなのだ。

何度もいうが、綺麗なコードを書くのは難しい。複雑なものを単純なものの組み合わせに落としこむのは至難の業だ。 そして、いつも利益になるのはアウトプットなので、利益になれば裏側がどんなに汚くても平気、という人はたくさんいるだろう。 むしろそういう人の努力がサービスや技術の発達を加速しているのだろう。 だが、何度も何度も様々なところで言われている通り、汚いコードには後で必ずしっぺ返しが来る。 開発効率は最初は良くても、その後失速する。人が入れ替わるとブラックボックスになる。壊れるのが怖くて修正も出来ず、やがて緩やかに死んでいく。 たまに最初に全てをかなぐり捨てて滅茶苦茶なコードで動かし始めた後、メンテナンスが出来ずに拡張がままならないとか、最悪沈没していったという話を聞くことがある。

無論初めから綺麗なコードにこだわっていつまでも書き始めなかったり、商機を逃すというのは馬鹿らしい。 現実世界の業務では往々にして速度が要求されるし、生きていくには状況に応じて必要なものを全力で確保しなければならない。 だが、一度動いて余裕が出来たなら、今度はメンテナンスを始めなければならない。維持費用や改修費用を考えないのはビジネスの視点からも論外だろう。 「美しい」コードと言うから誤解されるのかも知れないが、プログラマはなにも他人から見て何も変化のない自己満足の改変を加えたいわけではないのだ。 もちろんプログラマは自分の書くコードを、長く使う上で愛着を持てる程度に綺麗で、人に見せるときに素晴らしいと言ってもらえてちょっと鼻を高くできるようなものにしたいと思っているのだが、彼らがそう思うコードは、大抵他のプログラマにも理解しやすく改修が容易になっている。つまりランニングコストが低くなっているのだ。 これは業務の上でも喜ばしいことなのではないか。プログラマに少し自由を与えれば、勝手に維持費用が下がっていくのだ。それ自体が初期費用を激増させるなら無謀だが、動き始めてからならよいことだ。

良きプログラマになるのは難しい。 そもそも複雑なロジックをコードで表現できるようになるまでが難しい。 効率のよいアルゴリズムや周辺技術を理解して適切なタイミングで使えるようにするのも難しい。 コードを適切に一般化したり、核の部分を抜き出して別の場所で使えるようにするのも難しい。 他のプログラマが書いたコードを読み、理解して、追加するのにも別のスキルが必要だ。 現代の技術の発展に思いを馳せるとイメージできるが、興味をプログラミングだけに絞ったとしても、学ぶことが非常に多い。 たったN日でプログラミングができるようになる、というような謳い文句は、複雑でないロジックを表現できるようになる、つまり門をくぐれる程度のところまでしか指していない。 無論それでも十分な進歩なのだが、門をくぐっただけでこの世界が終わりだと思われるとより奥深くで頑張っている人たちが困る、という話だ。

良きプログラマになるためには、コードを美しくする方法を無視することはできない。それは他のプログラマと協調し、長く使える自立したコードを書くための技術だからだ。 コードが属人的になってはならないし、そのためには一定以上の技術を持った人なら誰でもわかるようにすることが不可欠だ。 ここでいう技術は、「そのコードを読む技術」でなく、「一般に通じる技術」である。 業務で長く使うコードは他の同規模のプロジェクトに参加した経験がある人なら誰でも読めるようなコードであるべきで、それを成し遂げるための技術が「美しいコードを書く技術」なのである。 短期目標を達成するときはコードを綺麗にすることの効果は薄いが、それは負債を負っているだけだ。 実務ではこの技能を発揮すべきでないタイミングもあるが、発揮すべきタイミングもある。というか、あらゆる技能には発揮すべきときとすべきでない時がある。 発揮すべき時が意識されづらいスキルが軽視されやすいだけなのだ。 もしかするとお金を稼ぐために一番効率のよい方法は、スキル向上に時間を割かずにアドホックなコードを書き上げて負債を膨れ上げさせた後、すぐにプロジェクトを抜けて返済には関わらないようにすることなのかもしれないが、そういう人だけでは業務は回らない。

とまあ長々と御託を並べてきたわけだが、個人的には、綺麗なコードを書きたい理由は一点に尽きる。

私は自分の設計したものが美しくないことが我慢ならない。

それだけだ。