プログラムと美しさ：第二章　見た目と冗長性　―コピペの呪い―

～ プログラミングって面白そうと思った方に向けた連載エッセイ ～

　美しいソースコードは、五メートル離れて見ても美しいとわかる。プログラムを知らない方でも、ぱっと見で美しいか醜いかは何となく直感できるだろう。その直感はあながち外れていないかもしれない。とは言え、プログラムならではの美的基準も存在するので、その点については解説が必要だろう。

　たとえば次の文章を見ていただきたい。

> 私の会員番号は1119071111である。
> フレドリックの会員番号は1111907111である。

　私とフレドリックの番号が似ている。ひょっとして重複していないだろうか。

　位置を合わせてみよう。

> 私＿＿＿＿＿の会員番号は1119071111である。
> フレドリックの会員番号は1111907111である。

　これでわかった。並びは似ているが桁の位置がずれている。同じ部分の位置を揃えることで違いが明瞭になった。後述のとおり、あくまで一面的な見方ではあるが、後の文の方がプログラムとして美しいと言うことができる。なぜか。より解読しやすく、バグ（プログラムの不具合）を検出しやすいからだ。最初の文もよく見れば違いはわかるだろう。だが、ぱっと見でわかるということと、よく見ればわかるということは、実益上はまったく違うことである。

　だから常に位置を揃えるべき、ということでないのは申し添えておきたい。メリットは総合的に考える必要がある。開発効率の観点からは「いちいち揃えていたら時間がもったいない」、保守性の観点からは「より長い名前の会員を追加したら位置を揃え直さなければいけない」、統一性の観点からは「一部のプログラマだけがそのようなスタイルで記述すると全体として汚くなる」といった、それぞれもっともな反論が想定される。純粋に美的観点から「余白が気持ち悪い」との異論が唱えられることもあろう。ここではあくまで一つの側面から見た視覚効果の例として挙げた。

　では、次はどうだろう。

> もし今日の午前中晴れていたら今日の午前中は公園で遊ぶし、もし今日の午前中雨が降ったら今日の午前中は家で将棋を指す。
> もし明日の午後晴れていたら明日の午後は川で泳ぐし、もし明日の午後雨が降ったら今日の午後中は家で本を読む。

　読みづらい。ぱっと見で同じ句が繰り返し使われているのがわかる。悪文である。これを美しいと感じる方はあまりいないだろう。経験を積んだプログラマは、このような記述にさらに不吉な匂いを感じ取る。

　一つ目の文は、冗長だが意味はおかしくないようだ。二つ目の文はどうだろう。改行して位置を揃えてみよう。

> もし
> 明日の午後晴れていたら
> 明日の午後は川で泳ぐし、
> もし
> 明日の午後雨が降ったら
> 今日の午後中は家で本を読む。

　見つかった。最後が「明日」でなく「今日」になっている。それだけではない。続いて「午後」と書くべきところ、「午後中」と書いてしまっている。バグである。

　なぜこんなことになってしまったのだろう。

　二つ目の文は、一つ目の文をコピー＆ペースト、つまり「コピペ」して、必要な個所だけ書き換えた。つもりでいたのに書き換え漏れと誤記があった。

　この「コピペ」は、実はプログラミングの世界で代表的なアンチパターン（避けるべき悪習）とされている。

　なぜコピペがよくないのか。

　第一に、今例に挙げたような間違いが起こりやすい。コピペするときには、必要な個所を正しく変更する自信がある。でなければしようと思わないだろう。とは言え過信してはいけないので、変更作業には慎重を期す。後で見直しも忘れない。ふぅ、これで大丈夫だ。

　それでも間違いが起こるのである。百回コピペして一回も間違いを犯さない人は、相当に優秀なコピペマスターと言えるだろう。たいていの人は間違える。見落としは人間につきものだ。貼り付けて編集しようとしたところで電話がかかってくることもあるだろう。上司の小言に五分間耐えた後、脳の状態を元に戻せる人を私は知らない。コピペは間違いを生む宿命にある。

　第二に、変更が困難になる。プログラミングには "DRY" というよく知られた原則がある。"Don't repeat yourself" の略である。簡単に言うと、重複を避けろ、ということだ。同じことを実現するコードがあちこちに散在していると、その部分に変更の必要が生じたとき、すべての箇所を同じように変更しなければならなくなる。手間であると同時に、変更漏れのリスクが出てくる。保守性が著しく損われてしまう。

　たいていのプログラミング言語には、類似するコードを一つにまとめるための仕組みがいくつか用意されている。それらを適切に活用すれば、重複を避けることが可能である。コピペできるということは、共通する部分を単一のコードに抽出することができるということなのだ。

　第三に、可読性を害する。ここでいう可読性とは、上から下へ順番に読んでいくときの読みやすさだけでなく、解析のしやすさも含んでいる。二つのそっくりなコードがあるとしよう。まったく同じかもしれないし、一語だけ違うのかもしれない。それを正確に見極めるのは、人間の目には酷な仕事である。コピペ頼りのコーディングは、冗長にもなりやすい。不必要に長いコードより短いコードの方が理解しやすいのは言うまでもない。

　文章の場合なら、あえて同じ内容でも重複して記述することが読み手のためになることもあるだろう。たとえば、料理本の「ボロネーゼの作り方」という項に、ところどころ「詳しくは『ペペロンチーノの作り方』を参照されたい」とあったら、きっと読みづらいし作りづらい。しかし書き手側としては、パスタを茹でる際の注意について何度も同じことを書くのは面倒だし、ほかにも注意すべき点があったと気づいた場合、すべての箇所にそれを追記するのは煩わしい。そこで実用本には〈基本編〉あるいは〈共通編〉という章が設けられ、全体に共通する基礎的な事項がまとめて説明されていることがある。このような「共通化」は、プログラムにおいても重複除去の主要な手法として有効に活用されている。

　コピペしてできた重複コードは「コードクローン」とも呼ばれる。その割合が多くなるほどプログラムは汚くなり、保守性が悪化する。無論、少ない方が望ましい。では、コードクローンはなぜなくならないのか。

　コピペで作るのが楽だからである。しかし、プログラムの世界では、先に楽をするとたいてい後で苦労をする。後で楽をするためにはどんな苦労も厭わない、極端に言えばそんな姿勢がよいプログラムの素地となる。わかっていながら、コードクローンは今日も量産される。なぜか。楽だからである。

　いや、実はそれだけではないのだが、続きは後の章に譲ることにして、本題へ戻りたい。

　いったん書式を整理することで誤りが見つかった。では次に、冗長性を排してわかりやすく書き換えてみよう。

> 今日の午前中、もし晴れていたら公園で遊ぶし、雨が降ったら家で将棋を指す。
> 明日の午後、　もし晴れていたら川で泳ぐし、　雨が降ったら家で本を読む。

　短くなった。簡素にまとまった。人間の頭は複雑さに弱い。意味の解読にかかる時間もかなり短縮されたはずだ。誤記も修正された。同じ句の繰り返しが少ない分、間違いが少なくなるし、もし間違いがあっても気づきやすくなる。見た目の美しさが実利に資する例である。

　見た目の悪いコードは信頼性も怪しい。その直感は当たっていることが多い。品質に対するプログラマの心構えの低さが表れたという解釈もできるが、誤りを発見づらいという実際的な問題もそこには存在している。たとえば冗長なコードは見た目が悪い。そしてそこには誤りの潜んでいる可能性が高い。ということがこの章でわかっていただけたと思う。

　ただし、書き手も読み手も形式的な見た目の美しさに信頼を置きすぎてはいけない。ただ整然と並んでいるだけでは美しいソースコードと呼ぶのに十分ではない。効率性、保守性、拡張性といった実質的な特性が、より重要な要素として美しさを形成するのである。

　さらに読み進めていただきたい。

---

[序章](https://qiita.com/CodeOne/items/01b4e49a7d5a84d48c71)
[第一章　その美の特徴](https://qiita.com/CodeOne/items/1969ec81d04529fbdb34)
第二章　見た目と冗長性
[第三章　ロジック](https://qiita.com/CodeOne/items/3009027a2f8b892e2b6b)
[第四章　命名](https://qiita.com/CodeOne/items/dfc3ace22c46273dc22c)
[第五章　アーキテクチャ](https://qiita.com/CodeOne/items/469b9f421e5d914f1ffb)
[第六章　リファクタリング](https://qiita.com/CodeOne/items/df50fad6bb0bd2f0096f)
[第七章　デザインパターン](https://qiita.com/CodeOne/items/0ac628d6be24328ecc10)
[第八章　正規化](https://qiita.com/CodeOne/items/5df2a5e38cc4c1c90a7a)
[終章](https://qiita.com/CodeOne/items/12ad8d54329bc946b85c)