The Rational Edgeより:ソフトウェア開発者がコードを書くに当たり、エレガンス、構造、そして効率について学ばなくてはならない理由を考察する。
筆者は今夏、ミネソタ州ミネアポリスで開催されたAgile 2006カンファレンスに参加し、これを大いに楽しんだ。そこで筆者がソフトウェア開発を教えるときのアプローチについてRon Jefferies氏と話をしていたところ、Agile ToolkitのBob Payne氏がこの話題をポッドキャストにしないかと聞いてきた[注1]。筆者が講義をするときのアプローチ[注2]については、1年前のこのコラムで説明しているため、ここでは詳しい説明は省略させていただく。その代わりに、ポッドキャストを録音しているときに遭遇した問題を中心に解説したい。プログラマー全員に共通する、クリーンで保守のしやすいコードを書く能力の欠如だ。
どうしてこのような話題が頭に浮かんだのだろうか? われわれがポッドキャストを録音する作業を聞いていた人の1人から、大学を出たばかりのいまの連中はなぜ優れたコード(つまり、信頼性が高く、きれいにフォーマットされ、エレガントなコード)を書くことができないのか、という簡単な質問が出た。彼は、「学生には、実世界ではうまくないコードを書くと不利益を受けることが分からないのか? 学生がコードやソリューションに対するエレガンスの必要性を理解できないのは、大学教授たちの指導のどこが間違っているのか?」と疑問を投げ掛けた。
本稿では、これらの問題と粗悪なコードがもたらす結果をいくつか考察し、考えられるソリューションをいくつか提案する。
クリーンなコードとは、美しさのように、見る人によっていろいろな意味で異なる。経験豊かなプログラマーがプログラムのソースコードを見れば、それが読みやすいかどうか分かる。彼らはさらに、コードが効率的かどうか、十分に構造化されているかどうか、そして簡潔性の面でエレガントかどうかについても素早く意見を出せる。これらの特性はどれも定義が難しいが、クリーンかそうでないかは、ソフトウェア開発者にコードを見せれば大抵は一致した意見が得られる。
クリーンなコードに寄与する要素は多い。そのいくつかは普遍的で、ソフトウェア開発時のあらゆるタイプのプログラミング言語や問題領域に当てはまる。また、クリーンなコードの特性の中には、特定のプログラミング言語に依存するものもある。
ここで、同じ処理を行う2つの短いコードを見てみたい。これは、テニスのセットカウントを数えるコードだ[注3]。いずれにも、勝ったゲームの数を計算するメソッドと、そのスコアを知らせるメッセージを返すメソッドがある。どちらも入力はすべて正しいと仮定しており、不正入力に対するチェックは行っていない。これらは、設計と構築を同時に進める手法で書かれており、クラスの正しい使い方はクライアント次第となっている。これらはいずれも同じユニットテストに合格している。では、以下の2つのリストを見てみたい。リスト1とリスト2のどちらの方が「クリーン」だろうか?
リスト1は、同じ処理を繰り返すようなコードで初心者プログラマーがよく使う幼稚なスタイルで書かれている。必ずしも複雑ではないが、筆者には散らかっていて効率が悪く見える。リスト2の方が複雑な条件になっているが、Javaを理解していれば、かなり読みやすい。唯一疑問を抱くかもしれないとしたら、最後の「else if」の中にある条件の最初の部分だけだ。このクローズに来るということは、どちらかのプレーヤーが勝ったことを意味する。
いずれのインプリメンテーションも間違ってはいない。実際、これらはどちらも非常に小さく、つまらない例にすぎないので、これらのリストでコードがいかにクリーンか論ずるのはあまり有益ではない。ただ、何をもってインプリメンテーションがクリーンなのかについて読者の興味を深めることはできるだろう。
クリーンなコードについて扱った記事、Webサイト、書籍は多数存在する。何をもってコードをクリーンとするかについては、誰にでも一家言ある。講義や研究の目的でコードを見る機会が増えているが、筆者がこのうちのいくつかを見たところ、そこには原則があるように思える。それらについては、本稿の後半に示す。
筆者は、汚い、もしくは粗雑なコードができるのには以下の3つの理由があると考える。
では、これらを1つずつ見ていこう。
・時間のプレッシャー
ソフトウェアプロジェクトは遅れるものだ。ウォーターフォールプロセスを使うと反復型アプローチよりさらに遅れるが、大半のプロジェクトは採用するライフサイクルモデルに関係なくある程度は遅れる。反復と増加を繰り返すライフサイクルにおいては、遅れがスケジュール的なものではなく、機能的なものに起因する場合もある。
プロジェクトが遅れ始めると、開発者とチーム全体が近道をしようとする傾向になる。これが人間性だ。「ワニに丸のみにされようとしているときに、自分が沼に入った目的を思い出そうとしても難しい」というではないか。プレッシャーが掛かると、何かをあきらめることになり、目の前のこと以外は見逃しがちになる。先の例の場合は、取りあえずワニに向かっていくことになる。筆者は、プロセスも典型的に無視されてしまうものの1つであることに気付いた。プロセスは、具体的な行動を取るか、特定の成果物を生み出す必要があるが、これらを回避できるのならそうするだろう。追い込み作業が一息ついてから作業を再開しようと考えるし、そうするつもりでいても、そうなることはめったにない。
必要に応じて捨てられるということに関しては、クリーンなコードにもプロセスと同じことがいえる。われわれは、意味のある「netPay」などの変数名を使う代わりに、短くて、貴重な時間の節約にもなる「np」などを使ってしまう。有意義なコメントも、アルゴリズムの説明も付加しなくなる。期限が迫り、コードを何としても動くようにしなくてはならなくなる。
期限に合わせてコードを書くこのようなアプローチはあまりに近視眼的で、後から自分たちが苦労させられることになる。
・学習不足
高校、大学、あるいは何らかの方法でプログラムを学習したとしても、クリーンなコードを書く方法について本当に学んだ経験はおそらくないだろう。これは、教育機関に時間的制約があることも要因の1つだ。ある一定の時間に教えられることには限界があり、プロジェクトの期限が迫るとプロセスが排除されてしまうのと同じように、クリーンなコードに寄与することの多いコーディングスタイルや読みやすさなどの内容は教育課程から省略されてしまう。
各種教育機関におけるプログラミングの講義概要を見ると、講義の名称や目標にプログラミングスタイルが含まれるものもいくつかある。しかしよく見ると、目標に向けて最後までやる講師はまれであるように思える。課題や成績評価基準にも、クリアで読みやすく、うまく書かれたコードに対する評価を加味した内容がない。営利目的でプログラミングを教えるコースは学校よりさらに悪い。こちらはさらに講義時間が短いのが普通で、会社に戻ってから学んだばかりの言語に関してのみは生産性を高められるよう、必要最低限の知識を教えることしか考えられていない。
・熱意
大学のコンピュータサイエンスの教科課程の大半は、各種言語のプログラミング入門になっていない。それよりむしろ、学生は各種言語の十分な基礎教育を受けているものと仮定され、OSやネットワークの課程にコーディングスタイルや読みやすさに関する内容が含まれることはほとんどない。学生は、問題を解くことで評価されるだけだ。スタイルが考慮されることはない。
誤解しないでいただきたいのだが、コンピュータ科学者はエレガントなコードを高く評価する。筆者としては、ソフトウェアエンジニアリングの教授はコードのクリーンさに特に注意を払ってくれるものだと思いたい。しかし、この評価の対象が必ずしもコードの読みやすさや保守性であることもない。われわれは、コードの読みやすさや構造よりエレガントなアルゴリズムや技術のエレガンスを評価することも多い。
コードをきれいにではなく適切に書くことに価値を感じているのは大学だけではない。これは実社会でも起こることであり、残念ながらプログラミングコンテストでも見受けられる。ACM International Collegiate Programming Contest世界大会決勝の採点方法からの引用をご覧いただきたい。
「チームは解いた問題の数で順位が決められる。上位12チームのうち回答数が同じチームは、まず所要時間の少ない順番、そして必要であれば最後の有効処理が実行されたときのタイムで最終順位を決める」[注4]
そう、そこにはクリーンなコードを評価する規定が全くないのだ。筆者は、コードのエレガンスと読みやすさを「判定」することが簡単な作業でなく、どちらかといえば主観的な作業であることは認識している。また、エレガントなコードを書けば回答を早く取得する確率も高まるといくら主張しても、筆者はこれを立証する調査を1つも知らない。ここで筆者がいいたいのは、重要なプログラミングの現場では、クリーンなコードが全く考慮されないことが多過ぎるということだ。
世間が汚いコードであふれている理由は十分に分かったが、では、われわれはそれに対して何ができるのだろうか? 筆者はここで、以下の3つが可能だと提案したい。
では、ここで1つ1つ説明したい。
クリーンなコードを書くことを自分のプロセスに取り入れる。
Agileコミュニティーにおいては、コードをクリーンしておくことは原則の1つだと高く評価している。その1つが以下だ。
優れた技術とデザインに常に留意することがアジリティを強化する[注5]。
この原則は、eXtreme Programming(XP)の連続リファクタリングなどの手法の中で明示されている。XPのチームに参加するプログラマーは、常に時間をかけ、コードを可能な限りクリーンかつエレガントなものにすることが期待されている。近道は許されることではなく、評価されることも報われることもない。もちろん、これは期限が迫ってもチームが実際にXPの手法に従っていると仮定した場合だ。しかし、時間に追われることによって、組織が再びワニとの対決を余儀なくされる文化に戻らないとの保証は一切ない。
もしあなたが、リファクタリングや優れたコメントの作成を自分の個人プロセスに組み入れれば、ほかの方法ではコードが書けなくなっていくだろう。見積もりが正確かつ妥当なものになるよう、コードをクリーンにし、コメントを挿入するための時間を考慮することになる[注6]。
・クリーンなコードの書き方を教える
コードを書く作業はほかのどのような作業とも同じだ。練習、批判、そして練習の繰り返しが必要だ。Richard Gabriel氏は自著『Writers' Workshops & the Work of Making Things: Patterns, Poetry……(作家のためのワークショップと物作り:パターン、詩……)』[注7]の中で、散文、詩、そしてソフトウェアコードを書くときの多くの類似点を解説している。これらのさまざまな書き方を芸術として扱い、協調テクニックを重点的に学ぶことは学校では難しいが、教師がソフトウェアのコーディング学を芸術の域にまで高めることのできる手段なら、おそらくどのようなものにも価値があるだろう。
うまく書けるようになるためには、うまく読めなくてはならない。書き方に堪能になりたいときは、まずは特定の言語で利用される標準と成句の両方の読み方を理解する必要がある。コードの読み書きも同じだ。その言語と、それのうまい使い方を学ぶ必要がある。そして、優れたコードを書けるようになりたいなら、コードをうまく読めるようになる必要がある。学生に対し、コードを読んでよく考え、その品質やエレガンスについて議論しろという時間が不足しているのだ。筆者が一緒に働く光栄にあずかれた最も優秀なソフトウェア開発者の1人は、膨大な量のコードを読む。彼は、さまざまなプロジェクトのコードを読み、どうすればそれを改良できるか考えることで、うまくプログラミングするための方法を学んでいるのだ。
一部の学校(その数はあまりに少ないが)では、「ソフトウェアスタジオ」のような名前の付いた課程やゼミを用意している。これらの課程では、学生がアーチストや作家のように集まり、作品を見せ合う。彼らはどんな意見でも出し合い、建設的な批判の仕方や受け方を学ぶ。大体の場合、優秀な学生には業界でよく見られる大きなエゴがあり、このような課程は彼らの多くにとって困難なものになるが、それは素晴らしい学習体験になるだろう。
われわれは、今年のWPIから「コーディング道場」を開催している。コーディング道場は、筆者が今夏の「Agile 2006」カンファレンスで知ったものだ[注8]。毎週集まってシンプルなコーディングに挑戦している。コードをグループで書くことも多い。筆者が先に示したリスト2のコードは、先日の集まりで作成したものだ。われわれの道場で唯一問題になるのは、時間があまりに短いことだ。しかし、この道場は、クリーンなコーディングテクニックについて考え、それを自分の中に取り入れるのに最適な方法だ。道場はどこでも開くことができる。会社の昼休みのイベントとしても素晴らしい。
大学の課程で出る課題の大半は短いもので、前述のようにコードのエレガンスや読みやすさはあまり重視されていない。しかし教育者としては、学生が利用できるコードベースを増やす方法を探す必要がある。例えば、学生に既存のコードベースの維持管理を行わせ、これを拡張することも考えられる。そうすれば、彼らもうまく書かれていないコードの苦痛を味わい、それが後々生産性に与える影響を感じられるようになるだろう。筆者の学生は2005年にこのようなことを経験した。2006年になってから、筆者がプロジェクトにおけるコードの品質向上の必要性を認識した次第だ。
その結果は劇的なものだった。筆者がソフトウェアエンジニアリングを教えている学生に対し、オブジェクト指向分析や設計を教えている学生の書いたベースコードを提供したところ、1週間もたたないうちにこれを効果的に使い出したのだ。2005年の時点では見られなかったことだ。筆者が毎週課題を出すOOADプロジェクトの成績は、そのjavadocコメントとコードのスタイルで採点した。
・クリーンなコードを評価する
もしあなたがマネージャならば、部下に自分の価値を理解させる必要がある。コードの品質とエレガンスがあなたにとって重要であることを、部下である開発者が確実に理解するよう努めるのだ。期限が迫ってきたらチームをかばい、(いずれにせよテキトーなことが多い)予定日を守るためだけに粗悪なコードを出荷するよりも、スコープ管理のために戦うのだ。
優れたコードには何らかの方法で報いたい。報いることは難しいことではない。あなたが何を重んじるのかを部下たちが認識するまでにさほど時間はかからないし、彼らは底力を発揮して、これらの価値に見合った成果を上げるだろう。大規模企業の活動はこのような価値を支持しないが、コードの保守性が将来的な作業に役立つため、長期的には部下たちができる作業は増えていくだろう。
本稿がきっかけとなり、クリーンなコードを評価することを考えていただけるようになれば幸いだ。筆者は、これがきっかけでクリーンなコードを評価する手段について考えるようになった。今後の記事では評価基準について解説していきたい。
Copyright © ITmedia, Inc. All Rights Reserved.