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