BOOK Preview

Code Complete 第2版 上・下
― 完全なプログラミングを目指して

第34章 ソフトウェア職人気質とは

マイクロソフトプレスの書籍紹介ページ
書籍情報のページ
2005/05/24

Page1 Page2 Page3 Page4

34.8 反復、その繰り返し

 反復は、さまざまなソフトウェア開発のアクティビティに適している。システムの仕様を最初に決める際には、ユーザーと合意に達するまで、ユーザーと協力して要求の版を重ねていく。これは反復型プロセスである。システムを何段階かに分けて開発する進化的デリバリー方式でプロセスに柔軟性を持たせることも、反復型プロセスである。最終的な製品に取りかかる前に、数種類のソリューション候補のプロトタイプを短時間で安価に作成することも、反復型プロセスの一種である。要求の反復は、ソフトウェア開発プロセスの他の部分と同様に重要である。プロジェクトが失敗するのは、代替案を検討しないままソリューションを決めてしまうからだ。反復は、製品の開発に取りかかる前に、その製品について学ぶための手段となる。

 「第28章 コンストラクションの管理」で指摘したように、最初のプロジェクト計画を立てる段階でのスケジュールの見積もりは、どのような試算方式を使用するかによって大きく異なる可能性がある。見積もりに反復手法を使用すれば、1つの方法に頼るよりも正確な見積もりが得られる。

 ソフトウェアの設計はヒューリスティックなプロセスであり、すべてのヒューリスティックなプロセスと同様に、反復的な改訂と改良の対象となる。ソフトウェアは実証されるというよりも検証される性質のものなので、正しい答えが得られるまでテストと開発が繰り返される。上位レベルの設計と下位レベルの設計を両方とも繰り返すべきである。一発でうまくいくソリューションが見つかるかもしれないが、それが最高のソリューションである可能性は低い。何種類かの方法を試してみれば、1つの方法では思いもよらなかった問題の実体が明らかになる。

 反復の概念はコードチューニングにも見られる。ソフトウェアが使用できる状態になったら、その一部分を書き直してシステム全体のパフォーマンスを改善することができる。ただし、最適化の試みの多くは、コードの助けになるどころか、かえって害を及ぼす。最適化は直感に反して、システムを小さく高速にするように思えるテクニックが、実際にはシステムを肥大化させ、低速にすることがある。最適化テクニックの効果に確信が持てなければ、チューニング、測定、チューニングの繰り返しが必要になる。あるボトルネックがシステムパフォーマンスにとって重大であるなら、コードのチューニングを何度か繰り返してみればよい。後の方に行ったチューニングが、最初のチューニングよりも効果的であることがわかるかもしれない。

 レビューは、開発プロセスのすべての段階にわたり、それらが実施されるすべての段階を反復させる。レビューの目的は、特定のポイントでの作業の品質を確認することである。製品がレビューをパスしなければ、作業はやり直しとなる。レビューをパスすれば、それ以上作業を繰り返す必要はない。

 エンジニアリングの1つの定義は、だれでも1ドルでできることを、10セントで行うことである。反復を後の段階まで先延ばしすることは、だれでも1ドルでできることを、2ドルで行うことである。Fred Brooksは「1つ捨てるつもりで。どうせ捨てることになるのだから」とアドバイスしている(Brooks1995)。ソフトウェアエンジニアリングの秘訣は、使い捨てになる部分をできるだけ時間をかけずに安価に作成することである。それが、早い段階での反復のポイントなのだ。

34.9 汝、ソフトウェアと信仰を結び付けることなかれ

 ソフトウェア開発における信仰は、1つの設計手法に頑固にこだわる、特定のフォーマットやコメントのスタイルを信じて疑わない、グローバルデータを何が何でも排除するなど、さまざまな姿で現れる。いずれにしても、それは常に不適切である。

34.9.1 ソフトウェアの神託

 困ったことに、宗教的な態度は、第一人者と呼ばれる一部の人々からもたらされている。技術革新は一般に公開し、現場の人々が前途有望な新しい手法を試せるようにすることが重要だ。新しい手法が完全に実証されるか、あるいは誤りであることが証明される前に、試してみなければならない。現場の人々に調査結果を広めることは「技術移転」と呼ばれ、ソフトウェア開発のプラクティスを前進させるために重要なことである。しかし、新しい手法を広めることとあやしげなソフトウェアを売りつけることは別の話である。「技術移転」という概念は、「新しいフリーサイズの先端技術」というふれこみの胡散臭いものによってすべての問題が解決されると思い込ませようとする方法論の押し売りのせいで、はかばかしい成果を上げていない。「さあ、この新しい手法は何事においてもあなたの生産性を100%向上させるほどすばらしいのだから、これまでに学んだことはすべて忘れてしまいなさい!」

参照
管理者としてプログラミングの信仰の問題に対処することについては、第28章の「28.5.3 信仰の問題」を参照。

 一時的な流行に執着するのではなく、さまざまな手法を組み合わせて使用すること。新しい画期的な方法を試してみるのもよいが、従来の信頼できる方法も頼りになる。

34.9.2 折衷主義

 1つの手法を盲目的に信じると、プログラミング問題の最も効果的な解決策を探しているときに、必要な選択ができなくなってしまう。ソフトウェア開発が決定論的なアルゴリズムに則ったプロセスであるとすれば、その解決策に対する確定的な方法論に従えばよい。だが、ソフトウェア開発は決定論的なプロセスではなく、ヒューリスティックなプロセスなので、確定的なプロセスは不適切であり、成功の望みはほとんどない。たとえば、設計ではトップダウン方式の分解がうまくいくことがあるが、オブジェクト指向の方法がうまくいくこともあれば、ボトムアップ方式の分解や、データ構造方式がうまくいくこともある。何種類かの方法を積極的に試して、うまくいくものとうまくいかないものを知っておかなければならない。しかし、それらを試してみなければ、うまくいくものを知ることはない。すなわち、折衷主義でなければならない。

参照
アルゴリズム的な手法とヒューリスティックな手法の違いについては、上巻第2章の「2.2 ソフトウェアメタファの使用法」を参照。設計における折衷主義については、上巻第5章の「5.4.1 反復」を参照。

 1つの手法にこだわることは、解決策に問題を無理やり押し込もうとするという点で、有害でもある。問題を完全に理解しないうちに解決方法を決定するのは、時期尚早である。解決策の候補を制約しすぎて、最も効果的な解決策を候補から外してしまうかもしれない。

 新しい方法論は、最初はしっくりこないものだ。プログラミングに信仰を持ち込まないためのアドバイスは、問題の解決に少しでも支障があったら、新しい方法論の使用をすぐに中止すべきである、というものではない。新しい手法も古い手法も公平に扱おう。

 折衷主義は、本書で紹介したテクニックに対しても、他の資料で解説されているテクニックに対しても、同じように効果的な姿勢である。ここで取り上げたいくつかのテーマには、同時に使用できない高度な代替手法が含まれている。特定の問題ごとにどれか1つを選択しなければならない。これらのテクニックを道具箱の道具として扱い、作業にぴったりの道具を独自の判断で選択しなければならない。ほとんどの場合、道具の選択自体はそれほど重要ではない。ボックスレンチを使っても、バイスグリップを使っても、三日月形レンチを使ってもかまわない。ただし場合によっては、道具の選択がかなり重要になることがあるので、選択は常に慎重に行うべきだろう。エンジニアリングには、競合するテクニックのどれかを選び、どれかを捨てるという試練的な部分がある。早くから選択肢を1つの道具に絞ったのでは、トレードオフの余地がなくなってしまう。

参照
上巻第2章の「2.3.5 ソフトウェアテクニックの適用:知的道具箱」では、道具箱のメタファ(たとえ話)を詳しく説明している。

 道具箱のメタファは、折衷主義という抽象的な概念を具体化するのに便利である。あなたが請負業者であるとし、相棒のシンプルサイモンがいつもバイスグリップを使っているとする。シンプルサイモンがボックスレンチや三日月形レンチを使うことを拒否したら、あなたはきっと、手持ちの道具をすべて使わないなんて変なやつだと思うだろう。ソフトウェア開発にも同じことが言える。上位のレベルでは、何種類かの設計手法がある。より詳細なレベルでは、何種類かのデータ型のどれかを使って設計を表現することができる。さらに詳細なレベルでは、コードのフォーマットやコメント、変数の命名、クラスのインターフェイスの定義、ルーチンへの引数の渡し方に、何種類かの方法がある。

 独断的な姿勢は、ソフトウェアコンストラクションに対する道具箱の取捨選択という手法に反する。この姿勢は、高品質なソフトウェアを構築するのに必要な姿勢とは相容れない。

34.9.3 実験

 折衷主義は実験との関係が深い。開発プロセスは実験の連続だが、柔軟性のなさはその妨げとなる。実験を効果的なものにするには、実験の結果に基づいて自分の信念を変える用意がなければならない。そうした意思がないのなら、実験は単なる時間の無駄使いである。

 ソフトウェア開発に対する柔軟性に欠ける手法の多くは、過ちを犯すことへの恐怖心に根ざしている。過ちを避けることに終始する試みこそ、最大の過ちである。設計は、大きな過ちを犯さないために、小さな過ちを慎重に計画するプロセスである。ソフトウェア開発における実験とは、ある方法が失敗するかどうかを知るためのテストのお膳立てをするプロセスである。実験そのものは、それが問題を解決する限りは成功なのだ。

 折衷主義と同様に、実験はさまざまなレベルで適用することができる。取捨選択の準備が整ったレベルごとに、どの手法が最適であるかを判断するための実験を考え出すことができるだろう。アーキテクチャ/設計レベルでの実験であれば、3種類の設計手法を使って、ソフトウェアアーキテクチャをスケッチするものになるかもしれない。詳細設計レベルの実験であれば、3種類の下位レベルの設計手法を使って、より上位のレベルのアーキテクチャの意味を確かめるものになるかもしれない。プログラミング言語レベルの実験であれば、簡単な実験用のプログラムを作成して、言語の完全に理解していない処理を試してみることかもしれない。コードの一部をチューニングしてベンチマークテストを実施し、コードが小さくまたは速くなったかどうかを確認することが、実験かもしれない。ソフトウェア開発プロセス全体のレベルでは、品質と生産性のデータを集めて、インスペクションの方がウォークスルーよりも多くのエラーを検出できるかどうかを調べることが、実験かもしれない。

 ポイントは、ソフトウェア開発のあらゆる面で、先入観を持たないことである。製品だけでなくプロセスに対しても、専門的な姿勢でのぞまなければならない。決まった手法ヘの宗教的なこだわりは、先入観のない実験と相容れないものである。

34.10 まとめ

  • プログラミングの主な目標の1つは、複雑さに対処することである。

  • プログラミングプロセスは、最終的な製品に大きく影響する。

  • チームプログラミングでは、コンピュータとのコミュニケーションよりも、人とのコミュニケーションが大切である。個々のプログラミングでは、コンピュータとのコミュニケーションよりも、自分自身とのコミュニケーションに終始する。

  • プログラミング規約は、使い方を誤ると、病気よりもたちの悪い薬となる可能性がある。よく考えて使用すれば、プログラミング規約は開発環境に有益な構造をもたらし、複雑さの克服や意思の疎通に役立つ。

  • 解決策ではなく問題の観点でプログラミングすることは、複雑さの克服に役立つ。

  • プログラミングはほぼ完全に知的なアクティビティなので、「疑いの炎症」のような知的な危険信号に注意を払うことは、プログラミングでは特に重要である。

  • 各開発アクティビティを反復すればするほど、そのアクティビティの成果は良いものになる。

  • 独断的な手法と高品質なソフトウェア開発は相容れない。知的な道具箱にプログラミングの代替道具をぎっしりと詰め込み、作業に適した道具を選択する能力に磨きをかけよう。

 

 INDEX
  Code Complete 第2版 上・下
  第34章 ソフトウェア職人気質とは
    1.34.1 複雑さの克服
    2.34.3 人間が1番、コンピュータは2番
    3.34.6 問題領域に立ったプログラム
  4.34.8 反復、その繰り返し
 
インデックス・ページヘ  「BOOK Preview」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間