プログラムと美 序章  コンピュータは優れた計算能力を持っているが、言われなければ何もしない。コンピュータを動かすための命令を記述したものをプログラムという。それを組む作業がプログラミング、組む人がプログラマである。ウィンドウズやエクセル、iPhone アプリといったソフトウェアは、どれもプログラムでできている。  プログラマは、人間とコンピュータの橋渡しとなるプログラミング言語を使って命令を記述する。記述された命令から成るテキストは「ソースコード」、あるいは単に「コード」と呼ばれる。ソースコードはコンピュータが理解できる言葉に翻訳され、実行に移される。翻訳を行うのはコンパイラやインタープリタと呼ばれる特殊なプログラムである。  プログラムには、「こう動きなさい」「次にこうしなさい」「こういうときはこうしなさい」といったことが綿々と綴られている。「そうなったとき」のケースをあらかじめ洗い出し、どうするかを決めて書いておくのである。  プログラムを渡されたコンピュータは、盲目的な従順さでそれを実行に移す。余計な気を利かせることは一切ない。「雨天中止」とそこに書いていなければ、嵐でも運動会は決行される。想定外の動きをしたら、それは不具合である。あるいは単に想定漏れという。「どうするか」には、ユーザーに判断を求めたり、データベースから過去の成功事例を参照することも含まれる。学習・推論を行うプログラムも今では一般的だが、究極的な仕組みは変わらない。結果は状況に応じた非決定的なものであっても、それを導き出すロジック自体は、あらかじめ与えられたとおりの決定的なものである。  硬い。融通が利かない。面白みがない。  コンピュータやプログラムがそうであるならば、それを相手にするプログラマも思考に柔軟性を欠く人が多いのではないか。感情よりも論理を優先する傾向が強そうだ。プログラミングの現場というのはきっと、数値化できるメリットのないものは容赦なく無駄と切り捨てる、ゴリゴリの実利至上主義社会なのだろう。  そう推測する方も少なからずおられると思う。  しかしそのプログラミングの現場で、しばしば「美しい」という言葉が違和感なく発せられ、最上級の褒め言葉として歓迎されるのはどういうわけだろう。  美的要素など邪魔にしかならないのではないか。  念のために添えておくと、ここで取り上げる「美しい」は、ソフトウェアを動かしたときに表示される画面の美しさのことではない。プログラムの美しさと画面の美しさに直接の関連性はないと言ってよい。見た目は美しいけれど中身はぐちゃぐちゃ、というケースは決して珍しくない。  プログラムとは、第一義的にはコンピュータに指示を与えるものである。そして、指示を受けるコンピュータは美しさを解さない。どんなに汚いプログラムだろうと、命令が正確に記述されてさえいれば正しく動作する。だが、プログラムには別の側面もある。  プログラムを読むのはコンピュータだけではない。人間も読むのだ。人間とは他人であり、ときに未来の自分である。作成中にも読み返すし、リリース後も調査の必要があれば読む。不具合があれば修正するし、機能追加があれば再利用が検討される。書かれたプログラムは、人間によって繰り返し見られ、変更され、利用される運命にある。  ここに美しさの意義が生まれてくる。  実際、プログラミングにおいて美しさは、邪魔などころか価値がある、それどころか重要である、品質を確保するには不可欠でさえあるとされている。  プログラムにとって美とは、少なくとも縁遠い存在ではないのである。もちろんプログラミングは芸術ではない。技術である。その「美」は絵画や音楽における「美」とは性質も基準も異なるものだろう。しかし「アート」の語源は技術であるというから、その語源に却って技術に宿る美しさに目を向けてみるのも、あながち無駄とは言えまい。  人間的行為の代表格である美術とは一見対極にあるコンピュータ・プログラムの世界。そんなところにも美が存在し、広く価値を認められている。美術について門外漢の私が美について語るのはおこがましいことではあるが、その点はご寛容を賜り、あまり表に出ることのないプログラムの世界を、ちょっと覗いてみるつもりで気楽に読んでいただければ幸いである。なお、読み進めるにあたってプログラムの知識は必要ない。例として挙げるのは普通の日本語である。 第一章 その美の特徴  先ほど画面の美しさとプログラムの美しさには直接の関連性はないと書いた。プログラミング経験のない方には理解しづらい点だろう。個別のトピックに触れる前に、この点について補足しつつ、プログラムにおける美の特徴について、簡単に整理しておきたい。  ソフトウェア開発において、プログラミングと画面デザインは分業されることが多い。設計者やデザイナが図やプロトタイプ(模型)に表したものを、プログラマがプログラムに組み込んでいくのである。画面の美しさは、基本的には元のデザインによって決まる。表示するためのプログラム構造が汚いからといって画面が汚くなるわけではない。どんな組み込み方をしようと、プログラマに目的を達成する意思と時間があれば、デザインの美しさを画面に再現することは概ね可能である。  規模が小さいソフトウェアや画面デザインの優先度が低い業務ソフトウェアでは、プログラマがデザイナを兼ねることも少なくない。しかし、プログラミングとデザインは基本的に別の根を持つスキルである。優れたプログラマが優れたデザインセンスを持っているとは限らない。バランスの悪い配色やメリハリに欠けた配置のせいで、中身のプログラムも同じだろうと推し量られ、ソフトウェア全体の品質が低く評価されてしまうことがあるのは、何とももったいない話である。  画面デザインはユーザーに直接触れるもので、その美しさは操作性とあわせて評価される。一般にデザインの役割は強調、関連といった意味づけであろうから、意図を明解に伝えられたとき、それを美しいというのかもしれない。  画面デザインとプログラムはソフトウェアの価値としては一体のものであるが、美しさの基準や効用にはかなりの違いがある。両者を一緒くたに扱うと、プログラムそれ自体における美が不明瞭になるおそれがあるため、ここではプログラムの美に画面デザインの美しさは含めないことにして、以降の文を進めさせていただく。  プログラムの美しさは、通常、ソフトウェアの外観には表れない。「美しいプログラムでできています」と訴えても人々の心に響くことは期待できないので、セールスポイントに挙がることもまずないだろう。ユーザーに及ぼす影響は実は小さくないのだが、それはあくまで間接的なものである。  では、プログラムにおいて美は、具体的にどこに存在するのだろうか。  プログラムの美には目的がある。目的とは、品質、生産性の向上である。少なくとも建前上は、実利に資する美なのである。  プログラマにとってプログラムは、ほかのプログラマや未来の自分とのコミュニケーション手段でもある。美しいプログラムは簡潔・明瞭である。その意図がスムーズに伝達されるため、作業のロスが少ない。無駄なく整理されているため、変更や拡張も容易である。  プログラムにおいて「美しい」は「正しい」という意味も含んでいる。想定漏れだらけで許されるなら、いかほどでも短く書けるだろうが、それを美しいとは言わない。どれだけきれいに整理されたソースコードでも、品評会に出したいくらい均整のとれたアーキテクチャでも、処理効率が悪ければ美しくない。逆も然りで、バランスが大事なのである。  以下、こうした目的にも触れながら、プログラムに存在する美について具体的に見ていきたい。 第二章 見た目  美しいソースコードは、五メートル離れて見ても美しいとわかる。プログラムを知らない方でも、ぱっと見で美しいか醜いかは何となく直感できるだろう。その直感はあながち外れていないかもしれない。とは言え、プログラムならではの美的基準も存在するので、その点については解説が必要だろう。  たとえば次の文章を見ていただきたい。   私の会員番号は1111907111である。   フレドリックの会員番号は11119071111である。  私とフレドリックの番号が似ている。ひょっとして同じになっていないだろうか。  位置を合わせてみよう。   私     の会員番号は1111907111である。   フレドリックの会員番号は1111190711である。  これでわかった。並びは似ているが桁の位置がずれている。同じ部分の位置を揃えることで違いが明瞭になった。後述のとおり、あくまで一面的な見方ではあるが、後の文の方がプログラムとして美しいと言うことができる。なぜか。より解読しやすく、バグ(プログラムの不具合)を検出しやすいからだ。最初の文もよく見れば違いはわかるだろう。だが、ぱっと見でわかるということと、よく見ればわかるということは、実益上は全然違うことである。  だから常に位置を揃えるべき、ということでないのは申し添えておきたい。メリットは総合的に考える必要がある。開発効率の観点からは「いちいち揃えていたら時間がもったいない」、保守性の観点からは「より長い名前の会員を追加したら位置を揃え直さなければいけない」、統一性の観点からは「一部のプログラマだけがそのようなスタイルで記述すると全体として汚くなる」といった、それぞれもっともな反論が想定される。純粋に美的観点から「余白が気持ち悪い」との異論が唱えられることもあるだろう。ここではあくまで一つの側面から見た視覚効果の例として挙げた。  では、次はどうだろう。   もし今日の午前中晴れていたら今日の午前中は公園で遊ぶし、もし今日の午前中雨が降ったら今日の午前中は家で将棋を指す。   もし明日の午後晴れていたら明日の午後は川で泳ぐし、もし明日の午後雨が降ったら今日の牛後は家で本を読む。    読みづらい。ぱっと見で同じ句が繰り返し使われているのがわかる。悪文である。これを美しいと感じる方はあまりいないだろう。経験を積んだプログラマは、このような記述にさらに不吉な匂いを感じ取る。  一つ目の文は、冗長だが意味はおかしくないようだ。二つ目の文はどうだろう。改行して位置を揃えてみよう。   もし   明日の午後晴れていたら   明日の午後は川で泳ぐし、   もし   明日の午後雨が降ったら   今日の牛後は家で本を読む。  見つかった。最後が「今日」になってしまっている。それだけではない。続いて「午後」と書くべきところ、「牛後」と書いてしまっている。バグである。  なぜこんなことになってしまったのだろう。  二つ目の文は、一つ目の文をコピー&ペースト、つまり「コピペ」して、必要な個所だけ書き換えた。つもりでいたのに書き換え漏れと誤記があった。  この「コピペ」は、実はプログラミングの世界で代表的なアンチパターン(避けるべき悪習)とされている。  なぜコピペがよくないのか。  第一に、今例に挙げたような間違いが起こりやすい。コピペするときには、必要な個所を正しく変更する自信がある。でなければしようと思わないだろう。とは言え過信してはいけないので、変更作業には慎重を期す。後で見直しも忘れない。ふー、これで大丈夫だ。  それでも間違いが起こるのである。百回コピペして一回も間違いを犯さない人は、相当に優秀なコピペマスターと言えるだろう。たいていの人は間違える。見落としは人間につきものだ。貼り付けて編集しようとしたところで電話がかかってくることもあるだろう。上司の小言に五分間耐えた後、脳の状態を元に戻せる人を私は知らない。コピペは間違いを生む宿命にある。  第二に、変更が困難になる。プログラミングには "DRY" というよく知られた原則がある。"Don't repeat yourself" の略である。簡単に言うと、重複を避けろ、ということだ。同じことを実現するコードがあちこちに散在していると、その部分に変更の必要が生じたとき、すべての箇所を同じように変更しなければならなくなる。手間であると同時に、変更漏れのリスクが出てくる。保守性が著しく損われてしまう。  たいていのプログラミング言語には、類似するコードを一つにまとめるための仕組みがいくつか用意されている。それらを適切に活用すれば、重複を避けることが可能である。コピペできるということは、共通する部分を単一のコードに抽出することができるということなのだ。  第三に、可読性を害する。ここでいう可読性とは、上から下へ順番に読んでいくときの読みやすさだけでなく、解析のしやすさも含んでいる。二つのそっくりなコードがあるとしよう。まったく同じかもしれないし、一語だけ違うのかもしれない。それを正確に見極めるのは、人間の目には酷な仕事である。コピペ頼りのコーディングは、冗長にもなりやすい。不必要に長いコードより短いコードの方が理解しやすいのは言うまでもない。  文章の場合なら、あえて同じ内容でも重複して記述することが読み手のためになることもあるだろう。たとえば、料理本の「ボロネーゼの作り方」という項に、ところどころ「詳しくは『ジェノベーゼの作り方』を参照されたい」とあったら、きっと読みづらいし作りづらい。しかし書き手側としては、パスタを茹でる際の注意について何度も同じことを書くのは面倒だし、もう一つ注意すべき点があることに気づいた場合、すべての箇所にそれを追記するのは煩わしい。実用本には〈基本編〉あるいは〈共通編〉という章が設けられ、全体に共通する基礎的な事項がまとめて説明されていることがある。このような「共通化」は、プログラムにおいても重複除去の主要な手法として有効に活用されている。  コピペしてできた重複コードは「コードクローン」とも呼ばれる。その割合が多くなるほどプログラムは汚くなり、保守性が悪化する。無論、少ない方が望ましい。では、コードクローンはなぜなくならないのか。  コピペで作るのが楽だからである。しかし、プログラムの世界では、先に楽をするとたいてい後で苦労をする。後で楽をするためにはどんな苦労も厭わない、極端に言えばそんな姿勢がよいプログラムの素地となる。わかっていながら、コードクローンは今日も量産される。なぜか。楽だからである。  いや、実はそれだけではないのだが、続きは後の章に譲ることにして、本題へ戻りたい。  いったん書式を整理することで誤りが見つかった。では次に、冗長性を排してわかりやすく書き換えてみよう。   今日の午前中、もし晴れていたら公園で遊ぶし、雨が降ったら家で将棋を指す。   明日の午後、もし晴れていたら川で泳ぐし、雨が降ったら家で本を読む。  短くなった。簡素にまとまった。人間の頭は複雑さに弱い。意味の解読にかかる時間もかなり短縮されたはずだ。誤記も修正された。同じ句の繰り返しが少ない分、間違いが少なくなるし、もし間違いがあっても気づきやすくなる。見た目の美しさが実利に資する例である。  書き手も読み手も、形式的な見た目の美しさに信頼を置きすぎてはいけない。几帳面な性格のプログラマは、ソースコードを書くにあたっても几帳面にインデントや改行、空白といった体裁を整える。それはほかのプログラマへのマナーという意味で大事なことだが、整然と並んでいるだけでは、美しいソースコードと呼ぶには十分でない。無駄のない簡素な記述、解読・変更の容易性が、より重要な要素として美しさを形成する。 第三章 ロジック  どんな論理、手法、手順で組み立てられているか。一般的にプログラムの美しさというと、これを指すことが多いかもしれない。  ロジックは、短く簡素にまとめられているのが美しい。  プログラミングにおいて、短さは善である。短かければ短いほど美しくもある。極端な話、コードを一行も書かないで実現できればそれがベストだ。一行でも書けばバグの可能性が発生する。〇行ならバグの入り込みようがない。かつてはプログラミング作業の成果を「ステップ数」と呼ばれる記述行数で測ることも多かったが、最近ではプログラムの規模を把握するための一つの参考指標に位を下げている。苦労して行数をたくさん書くのではない。短時間でコードを量産することが偉いのではない。たくさん書けば、その分保守すべき対象も増えてしまう。考え抜いて簡素なロジックで表現し、奮闘の成果としてコード量を減らすのである。  一昔前は、保存領域や実行時の負荷を抑えるため、プログラムサイズを小さく抑えることも重要だった。今でもデバイス環境によっては重要な要件だろうが、パソコンに限って言うと、大容量のハードディスクがメモリや安価に購入できるようになり、その優先度は低くなった。人は制限がなくなれば甘えるものである。実現できることの幅が広がったのはたいへん喜ばしいことだが、パソコン向けのソフトウェア開発において、極力コード量を減らそうという動機づけが一つ減ってしまったのは残念な副作用である。プログラマには、感じない方がいい自由もある。  処理速度についても同様である。パソコンの処理能力向上に比例して、意識は低くなっている。このくらいの無駄は、今のパソコンの処理能力をもってすれば体感できるほどのロスにはならないだろう、というわけである。しかし、無視できるほどの負荷も、積み重なれば大きくなる。プログラムの処理では、繰り返しが頻繁に使用される。ある一塊のロジックを記述するということは、それがほかのプログラマによって、ときとして別のプログラムから使用される可能性があるということであり、その使用方法を完全に制御することはできない。どのタイミングで呼び出され、何度繰り返されるか、将来にわたって正確に想定するのは難しい。0・1秒の処理は体感できないかもしれないが、それが千回繰り返されれば100秒である。これを体感できないほどのんきなユーザーはいないだろう。決してわかりやすく強調した大げさな話ではない。実際にこうした問題が起こって原因を調査し、非効率な実装に気づくことも少なくないのである。  現代のプログラミングにおいて、一からすべてを実装することはまずない。ある程度の汎用的なロジックは部品として提供されており、それを駆使してプログラムを組む。部品の処理仕様は公開されているが、その具体的実装は基本的にブラックボックスである。その中身が効率よく実装されている保証はない。部品を使う側としては、仮に非効率な実装であっても極力パフォーマンスに影響が及ばないよう、呼び出す回数をなるべく少なくするなどの心がけを―常に最優先というわけではないが―忘れてはならない。優しく使ってあげよう、ということだ。そして部品を作る側に回ったときには、使う側の気持ちに思いを馳せて、できるだけ効率的なロジックで実装してあげるのである。双方の気遣いがロジックに込められて、優れたパフォーマンのプログラムとして提供される。ユーザーは気持ちよく操作する。料理だけではない。プログラムも愛情が大切である。これもまた美しいとは、こじつけかもしれないが。  見た目についての記述で "DRY"("Don't repeat yourself")―重複を避けろ―という原則を紹介したが、これはロジックにも関わることである。  例を挙げよう。     劉さんの二番目の娘が昨日我が家にやって来た。   劉さんの二番目の娘は飲みすぎたのか、座ったまま眠ってしまった。  「劉さんの二番目の娘」を解析するたびに、それが誰かを特定する処理が発生すると思っていただきたい。  二度繰り返すのは無駄である。   劉さんには二番目の娘がいる。   彼女が昨日我が家にやって来た。   彼女は飲みすぎたのか、座ったまま眠ってしまった。  「彼女」という代名詞を使うことで、誰だが特定する処理を一回に減らすことができた。無駄が一つなくなった。プログラミングの世界では、「変数」という仕組みを使って同じことが実現できる。  無駄は美しくない。ロジックについても然りである。ある課題を無駄のない効果的な方法で解決したとき、そのロジックを美しいと評することができるだろう。美しいロジックは理解しやすく、使いやすく、変更しやすい。  ロジックはその目的たる処理動作とも不可分である。無駄のないロジックは無駄のない処理動作の基礎となる。プログラムの機能美という側面からは、処理動作の効率性も美しさの重要な位置を占めるだろう。 第四章 命名  プログラムの本質とは命名と分類である。そして分類の本質は命名である。と言っても過言でないほど、命名は重要な行為である。プログラマは膨大な数のデータや操作を、名前をつけることによって識別する。適切な名前をつけることで管理がしやすくなることは、ファイルやフォルダの管理からもご推察いただけると思う。  仏陀はたびたび「すべては名称にすぎない」と語っていたそうである。存在とは名前であり、存在しないものは管理できない。だからプログラムでは、あらゆるものに名前をつける。ただつければいいというわけではない。二の足を踏む「猛雄」くんや傍若無人な「優子」さんは、プログラムではご法度である。  美しい名前は、わかりやすく、実体に即している。  美しい名前は、対象を一意に特定するのに十分な情報を持ち、かつ、長すぎない。中に収められているのが何なのか、すぐに判断できる。  ネーミングセンスという言葉が広く使われるように、命名にはセンスが表れる。大人も唸るうまいあだ名をつける小学生がいるが、それは経験・知識よりも感覚的なものなのかもしれない。ビジネスの世界に目を向ければ、バカ売れの起爆剤となる商品名、思わず手に取りたくなる書名といったものがある。そこで重要なのはおそらく共感とインパクトで、その共感は部分的なものでかまわない、むしろ部分をデフォルメした方がインパクトが強くなるのだろう。  プログラムにおける命名では少し事情が異なる。皮肉ったり、初見の人に訴えかけることが目的ではないので、インパクトはあまり必要とならない。特徴を捉えるのは重要で、そこにセンスの働く余地はあるが、求められるのは部分のデフォルメでなく、全体像の把握と要約である。楽しい例でないのが残念だが―プログラミングは楽しいものなのに―、国語の試験に出る長文読解の設問に近いかもしれない。色気は無用という点も似ている。色気のある命名もたまに見かけるが、プログラムの世界では逆に美しさを損なう。減点である。  プログラムにおける命名の主たる目的は識別である。識別するためには、プログラム内での役割や、出現する文脈を意識することも大切となる。プログラムを構成する要素に、それ単体の絶対的価値はない。ほかの要素との関連において、初めて価値が生まれるのである。したがって、単体で見てふさわしい名前がつけられているというだけでは十分とは言えない。ほかの要素と並べて役割が明確になってこその命名である。  命名の統一性も大事である。整合性のとれた、統一された基準に基づいた命名は、コードの素早い理解の助けとなる。  形式的な統一性を保つための方策として、たいていの開発プロジェクトでは命名規約が設けられる。一人や少人数のチームでは暗黙的な場合もあるが、ある程度の規模の開発では文書化されることが多い。そこには、動詞で始める、名詞で終わる、小文字で始める、といった規則が、それぞれ要素の種類ごとに網羅的に定められている。プログラミング言語によって、世界標準的なものがあれば、基本的な規則はそこに委ねてしまうことも少なくない。規約はかなりの分量になることもある。すべてを頭に入れるのはたいへんだし、いちいち規約にあたるのも効率が悪い。近年では、自動的にチェックして、ワープロソフトのスペルチェックのように警告してくれるツールも出てきている。それらを活用することで、より効率的に、規約の遵守を徹底することが可能となる。  規約を設けるのは単に整頓するためではない。規則は名前を補完する。それが何であるかの形式的な基礎情報を与える。見た目に関して記載したように、ぱっと見でわかるということと、よく見ればわかるということは、全然違うことである。ぱっと見でわかるコードは美しい。美しいコードは、文脈を追うことをむやみに強要しない。  実質的な統一性に関しては、個々のプログラマのセンスに委ねられる部分が多いが、命名規約の付録として、頻出する業務用語の辞書などが作られることもある。たとえば車のシステムを開発するとして、「車」をある人は car、別の人は vehicle、また別の人は automobile などと書いていたのでは、コードがわかりづらくなってしまう。後から参加するプログラマもどれに従えばよいか迷うだろう。一番発言力のありそうな人に従うべきか、出現回数の最も多いものにするか、触発されて私ならと kuruma を新たにエントリするか。ひどいケースだと、Aさんが書いた car をBさんが vehicle に書き換え、その後Aさんが car に戻すなど、不毛な争いが繰り広げられることもある。相手に恨みがあるわけではない。自らの信じるところに従い、それを徹底したまでである。しかし益は薄い。コンピュータはどちらでも同じように動くのだ。プログラムの状態も人間関係も、これでは美しいとは言えない。あらかじめ「車は car と表現する」と決めておけば、このような事態は避けられる。  統一化された美しい命名は、開発効率を高め、コードを通したプログラマ間のコミュニケーションも円滑化してくれるだろう。  本章冒頭の「分類の本質は命名である」については、別に詳しく書く機会があるかもしれない。ここでは、パソコンのフォルダとファイル名をすべてつなげると「完全パス」という一つの名前になることを例示するにとどめる。 第五章 アーキテクチャ  プログラム全体をどう構成するか。個々のロジックを組む前に、より広い視点で検討する。ソフトウェアの構造は、建築にならって「アーキテクチャ」と呼ばれる。それを設計する人が「アーキテクト」である。その設計を日本語で「方式設計」と呼ぶこともある。  プログラマは、アーキテクトによって設計されたアーキテクチャに従ってプログラムを組む。小さなチームでは、プログラマがアーキテクトを兼ねることも珍しくない。  アーキテクトは、技術者にとって憧れの職種と言ってよいだろう。技術者は職人であり、職人はずっと現場で働きたいものである。組織からは加齢とともに管理職への転身を勧められるが、適性も意欲もついてこない場合が少なくない。アーキテクトは、技術者の上級職と位置づけられる。一般的には報酬も高い。発言力もある。マネージャよりも技術者の尊敬を集めることができる。高度なスキルとバランス感覚、構成力、経験が求められるので、誰もがなれるわけではないし、現状では専門職としての募集はかなり限られているが、管理者コース以外のキャリアパスとして、今後定着していくことが期待されている。  アーキテクチャ設計で検討する対象は、ミドルウェア、ソフトウェアの枠組、コーディングスタイル、ネットワーク、データベースなど幅広い。大きな組織では、専門分野ごとにアーキテクトが分業化されることもあるだろう。アーキテクチャはプログラムの基盤となるので、品質や生産性に対する影響は甚大である。規模が大きくなれば、何百人のプログラマがそれに沿って進むのである。その失敗は取り返しのつかない事態を招くことになる。  責任が重大な一方で、やりがいはもちろんある。プログラムの共通基盤を設計するというのは、技術者の腕の見せ所であり、もっとも「おいしい」部分を任されているとも言える。通常、個々のプログラマが担当するのはソフトウェアの一部分であるが、アーキテクチャや、フレームワークと呼ばれる共通の枠組みにおいては、全体を構築することになる。言わば、小さな世界を作り上げるのである。腕も振るいたくなろう。  美しいアーキテクチャは美しいプログラムの礎となる。だが、アーキテクチャには、プログラムから独立した、それ自体の美しさがある。アーキテクトは美意識の強い人種である。美しさにこだわりを持つ人が多い。また、そうでなくては困る。もちろんその職務に限っての話である。幸運なことに、この美への志向はアーキテクチャの実効性とうまく合致する。最適な方式の選択、均整のとれた部品構成、簡素な実装を促す共通基盤、無駄のない処理の流れ―これらを追求することで、美しいアーキテクチャが構築される。それがプログラムの品質、生産性を支えていくのである。  素晴らしい。頑張ったのだから、うっとり自賛するくらいは許してあげよう。ただし、いっときである。アーキテクチャは作って終わりではない。プログラミング工程が進めば、想定外のことは必ず起こる。起こり得ることはすべて想定しておくのが理想であるが、現実には不可能であるし、コストもかかる。最初の決め事は最小限に抑えるという方法論で進められることもある。いずれにしても、アーキテクチャは必要に応じて追加、変更していくものであり、それに耐えうる保守容易性が望まれるのは、プログラム自体と同様である。 第六章 リファクタリング  ソフトウェア業界には「動いているソースコードに触るな」という伝統的な掟がある。何かの改修のついでに、よかれと思って関係ない部分にまで改善を施す。それが仇となり、思わぬ動作の問題を引き起こす。よくあるケースである。当のプログラマは、善意で行ったにも関わらず、その罪を責められ、二度とそのようなことはしないと上司に誓うはめになる。  「コピペ」による「コードクローン」がなくならない背景には、こうした事情もある。  一般的に言って、プログラムの変更が新たな問題を生まないことを確実に保証するのは難しい。些細な変更でも、その影響は無限に広がる可能性を秘めている。他人―半年以上前の自分を含めてもよいだろう―の書いたコードは、一見無駄に見える処理が実は重要な意味を持っていたりと、意図を正確に汲み取ることができないこともある。コードを変更すればテストもしなければならない。影響範囲を限定できなければ、自ずとテスト範囲も広がる。「触るな」の掟が支持され続けている現実には、それなりの理由があるのだ。  だが、この掟に従ってつぎはぎ的な変更を重ねていくと、プログラムの可読性、保守性は落ちる一方で、しまいには誰も見たくない、触りたくないという逆聖域になってしまう。このようなコードは、そのこんがらがっている様から「スパゲティ・コード」と呼ばれたりする。  「触るな」の掟に対し、勇気を持って積極的、継続的にコードを改善していくことを提唱するのが「リファクタリング」である。リファクタリングでは、原則として動作を変えずにソースコードを整理し直す。プログラムは美しくなるが、ソフトウェアの振る舞いは何も変わらない。そのためマネージャには「自己満足」と片づけられてしまうことも少なくない。しかしそうではないのだ。本当はもっと切実な問題なのである。リファクタリングの目的は可読性の向上であり、品質、生産性の向上である。リファクタリングにコストがかかるのは事実だが、それは、放置しておけば膨らむ一方の借金を頑張って今返済してしまうことである。  近年ではリファクタリングの価値も広く認められるようになり、それを安全かつ効率的に行うためのツールも整備されてきた。修正後のテストを自動化する仕組みもある。「触るな」の掟はいまだ健在だが、積極的にリファクタリングを採用する開発チームも増えてきている。プログラムの美しさを維持するためには、継続的にリファクタリングを行う必要がある。そうして美しさを維持することによって、プログラムの品質や保守性も維持されることになる。  リファクタリングの手法自体は純粋に技術的なものだが、プログラマのやる気に与える影響も見逃せない。プログラマとは―どんな職種でもそうかもしれないが―、やる気を起こすと生産性の上がる種族である。そして普通は、スパゲティ・コードよりも美しいコードを前にした方がやる気が起こる。  なお、このような効果を期待して、この乱文にもリファクタリングを施していく所存である。余談であるがお断りしておきたい。  一つ例を。   ヨルゲンはミシェルより酒が強く、エミールはヘンリーより酒が弱い。ミシェルはリディアほど酒が弱くない。ヨルゲンはエミールほど酒が強くない。  最も酒が強いのは誰だろう。  意地の悪いクイズのようだが、このように頭を悩ませるソースコードも実際に存在する。  まず強弱の表現が統一されていないのが問題である。比較する順序もばらばらだ。このままでは理解が難しいのでリファクタリングしてみよう。   リディアよりミシェルの方が酒が強い。   ミシェルよりヨルゲンの方が酒が強い。   ヨルゲンよりエミールの方が酒が強い。   エミールよりヘンリーの方が酒が強い。    正解はヘンリーだった。  強弱の表現を統一し、弱い順から並び替えることでかなりわかりやすくなった。規則性を持たせることで可読性が向上する一例である。  より美しくなったが、さらに短くしてみよう。     酒の強い順に、ヘンリー、エミール、ヨルゲン、ミシェル、リディアである。    無味にすぎるだろうか。心配ない。コンピュータもプログラマも、プログラムに趣を求めてはいない。プログラムにおいて、装飾は邪魔にしかならない。それは美しさをも阻害する。  次の例に移ろう。   トラックレースでは、ちょうど0・1秒で終わる以外は次の0・1秒として変換され記録される。すなわち、10秒11は10秒2と記録される。  日本陸上競技連盟ルール第3部第165条からの引用である。  規程らしく形式ばった表現で、失礼ながら、一読で意味を正確に把握するのは困難である。これをリファクタリングしてみたい。  条文を噛み砕いていくと、「え、これって切り上げってことじゃないの?」という疑問が浮かぶ。が、すぐに断定する自信はない。なぜこのような表現にしたのだろう。特別な理由があるのかもしれない。見落としているケースはないだろうか。  検証が必要だ。  条文の構成は、第一文がルールの定義、第二文が例となっている。検証の手順としては、第一文で切り上げにならないケースがないかを検討したうえで、念のため、第二文の例が切り上げになっていることを確認すればよいだろう。計測の精度は、例に従って小数第二位までとする。  「ちょうど0・1秒で終わる」、すなわち小数第2位が0になるケースについては、特に記載がないので変換は不要と解する。それ「以外」のケース、すなわち小数第2位が0以外のときは、「次の0・1秒」に変換される、とある。境界値の変換をシミュレートしてみよう。     条文による変換:小数第2位が0    10秒10 → 10秒1   条文による変換:小数第2位が0以外(下限値)    10秒11 → 10秒2   条文による変換:小数第2位が0以外(上限値)    10秒19 → 10秒2  結果は切り上げと同じになるようだ。   切り上げ処理:第二文の例    10秒11 → 10秒2  第二文の例が切り上げと一致することも確認できた。  参考までに、こうした局所的な動作の検証は、実際のプログラミングにおいては「単体テスト」という形で行われる。近年では、単体テストはプログラムを実装して自動的に実行することが多い。製品ソースコードの妥当性を、テスト用に記述したソースコードによって検証するである。テストを自動化することで、人の手を介さずに何度でも、素早く、正確に検証できるようになる。ソースコードをリファクタリングしたときも、単体テストを自動実行すれば、意図せず動作が変わっていないことを即座に確認できる。  念のため、信頼できそうな文献として特定非営利活動法人・数理検定協会のサイトを参照すると、「切り上げ」の定義に「概数にする方法の一つで、必要な位より下の数がすべて0でないかぎり、求める位の数を1大きくすることを切り上げという」とある。「必要な位より下の数がすべて0」が「ちょうど0・1秒で終わる」に、「求める位の数を1大きくする」が「次の0・1秒として変換」に相当すると考えると、第一文は、ほぼ切り上げの定義を説明していることになる。  まだ百パーセント確信が持てたわけではない。その意図を日本陸上競技連盟に確認すれば確実なのだろうが、ここでの核心からは外れてしまうので、仮定は正しいと証明できたことにして、実際のリファクタリング作業へと進もう。  先ほどから位を指定せずに「切り上げ」と書いているが、この場合、切り上げの表現は「第2位を切り上げ」だろうか。「第1位に切り上げ」だろうか。あるいはより明確に、「第2位までになるように第3位以下の端数を切り上げ」だろうか。それでは長ったらしくてリファクタリングの意味が薄れるか。面倒だな。せっかく好意で改善しようとしてるのに、表現を間違えて意味を狂わせてしまったら仇になる。得がない。やめてしまおうか。  そう葛藤するのも、実際のプログラミング現場でよくあることだ。特にリファクタリングの価値を認める文化のない組織では、頑張っても評価されないのに、責任だけを負うことになってしまうという意識が、「そっとしておこうじゃないか」という方向に強く働く。  ここで再び数理検定協会の定義にあたると、「例:切り上げによって小数第一位までの概数を求める。」とある。この表現に倣ってみよう。定義が明解なら、第二文の例は不要だろう。   トラックレースでは、切り上げによる小数第1位までの概数で秒数を記録する。  より明解になった。堅い気もするが、正確さを優先してこれでよしとしよう。  忘れてはいけない。大事なまだ作業が残っている。リファクタリング後の定義に先ほどの「単体(自動)テスト」を通しておこう。  いずれもリファクタリング前と結果が変わらないことが確認できた。これで安心だ。このように「単体(自動)テスト」は、最初に書かれたソースコードを検証するだけでなく、動作が変わっていないことを確認するときにも活躍する。リファクタリングには欠かせないツールである。  以上、日本語の文章を例に、リファクタリングの過程を、心の動きも含めて追ってみた。たいへんだという印象を与えてしまったかもしれないが、リファクタリングを施した後のすっきりした感じを、少し味わっていただけただろうか。  美しさを保つにはコストがかかる。だが、すぐに成果に表れないからと言って、そのコストを無駄と切り捨てるのは早計である。違いは将来確実に表れる。美しさを保たれたコードが品質、生産性のうえでメリットを生み出すのは、ほぼ約束された未来と考えてよい。逆の表現がよりわかりやすいかもしれない。作りっぱなしのコードが品質、生産性のうえで大きな足かせとなるのは、ほぼ約束された未来である。 第七章 デザインパターン  プログラミングの世界に、デザインパターンと呼ばれるものがある。  類型化されたプログラム上の問題に対し、解決策としてあるパターンが提示され、名前をつけられる。その効果が広く認められれば、汎用的なツールとして世界的に流通するようになる。「○○パターンで」と言えば、技術者間では「はいはい」となるくらい常識化しているパターンもいくつかある。  もともとは建築のデザインパターンになぞらえて命名されたと聞く。実用に資するという共通点から、概念的にも参考にできる点が多くあったのだろう。建築家クリストファー・アレグザンダーの「パタン・ランゲージ」から多くの影響を受けているという。  パターンとは模倣であり、省力化である。それは、あちらこちらで起こる問題の解決にかかる労力の省力化であるとともに、伝える労力の省力化でもある。プログラムがあるパターンに基づいて実装されていれば、どのような問題に対して何を意図してどのような構造で実装されたのか、おおよその見当がつき、理解の助けになる。  パターンは一般的に美しいものと捉えられている。美しくないパターンはそもそも流通しないので、一つにはそのパターンが美しかったということもあるが、パターンを使う、標準に倣うこと自体が、プログラミングの世界では美しいとされる。依るべき標準はできるだけ広く、多くの人に浸透しているものが望ましい。ローカルな標準は、いつグローバルな標準に飲まれるかわからない、想定ケースが甘いことが多い、という二つの意味で脆く、維持にコストもかかる。標準は規格化されていることもあれば、デファクトスタンダード(事実上の業界標準)やベストプラクティス(最善の慣行)として広く認知されていることもある。デザインパターンでは、"GoF"("The Gang Of Four") (4人のギャングたち)によって定義されたものが有名で、実際に使用されることも多い。  美術や音楽、建築の分野では、ある種の作品が「様式美」と評されることがある。形式的に限定された、ルールを与えられた中での表現とその鑑賞に、特有の趣があるのだろうか。  プログラミングのデザインパターンは「様式美」とは少し違うようだ。むしろ対照的なものなのかもしれない。必然性はないが○○風の流れに乗る、といった趣味的要素はそこにはない。デザインパターンは必然性で成り立っている。優秀な技術者が考え抜けばいつか辿り着くであろう共通の解決策を整理したもの、という見方もできる。そこには根拠があり、目的がある。パターン自体は目的でなく、手段である。感覚よりも理論に依拠している。「様式美」は意図的な形式的模倣と考えられるが、デザインパターンの活用で重視されるのは形式ではなく、問題の実質的解決である。「様式美」も形式でなく、その裏にある心が大切なのだ、というご指摘があれば、その点については私の教養不足と率直にお詫びしたい。  パターンを濫用するのは覚えたての時期に陥りがちなアンチパターンとして歓迎されないが、適切に利用される限り、パターンをきっちりなぞることが「パクリ」「恥知らず」と非難されることはない。プログラミングは言語である。言語は模倣を基盤としている。プログラミングにおいて、模倣それ自体は悪ではなく、むしろポジティブに評価されることが多い。 第八章 正規化  正規化という概念がある。数学でいう正規化とは少し違う。この正規化とプログラムにおける美しさの概念は、体感的に合致するところが大きいと思う。芸術の世界では使われないようなので、プログラムに特徴的な美的要素と考えてよいだろう。  よく知られているのは「データベースの正規化」である。そこには第一から第三―より徹底する場合は第四、第五―までの「正規形」が段階的に定義されている。なお、「データベース」にも種類があるが、ここでは現在主流の「リレーショナル・データベース」を前提とする。「リレーショナル」とは、わかりやすく言うと、行と列の関係たる表で構成されている、という意味である。表同士の関連(リレーションシップ)も定義、操作できるのが一般的である。  実例で見てみよう。  エクセルのような表計算ソフトで、売上シートを作るとする。表計算ソフトの使用経験がない方は、手書きの一覧をイメージしていただいてもかまわない。  必要な情報は何だろう。どの商品を何個購入したか。いつ購入したか。誰が購入したか。連絡先も必要だ。一度の売上で複数の商品を購入することもある。それらは一括りで管理したい。  列定義は次のようになる。   売上伝票番号   売上日   顧客氏名   顧客住所   商品コード   商品名   単価   数量   合計金額  説明を単純化するため、値引きなどは考慮していない。最低限の定義である。  さて、実際に管理を始めてみると、不都合なことが起きてくる。  複数の商品を一度に購入した場合、「顧客住所」まではまったく同じ情報が複数行に展開されることになる。表計算ソフトならコピー&ペーストすればよいが、無駄ではないか。労力もディスクスペースも。「コピペ」は害悪と耳にしたこともある。  無駄な繰り返しをなくすため、「顧客住所」までを別のシートに分離しよう。   [売上伝票]   売上伝票番号   売上日   顧客氏名   顧客住所   [売上明細]   売上伝票番号   商品コード   商品名   単価   数量   合計金額  伝票、明細ときれいに階層化された。大きな成果は、同じ番号の伝票情報が一行にまとまることである。明細から具体的な伝票情報は消え、「売上伝票番号」だけが紐づけ役として残っている。伝票情報の無駄な繰り返しは排除された。  「売上伝票」の行は「売上伝票番号」によって一意に特定できる。「売上明細」の行は「売上伝票番号」と「商品コード」によって一意に特定できる。伝票と明細は「売上伝票番号」によって関連づけられているので、明細から該当する伝票情報を参照することができる。  これが「第一正規形」である。  伝票の無駄な繰り返しはなくなったが、まだ無駄があるような気がする。その直感が当たるのは、商品名を訂正しようとしたときである。今まですべて間違えて入力していた。商品名は各明細に散っている。探して漏れなく直さなくてはならない。一箇所直すだけで自動的に他の明細にも反映されればいいのに。  それを現実化する方法がある。  先ほど「売上伝票番号」と「商品コード」が明細行を特定すると書いた。ということは、ほかの明細情報はその双方に依存するのが自然な形である。どちら一方に依存する場合、居るべき場所に居ないということになりそうだ。ほかに居場所がある。商品名について検討してみると、それは「商品コード」のみに依存していることがわかる。  商品情報を別のシートに分離しよう。   [商品情報]   商品コード   商品名   単価      [売上伝票]   売上伝票番号   売上日   顧客氏名   顧客住所      [売上明細]   売上伝票番号   商品コード   数量  商品情報を独立させることで、同じ商品の名称や単価が明細シートに点在する状態が解消される。明細には「商品コード」が残っているので、そこから商品情報を引くことができる。商品名の訂正が一か所で済むようになった。同じ商品コードに対して商品名の同一性が保証されるので、資料の信頼性も高まるだろう。  「合計金額」も明細から削除された。「商品コード」から「単価」がわかり、「数量」を掛けることで算出できるからだ。  これが第二正規形である。  足速に進むので、もう一つだけお付き合い願いたい。  顧客情報のうち、「顧客氏名」は「売上伝票番号」に対して一意に決まる。ここまでは問題ない。「顧客住所」はどうだろう。「売上伝票番号」がわからなくても、「顧客氏名」がわかれば特定できそうだ。「売上伝票番号」に間接的に依存する形である。新しい居場所を探そう。   [顧客情報]   顧客番号   顧客氏名   顧客住所      [商品情報]   商品コード   商品名   単価      [売上伝票]   顧客番号   売上伝票番号   売上日      [売上明細]   売上伝票番号   商品コード   数量  「顧客番号」を追加したのは、同姓同名があり得るからである。氏名は顧客を一意に識別する情報としてふさわしくない。住所は顧客に対して一つだけ存在するようになった。このままだと、顧客が引っ越した場合に購入時の住所が失われてしまう。これについては、「顧客情報」で変更履歴を保持するよう、拡張することで対応可能である。  これが第三正規形である。  正規化はまず目指すべき基本の形であるが、パフォーマンスや使いやすさの観点から、逆正規化、つまり非正規形に戻すこともある。たとえば、第三正規形で移動した「単価」は、時期や顧客、数量によって変動することがあるため、実際には明細にも保持しておくのが一般的である。定価で販売するとは限らないという前提で、商品情報の単価を「定価」、売上明細の単価を「売上単価」(販売単価)と位置づけるなら、逆正規化ではなく、要件に基づく定義の適正化ということになるだろう。また、第二正規形で削除した合計金額は、プログラム側で毎回計算するより、列として定義しておいた方が楽である。ただし、個別に計算して登録するのでは、数量変更時の反映漏れなど、整合性に不安が残る。表計算ソフトの計算式同様に、自動計算列を定義できるデータベース製品も多いので、それを活用するのがよいだろう。  正規化で美しく整理されるのはわかったが、情報が分かれてしまうと見づらくならないか。一覧のよさは、まさに情報を一覧できるところであり、いちいち別の表を参照するのは手間である。そのとおりだが、心配はいらない。データベースには、求めに応じて情報を結合し、一覧化して提供する機能が用意されている。  ここまでデータベースの正規化について述べてきたが、「プログラムと美」である。プログラムの正規化はないのか。  ない。明文化、体系化されたものとしては。少なくとも普及はしていない。  ある。暗黙的には。プログラムにもその理念は適用できる。  正規化の理念は、美しいプログラムを追求するうえで避けて通ることのできない、必須のものとさえ思う。データベースの正規化とは違った形で、独自に発展、体系化することができるだろうし、それは有用な試みだと思う。  そう思って整理したものが、手元にある。そこには次のような視点が挙げられている。   ・冗長性の排除   ・混在の排除   ・点在の排除   ・不整合の排除   ・不完全性の排除   ・無用なものの排除   ・アンバランスの排除   ・あいまい性の排除   ・不適切性の排除  面白いテーマではあるが、内容が専門的になってしまうので、詳細は別の機会に譲りたい。手元にあると言っても、十年以上前、業界経験のまだ浅い新人が書いたものである。かなりの見直しが必要であろうから、日の目を見ることはないかもしれない。言い尽くされたことの再構成にしかならない危惧もある。もっとふさわしい人が、より的確な視点で書いてくださるなら、もちろんその方が望ましい。 終章  プログラムに存在する美について、いくつかの側面から見てきた。プログラミング経験のない方に、プログラムというものを身近に感じていただくのが目的だった。つまみ読みして「へえ、そうなんだ」と、ぼんやりでも感じてもらえたなら嬉しい。  実のところ、プログラミングはセンスと言ってしまえばそれまでである。どれだけ規則で縛ろうと、規則への従い方にもセンスが表れる。ラップ調にもヨーデル風にも歌えます―いかほど言を尽くされても、実際に歌を聴くまでは信用できない。プログラマも同様である。つまり、私のように理屈をこねる人間が、美しいプログラムを書く保証はまったくない。これが面白いところである。  なお、リファクタリングの章で書いたように、この文章は随時追記、変更、再構成していく予定である。縁あって再びご覧いただく方には、大胆に洗練された姿をお見せできるかもしれない。論を自ら体現したものとご理解いただければ幸いである。内容に違和感を感じる箇所については、辛抱強くお待ちいただければいつか改善されるかもしれない、とこれは言い訳であるが。  2014年 初稿  以降、随時改変
しおりをはさみました。