第2章 分析

ソフトウェア開発サイクルに決まった数のフェイズがあると言う人は愚かです。

それでも…

プログラミングサイクルの9つのフェイズ

これまで見てきたように、Forthは設計の側面と実装・保守の側面を統合しています。 その結果、「典型的な開発サイクル」という概念は、「典型的なノイズ」と同じくらいの意味しかありません。

しかし、どんなアプローチもアプローチ無しよりは良いです。そして成程、一部のアプローチは他のアプローチよりもマシです。以下がソフトウェアプロジェクトで使われていて最も成功しているアプローチの「平均的な」開発サイクルです。

分析

  1. 要件と制約を発見する
  2. 解決策の概念モデルを構築する
  3. 費用、期間、性能の見積もり

エンジニアリング

  1. 予備設計
  2. 詳細設計
  3. 実装

使用

  1. 最適化
  2. 検証とデバッグ
  3. 保守

この本ではサイクルの最初の6つを取り扱います。分析・設計・実装に焦点を当てます。

Forthプロジェクトではこれらのフェイズは幾つかのレベルで発生します。最も広い観点からプロジェクトを見ると、これら各フェイズは1ヶ月以上かかる事があります。季節が移り変わるように、あるフェイズに次のフェイズが続きます。

しかしForthプログラマは各ワードを定義するときも同様のフェイズを適用します。そのサイクルは分単位のオーダーで繰り返されます。

プログラミングサイクルをこのように素早く繰り返してアプリケーションを開発することは「反復アプローチ」として知られています。

対話的アプローチ

反復的アプローチはキム・ハリスによって雄弁に説明されています。 [harris81] 彼は科学的手法を説明するところから始めます。

…それは果てしない発見と洗練のサイクル。それにはまず、既存の自然のシステムを研究し、そのふるまいを観察します。それから、その観察結果を自然のシステムについての理論を生み出すためにモデル化します。次に、分析ツールをそのモデルに適用することで、現実のシステムのふるまいに関する予測が生成されます。実験とは現実のふるまいと予測したふるまいを比較することです。こうして自然のシステムが再び研究され、モデルが改訂されました。

_images/fig2-1.png

図 17 ソフトウェア開発のための反復的アプローチ("The Forth Philosophy", by Kim Harris, Dr. Dobb's Journal. より)

この方法の「目標」は、自然のシステムのすべての観察可能な行動を正確に予測するモデルを作成することです。

そしてハリスはこの科学的手法を 図 17 に示すように、ソフトウェア開発サイクルに適用します。

  1. 解決策に必要な機能を決定するために問題が分析されます。
  2. 利用可能な資源(resources)を使ってこれらの機能をどのように達成するか決定します。
  3. 設計を実装するためのプログラムが記述されます。
  4. プログラムは、機能が正しく実装されたかどうかを判断するためにテストされます。

ハリスは加えて、

Forthでのソフトウェア開発では、まず最初に、与えられた問題に対する最もシンプルな解決策を見つける事を求めています。問題の、選択した部分をばらばらにし、できるだけ制約を無視して実装することで行います。その後一つまたは幾つかの制約が課され、プログラムが修正されます。

設計の開発モデル・テストモデルを表す優れた証言は「進化」です。原生生物からオタマジャクシ、そして人類まで、進化の道に沿ったそれぞれの種は機能的な生物からなっています。創造主はトップダウン設計者ではないように見えます。

ヒント

シンプルに始めましょう。それを実行して下さい。あなたが試そうとしていることを習い学びましょう。要件と制約に合うように、必要に応じて徐々に複雑さを増して下さい。最初からやりなすことを恐れないで下さい。

計画の価値

この章の冒頭の、9つのフェイズで、「実装」の前に5つのフェイズを挙げました。なお、 Chapter One では、計画への耽溺は苦難が伴い、かつ無意味であることがわかりました。

言語に関係なく、ある程度の計画無しに重要なソフトウェアプロジェクトに着手できないのは明らかです。正確には、どの程度の計画が適切なのでしょうか?

複数のForthプログラマが、 デーブ・ジョンソン の計画に対する几帳面アプローチを高く評価しています。 ジョンソンは、ペンシルベニア州スプリングハウスにあるムーアプロダクツ社のスーパーバイザーです。 同社は産業用計装およびプロセス制御アプリケーションを専門としています。 デーブは1978年以来Forthを使用しています。以下は彼自身による、このアプローチの説明です。

Forthを使っている他の多くのユーザと比べて、私たちはもっと正式なアプローチを取っていると思います。私がこれを学ぶのは大変でした。私の、初期の規律の欠如は、私を悩ませてきました。

私たちは新製品を思いつくために2つのツールを使います。機能仕様と設計仕様です。私たちの販売・アプリケーション部門ではカスタマーセンターを通じて機能仕様を作成しています。

私たちがやるのに合意したら、機能仕様は私たちの部署に引き渡されます。その時点で私たちは設計作業して、設計仕様を考え出します。

これまでのところ、私たちのアプローチはどの言語のプログラミングとも変わりません。 しかし、Forthでは、設計を多少変更します。 Forthを使用すると、コーディングを開始する前に設計を95%行う必要はありませんが、反復プロセスに入る前に設計を60%行っておく必要があります。

典型的なプロジェクトは、当社のある製品に機能強化を加えることです。 たとえば、ディスクドライブを搭載したインテリジェント端末があり、他のデバイスと通信するには特定のプロトコルが必要です。 プロトコルの設計、ディスプレイの作成、ユーザインターフェイスの提供などのプロジェクトには数ヶ月かかることがあります。 機能仕様は1か月かかります。 設計仕様書は1か月かかります。 コーディングは3ヶ月かかります。 統合とテストにはもう1か月かかります。

これが典型的なサイクルです。あるプロジェクトは丸2年かかってしまいましたが、6、7ヶ月掛かるのは普通です。

私たちが5年前にForthを使い始めたときは、こんな感じではありませんでした。機能仕様を受け取ると、私はすぐにコーディングを始めました。私はトップダウンとボトムアップを交錯させながら、 全体的な構造を定義し、それを必要に応じていくつか低レベルの、そしてより多くの構造を定義しました。

そのアプローチの理由は、経営陣に何かを見せるなければいけないという大きな圧力でした。 私たちはしていたことを書き留めることは決してありませんでした。 3年後、何もドキュメントなしでコードを修正しようとしました。 それは私達にあまりにも早く作業すること許したために、Forthは不利になりました。 ライトをチカチカさせたりディスクドライブがうなるのは楽しかったです。 しかし、私たちはすべきでないように見えた設計作業を行いませんでした。 私が言ったように、私たちの「自由な精神」は私たちを悩ませるために戻ってきました。

今では、新しいプログラマのために、私たちには確立された要件があります。あなたのプロジェクトが行おうとしてるタスク、つまり、定義する全てのハイレベルForthワードを詳細に網羅した設計仕様です。機能仕様を数ページも読んだり、それに答えたり、更に数ページ読んだり、それに答えたりすることはもう必要ありません。

生きているプログラマは誰も文書化するのを好みません。 設計を前もって確実にすることで、数年後でもかつて行ったことを思い出すことができます。

設計段階では、特定のアイデアを試すためのコーディングがある程度行われていることに注意してください。 しかし、このコードは完成品の一部ではないかもしれません。 そのアイデアはあなたの設計を描き出すためです。

ジョンソンは、必要な予備テストを除いて、コーディングを開始する前に設計仕様を完成させることを推奨しています。 次のインタビューではこの点を取り上げ、そして幾つかの追加の理由を述べます。

ジョン・テレスカ は1976年から独立系ソフトウェアコンサルタントとして、学術研究環境向けのカスタムアプリケーションを専門としています。 彼は「テクノロジーが不可能を可能にする正に最前線」で研究ツールを提供することを楽しんでいます。 テレスカはニューヨーク州ロチェスターで働いています。

私はソフトウェア開発プロセスは2つのフェイズがあると思います。 1つ目は、問題が何であるかを確実に理解することです。 2つ目は、デバッグ、検証などを含む実装です。

フェイズ1の私の目標は操作上の仕様です。私は問題の説明から始めます。そして進めるにつれてそれは操作上の仕様になります。問題の私の理解は解決策に変身します。より良い理解はより完全な解決策になります。私は、討論終結点を探ります。それは印刷物では答えられない質問がこれ以上無いと見て取ることです。

私は、各プロジェクトでフェイズ1に時間をかけていることに気付きました。これは、私の顧客の多くが最初は狼狽していた意味します。限界要因はどのぐらいか、私はその時間を前もって費やす必要があることを顧客に納得させることができます。顧客は一般的に彼らがやりたい仕事の仕様を知りません。そして、彼らは良い仕様を作る為に費やす為の資本を持ってない、または費やせるとは感じていません。 私の仕事の一部は、そのために資本を費やすことは、結局は、より多くの時間とお金を掛けないで済むことになると、彼らに納得させることです。

フェイズ1のいくつかは実現可能性の研究に費やされています。 仕様書を書くことは不確実性を明らかにします。 私は不確実性についてはできる限り不確実なものとして試します。 たとえば、一定の精度で1秒間に200,000サンプルを収集したいとします。 私は最初に彼らが持っている機器でもそれが可能であるかどうかを調べる必要があります。 この場合、コードのパッチを書くことによってその実現可能性をテストする必要があります。

仕様のもう一つの理由は私自身を守ることです。 アプリケーションが仕様どおりに機能しても顧客を完全には満足させない場合、それは顧客の責任です。顧客が更に要求するなら、私たちは再交渉しなければならないでしょう。しかし、私はそれを設計者の義務として考え、顧客が満足のいく仕事ができる運用仕様を生成するために必要なことは何でもします。

仕事を失うことを恐れて、顧客の圧力に屈し、仕様に費やす時間を制限するコンサルタントがいると思います。 しかし、そんな状況では、だれも幸せになりません。

閑話休題。後でまたテレスカのインタビューに戻ります。

計画の限界

コーディングを開始する前に、私たちはどこに向かっているか計画することを経験によって学びました。しかし計画には一定の制限があります。以下のインタビューでは計画の価値についてさまざまな見通しが示されています。

テレスカ の好みはよく計画されたプロジェクトですが、トップダウンとボトムアップのどちらのアプローチを選択するかは状況に依存するとほのめかしています。

多くの技術的なインターフェイス作業を含む最近の2つのプロジェクトでは、私は全部ボトムアップしました。私が扱っていたオペレーティングシステムの細かな部分のデータシートと技術的な説明の束を抱えて私はうろうろしました。 時間のほとんどを浪費して、私はなぜこの仕事を請けたのだろうとさえ思いました。それからついに私はある種の限界質量(ある結果を得るために必要な量)に到達し、小さなことを実現させる小さなプログラムをまとめ始めました。 それから私はそれがターゲットアプリケーションと一致するまで、ボトムアップで続けました。

私の、トップダウンに慣れた感覚からすると、この手順はぎょっとするものでした。しかし、教育的な理由によるものを割り引いてみても、私はこのプロセスで何度も成功を経験しました。そしていつも、たくさん直線的思考をしないと突破できないように見える、この困難なフェイズがあるように思えます。このビジネスでは、プログラミングは、お互いにが当然すべきであるとすることより、もっと直感的に思えます。

アプリケーションがこの失われた感覚を引き出すと私が考えるなら、私はボトムアップで進めます。アプリケーションがおなじみの領域にある場合は、私はおそらく伝統的な書籍によるアプローチを使用します。

そして、以下もまた別の見方です。

私が彼にインタビューした時には、ユニオン・カーバイドのマイケル・スターリングは、ユーザが設定できるラボ自動化とプロセス制御自動化システムを含む2つのアプリケーション上で最後の仕上げを行っていました。 パイロットプラントシステムのために、スターリングは、既知の要件のためにハードウェアとソフトウェアの両方を設計しました。 ラボ自動化システムでは、彼自身も要件を定義しました。

彼の努力は大成功でした。 あるプロジェクトでは、新しいシステムのコストは同等システムのわずか20%で、インストールと設定には数か月ではなく数日で済みました。

私は彼が採用したプロジェクト管理テクニックはどのようなものなのか尋ねました。

どちらのプロジェクトでも多くの設計が必要でした。しかし私は伝統的な分析手法には従いませんでした。私は以下のステップを採用しました。

第一に、問題の境界を明確にしました。

第二に、小さな機能部分であるソフトウェアサブシステムがどうあるべきかを決めました。

第三に、私は各部品を作り、それらをまとめると、システムが走りました。

次に、私はユーザに「これはあなたの要求を満たしていますか?」と尋ねました。 時々はユーザも仕様設計者も予想できなかった理由で要求を満たせていませんでした。

例えば、設計者は、元の仕様では人を対象とした快適なグラフィックディスプレイを作成できないことに気付きませんでした。最初のバージョンでインタラクティブグラフィックを使って作業した後、ユーザは任意なスケールの適用と奇天烈な表示装置を見せてきました。

そのため、基本的なプロットアルゴリズムの設計後に自動スケーリングが必要なことが判りました。私たちは開発の前の段階に戻って、人間がどのようにデータをプロットするのかを分析し、xとyのデータを評価し、グラフにどれだけ収まるかを評価する第一レベルのプロット機能を書きました。

その後、私たちは、得られたデータ全てが実験者にとって興味を惹く訳ではないことに気付きました。そこで、私たちはズーム機能を追加しました。

この反復的なアプローチにより、よりきれいなコードになり、より良いコードを考え出すことができました。 基本的な目標を設定し、ユーザの既知の要件に合わせて最小限のシステムを構築しました。それから、私たちはプログラマの経験により、改良したり、仕様作成時にユーザが必要なのに忘れていたもの確認したりします。

ユーザは新しいアイデアのほとんどを考え出しませんでした。プログラマが考え出して、ユーザへこれらのアイディアを提示しました。問題の定義は双方向でした。 場合によっては、そのような小型コンピュータでは、デジタルフィルタの適用やデータへの信号処理などは実行できないことがわかっていました。

Forthがこのアプローチを可能にするのは、プリミティブが簡単にテスト可能であるということです。 これを利用する方法を学ぶには、Forthでの何らかの経験が必要です。 従来の環境の人たちは、コーディング用紙で10ページのコードを書き、それかおもむろにそれをタイプインしてそれが機能することを期待しています。

私のアプローチを要約します。私はユーザから、ユーザ必要とするものを見つけることを試みるが、同時にその不完全性を認識することを試みます。 それから、ユーザがアプリケーションの業務知識を持っているので、ユーザには実装の間、設計に関わってもらいます。 ユーザが結果を見たとき、ユーザは自分たちの考えが関わっていることを知っているので、気分が良いです。

反復アプローチは、実際の問題に対する優れた解決策を生み出すことに最大の価値を置きます。 そのソフトウェアのコストが予測可能とは限りません。解決策への道はあなたの優先順位に依存するかもしれません。 覚えておいてください。

良い
速い
安い

どれか2つを選んでね!

スターリングの考察のように、自身で完全にやってみるまで、あなた自身がしていることを完全には知りません。私自身の経験では、アプリケーションを書くための最良の方法はそれを2回書くことです。最初のバージョンを捨て、そしてその経験を記録します。

ペーター・コゲ は、ニューヨーク州オズウィーゴにあるIBM連邦システム事業部のシニアテクニカルスタッフです。

私が見つけたForthの利点の一つは、ごたごたせずに非常に素早くアプリケーションを試作できることです。それは多くの場合、大きな制限がありますが、実地に試しに走らせて「ヒューマン・インターフェイス」を引き出すのには充分です。

私がこのように試作するときは、最終プログラムでは、試作のコードを単一行で使わないという強い制約のもとに作成します。これらのプログラムがForth以外で書かれている場合でも、この強制された「作り直し」は、ほとんどいつも、はるかに単純でより洗練された最終プログラムをもたらします。

私たちの結論は何でしょうか。Forthでは環境計画は必要です。しかしそれは短く保っておくべきです。テストと試作は本当に必要なものを発見する最良の方法です。

プロジェクトマネージャへの注意事項:もし、経験豊富なForthプログラマを監督しているのなら、計画に時間をかけすぎることを心配する必要はありません。 したがって、以下の「ヒント」には2つのバージョンがあります。

ヒント

(「伝統的」な開発手法の経験のある)Forth初心者の場合、分析フェイズを最小限に抑えてください。

(伝統的な開発手法経験の無い)Forth常用者の場合、あなたが耐えられる限りコーディングを延期して下さい。

または、第1章 で観察したように、

ヒント

(変更可能なコンポーネントを設計することによって)変更を計画する

または、シンプルに、

ヒント

試作する

分析フェイズ

この章の残りの部分では、分析フェイズについて説明します。 分析とは、プログラムが何をすべきかを理解し文書化する体系的な方法です。

あなたが1時間もかからずに書く簡単なプログラムでは、分析段階は約250マイクロ秒なのかもしれません。 反対に、プロジェクトによっては構築に多大な人月を要するものもあります。 そのようなプロジェクトでは、分析フェイズはプロジェクト全体の成功にとって重要です。

分析フェイズには3つの部分があります。

  1. 要件と制約の発見
  2. 解決策の概念モデルの構築
  3. コスト・スケジュール・性能の見積もり

では、各部分の簡単な説明を見てみましょう。

要求の発見

最初のステップは、アプリケーションが何をすべきかを決めることです。 顧客、またはシステムを望む人は誰でも、「要求仕様」を提供するべきです。これは完成品の最低限の機能を一覧にしたささやかな文書です。

また、分析者はインタビューを実施し、ユーザにアンケートを送付することによってさらに調査することができます。

制約の発見

次のステップは、あらゆる制限要因を発見することです。スピードはどのぐらい重要ですか?利用可能なメモリはどのぐらいですか?納期はどのぐらいですか?

テクノロジーがどんなに高度であっても、プログラマはいつも限界に立ち向かう事になるでしょう。システムの容量は時間の経過とともに不思議にな減少をします。 かつて私のストレージへの願いに答えていた倍密度フロッピーディスクドライブは、もはや要求を満たすことはできません。 私が次に手にするだろう両面倍密度フロッピーディスクドライブは、しばらくの間だけは、広大なフロンティアのように思えるでしょう。10メガバイトのハードディスクを持っている人たちが窮屈な気分を訴えているのを聞いたこともあります。

何か不足する都度、トレードオフの必要があります。そしてそれはいつも起こるのです。制約のほとんどを予測しトレードオフをなすためには分析フェイズを用いるのが最善です。

一方、分析中は他の種類の制約を考慮しないで下さい。代わりに、実装時に徐々に制約を課すようにしてください。

分析中に考慮する制約の種類には、全体的なアプローチに影響を与える可能性がある制約が含まれます。 延期する種類には、ソフトウェア設計計画で反復改良することによって処理できるものが含まれます。

以前のインタビューで聞いたように、ハードウェアの制約について知るために、しばしばテストコードを書いて試してみる必要があります。

顧客 の制約について知るには、通常、顧客に尋ねるか、または、書面による調査を行います。 「1〜10の尺度で、どれだけ早くそのようなものが必要ですか?」などなど。

解決策の概念モデルの構築

概念モデルは、問題に対する架空の解決策です。 それはシステムがどのように動作するように見えるかの観察です。 それは、すべての要件と制約に対する答えです。

_images/img2-047.png

図 18 要件と制約を満たすよう概念モデルを改良

要件の定義が「天井を塗装するために立つための何か」である場合、概念モデルの説明は「自立型(つまり、部屋の中央で塗装することができます)の装置で、使いやすい間隔の幾つかのステップ(あなたが昇降することできます)、てっぺんの近くに小さな棚がある(塗料缶を置くため)、です。

ただし、概念モデルは全くもって設計と言えるものではありません。設計を始めてシステムが実際にどのように動作するか説明します。設計していくと脚立のイメージが現れ始めます。

すべての定義は概念的な言葉で書かれており、下位レベルのコンポーネントの用語集を使用しているため、Forthは区別を少しあいまいにします。 実際、この章の後半では、概念モデルの解決策を説明するためにForthの「擬似コード」を使用します。

それでも、区別することは有用です。 概念モデルはデザインよりも柔軟性があります。 設計よりモデルに要件と制約を適合させる方が簡単です。

ヒント

設計を始める前に、しっかりした概念モデルを構築するようにしてください。

分析とは、要件定義の概念モデルへの拡張です。これには、モデル記述のための連続した試行の最中の、顧客との双方向コミュニケーションを含みます。

開発サイクル全体と同様に、分析フェイズは反復的にアプローチするのが最善です。それぞれの新しい要求はあなたの頭の中で何かを提案してくる傾向があります。あなたの仕事は、要求にフィットできるまですべての要件と制約を調整することです。

_images/fig2-2.png

図 19 分析のための反復的アプローチ

図 19 は分析フェイズのための反復的アプローチを表しています。 最後のステップは最も重要なものの1つです。それは文書化されたモデルを顧客に見せることです。 あなたの理解を顧客に伝え、必要なフィードバックを得るために必要なコミュニケーション手段(図、表、またはイラスト)を使用してください。 この繰り返しを100回繰り返すことになっても努力する価値はあります。

以下の3つの節では、概念モデルを定義し文書化するための3つの手法を探ります。

  1. インターフェイスの定義
  2. 規則の定義
  3. データ構造の定義

インターフェイスの定義

ヒント

最初に、そして最も重要なこととして、概念モデルはシステムのインターフェースを記述するべきです。

テレスカは言います。

「仕様」は基本的には「何か」を扱います。そのもっともすばらしい形で、それはシステムがユーザにどのように見えるかを説明します。あなたはそれをユーザマニュアルと呼ぶかもしれません。私は内部の仕事を成し遂げる部分よりも、外側から見える人間との対話について多くのメモを残しているのが判ります。たとえば、特定のエラーが発生したときに何が起こるかを示すために、エラー対応表全体を含めます。 不思議なことに、これはとにかく実装に最も時間がかかる部分です。

私は現在、半導体工業用洗浄機のタイマーに取り組んでいます。 この場合、ユーザインターフェイスはそれほど複雑ではありません。 複雑なのは洗浄機へのインターフェースで、私は顧客と彼らが提供できる文書に頼らなければなりません。

重要なインターフェースは何であれ製品の手足です。 初期の段階では、ハードウェアとソフトウェアを区別しません。 それらは実装の段階で入れ替えることができます。

ハードウェアを設計するプロセスとソフトウェアを設計するプロセスは類似しています。 私がハードウェアを設計する方法は、それをブラックボックスとして扱うことです。 前面パネルは入出力です。 ソフトウェアも同様にできます。

私は、製品が為すすべきことの説明を使用して、入力と出力がどのように見えるかを顧客に示すためにあらゆるテクニック、図表などを利用します。 しかし並行して、私自身の頭の中では、それがどのように実装されるかを想像しています。 効率的にできるかどうかを評価しています。 だから私にはブラックボックスではなく、グレーのボックスです。 設計者はブラックボックスの内側を見ることができなければなりません。

別個のモジュールを使ったシステムを設計するときは、連結が合理的かつ可能な限り少なくするようにします。あなたは自身の理想を危うくしていますが、しかし、常にギブ&テイクはあるものです。

文書には、DFD(データフロー図、後で説明します)、および顧客に提示できるその他の表現を使用します。 理解を明確にするために、できるだけ多くの図を提示しています。 実装になると、私は一般的にこれらを使用しません。 図表を参照せずとも、文章は完全でなければなりません。

ヒント

インタフェースの定義の一部として、エラー処理と例外処理を早期に決定してください。

コーディングするとき、プログラマはまず「正常」な条件下でコードを正しく実行することに集中し、その後でエラー処理について心配することがよくあります。 しかし、誰かのために働くときは、エラー処理は前もって解決されるべきです。 これは初心者プログラマが見過ごしてしまいやすい分野です。

この段階でエラー処理を決定する事がそんなに重要な理由は、どのようにエラーを扱うかが広範囲に渡るためです。とあるエラーでは以下のような対処方法があります。

  • 無視
  • エラーが発生した事を示すフラグがセットされているのに処理を続行
  • アプリケーションをアボートさせる
  • 問題を正としてプロシージャを開始し、プログラムを実行し続けるような設計

早い段階でエラー処理がどの程度複雑かはっきりさせないと、プロジェクトチーム内で深刻なコミュニケーションのギャップが生じる可能性があります。 明らかに、この選択はアプリケーションの設計と実装に多大な影響を与えます。

ヒント

データが通過して、モデルの各部分が実行されるのを想像して概念モデルをを開発します。

「構造化分析」 [weinberg80] と呼ばれる分野では、顧客が理解しやすい方法でインターフェースを記述するためのいくつかの技法を提供しています。 これらの手法の1つが、テレスカが言及した「データフロー図」(DFD)です。

_images/fig2-3.png

図 20 データフロー図

図 20 のように描かれるデータフロー図は、データ項目がシステム内をめぐるときに何が起こるかを強調します。 円は「変換」を表し、情報に基づいて機能します。 矢印は変換の入力と出力を表します。

この図は、動作中のシステムのとある瞬間を表しています。 初期化、ループ構造、およびその他時間の流れが絡む詳細は無視されます。

DFDを使用すると、以下の3つの利点があります。

第一に、その図はシンプルで直接的な言葉で顧客に語ります。 顧客があなたのデータフロー図の内容に同意すれば、あなたは問題を理解していると言えます。

第2に、それはあなたに、手続き的に「どのようにするか」に巻き込まれずに、論理的に「何か」という観点から考えさせます。これは前の章で説明したように、情報隠蔽の哲学と一致します。

第3に、それらはシステムへのインターフェースとモジュール間のインターフェースにあなたの注意を集中させます。

しかし、Forthプログラマは、顧客の便宜を図る時を除いてDFDを使用することはめったにありません。 Forthは概念モデルの観点から考えることを奨励し、Forthが暗黙的にデータスタックを使用することで、モジュール間でのデータの受け渡しが非常に簡単になり、通常は当然のことと考えられます。 これは、適切に使用されているForthが関数型言語に近づいているためです。

Forthに数日も触った人なら、シンプルな定義は図と同じくらい分かりやすいです。

: REQUEST  ( quantity part# -- )
   ON-HAND?  IF  TRANSFER  ELSE  REORDER  THEN ;
: REORDER   AUTHORIZATION?  IF  P.O.  THEN ;
: P.O.   BOOKKEEPING COPY   RECEIVING COPY
   VENDOR MAIL-COPY ;

これはForth擬似コードです。 どの値が実際にスタックに渡されるかを決定するための努力はなされていません。なぜなら、それは実装の詳細だからです。 REQUEST のスタックコメントは、プロセスを開始するのに必要な2つのデータ項目を示すためだけに使われています。

(私がこのアプリケーションを設計していたならば、私はユーザインターフェースには NEED というワードがよいと思います。これは以下の構文を持ちます。

NEED 50 AXLES

NEED は数量を数値に変換しスタックに置き、文字列 AXLES も部品番号に変換してスタックに置きます。そして、 REQUEST を呼び出します。このようなコマンドは最も外側のレベルでのみ定義されるべきです。)

ムーアプロダクツ社のジョンソンがForth疑似コードについて少々。
IBMでは厳密に文書化されたPDL(プログラム設計言語)を使用します。 私たちはここでもPDLを使います。なお、Forth設計言語はFDLと呼びます。これらの全ての規格には価値はありますが、一度あなたがForthに慣れたら、Forth自身を設計言語にすることができます。あなたはForth設計言語から「ノイズ」と言われるワード、つまり C@, DUP, OVER, 等を省く必要があります。そして基本的な流れだけを表します。殆どのForthユーザはおそらくそれを非公式に行っています。私たちはそれを公に行います。
私たちはインタビューで、ムーアに、概念モデルを計画するために何らかの図表を使用したのか、それとも直接Forthでコーディングしたのかを尋ねました。彼の返事です。

概念モデル=Forthです。長年の経験から、私はそのように考えることを学びました。

誰もがそのように考えることを学べますか?

私には不公平な優位があります。私は自身のプログラミングスタイルを体系化し、他の人々がそれを採用しました。私はこのことにびっくりしました。人が私のスタイルをエミュレートするために学ぶのは素敵に思えます。彼らは私が考えるように考えることを学べますか、という質問には、私は可能だと思います。それは単に訓練の問題です。私はたくさん訓練してできるようになりました。

規則の定義

問題を定義するための努力のほとんどはインターフェイスの説明に集中することになるでしょう。アプリケーションによってはアプリケーション規則の組を定義する必要があります。

すべてのプログラミングは規則を含みます。 通常、これらの規則は非常にシンプルなので、どのように表現するかはほとんど問題になりません。例えば「誰かがボタンを押した場合は、ベルを鳴らしてください。」のように。

ただし、アプリケーションによっては、規則が非常に複雑で、短文では表現できないものもあります。 これらのより複雑な規則を理解し文書化するのに、いくつかの技法が役立つことがあります。

一例として、私たちが欲しいのは、長距離電話の通話料金を計算するシステムです。以下がその料金体系の説明です(これを書いたのは私ですが、電話会社が客にふっかける料金の計算を、実際にどのように計算するのかは知りません)。

全ての料金は、数百マイルの距離に応じて分単位で計算される。加えて定額料金がある。平日の午前8時から午後5時の間の、直通ダイヤル通話の固定料金は、最初の1分が30セント、追加の各1分で20セント(".20")。加えて、100マイルごとに12セント(".12")を各1分ごとに課金します。平日の午後5時から午後11時の間の、直通ダイヤル通話の固定料金は、最初の1分が22セント(".22")、追加の各1分で15セント(".15")。距離に応じた料金が100マイル当たり1分12セント(".12")かかります。平日の午後11時以降か、土曜日・日曜日・祝祭日の終日は、最初の1分が12セント(".12")、そして追加の各1分が9セント(".09")。距離に応じた料金が100マイル当たり1分6セント(".06")かかります。電話オペレータを頼んだ場合、時間に関係なく固定料金が90セント(".90")増加します。

この説明は普通の文章で書かれていて、かなり饒舌です。この文章を追うのは大変で、そして、ガラクタがぎっしり詰まった屋根裏部屋のように、いくつものバグを隠しているかもしれません。

このシステムのための概念モデルを構築する際には、明確で有用な方法で料金構造を記述する必要があります。 雑然としたものを整理するための最初のステップは、無関係な情報を取り除くことです。 この文章を2つに分割することで、大幅に改善できます。 まず、時刻規則があります。

平日の午前8時から午後5時の通話は「full」料金です。平日の午後5時から午後11時の通話は「lower」料金です。平日の午後11時以降と土曜日・日曜日・祝祭日の終日は「lowest」料金です。

それから料金構造自体として、「最初の1分料金(first-minute rate)」、「追加の各1分料金(additional minute rate)」、「距離による料金distance rate)」、「電話オペレータ料金(operator-assistance rate)」の観点から説明する必要があります。

ヒント

要因とは果物と説く。その心は、「りんごとオレンジを混同しないでください」

しかし、これらの文章はまだ読みにくいです。 システム分析者は、構造化された文章、決定木、決定表など、これらの文章を単純化するためにいくつかの手法を使用します。 これらの各技法を調べて、Forth環境におけるそれらの有用性を学びましょう。

構造化文章

構造化文章(Structured English)は一種の構造化疑似コードで、料金の文章は次のようになります。

IF full rate
   IF direct-dial
      IF first-minute
     .30 + .12/100miles
      ELSE ( add'l- minute)
     .20 + .12/100miles
      ENDIF
   ELSE ( operator )
      IF first-minute
     1.20 + .12/100miles
      ELSE ( add'l- minute)
     .20 + .12/100miles
      ENDIF
   ENDIF
ELSE  ( not-full-rate)
   IF lower-rate
      IF direct-dial
     IF first-minute
        .22 + .10/100miles
     ELSE ( add'l- minute)
        .15 + .10/100miles
     END IF
      ELSE ( operator)
     IF first-minute
        1.12 + .10/100miles
     ELSE ( add'l- minute)
        .15 + .10/100miles
     ENDIF
      ENDIF
   ELSE ( lowest-rate)
      IF direct-dial
     IF first-minute
        .12 + .06/100miles
     ELSE ( add'l- minute)
        .09 + .O6/100miles
     ENDIF
      ELSE ( operator)
     IF first-minute
        1.02 + .O6/100miles
     ELSE ( add'l- minute)
        .09 + .06/100miles
     ENDIF
      ENDIF
   ENDIF
ENDIF

これは単にめんどくさいだけです。読むのが難しく、保守が難しく、書くのが一番難しく、しかも実装時には意味がありません。もうクチにするのも嫌です。

決定木

_images/fig2-4.png

図 21 決定木の例

図 21 は電話料金の規則を表す決定木(decision tree)です。決定木は、条件分岐に従って書くのが最も簡単な方法です。このため、顧客に見せる最も良い表現かもしれません。

残念ながら、どの条件がどの条件を生み出すか決めるために、決定木で追跡するのは困難です。これが問題を単純化して見せる事を妨げます。この「木」は電話オペレータが補助しているかどうかにかかわらず、追加の分にかかる費用が同じであるという事実を覆い隠しています。あなたは「木」の事実を見ることはできません。

決定表

以下に説明する決定表(decision table)は、プログラマにとって、そして場合によっては顧客にとっても、最も有用な複合規則の図表です。 図 22 は、決定表の形で電話料金規則の構造を表しています。

_images/fig2-5.png

図 22 決定表

図 22 には3つの次元があります。割引率、電話オペレータを使うかどうか、最初の1分対追加の分、です。

紙に二次元を超える問題を描くのは少し難しいです。ご覧のように、これらの追加の次元は外側の次元の中のサブ次元として紙に描く事ができます。サブ次元の全ての条件は、外側の次元の全ての条件内に表示されます。ご存知のとおり、ソフトウェアでは、任意の数の次元を簡単に処理できます。

私たちがこれまでに説明した全ての手法を使って、どの条件がどの次元に適用されるかを分析しなければなりません。これらの次元のファクタリング(要素分解)には次の2つの規則が適用されます。

第一に、各次元のすべての要素はお互い排他的でなければなりません。「直通ダイヤル」と同じ次元に「最初の1分」を入れないでください。これらは相互に排他的ではないからです。

第二に、すべての可能性が各次元内で説明されなければなりません。 午前2時から午前2時5分間にかけられた通話に別の料金がある場合、表を拡大する必要があります。

しかし、決定表には他の利点もあります。決定表は顧客が読みやすいだけでなく、以下の通り、実際に幾つかの点で実装者に利益をもたらします。

実際のコードに変換が容易
これは、決定表が、図表とよく似た形式で、簡単に実装出来るForthに特に当てはまります。
ロジックを上流に向かって追跡
条件を探して、そしてそれがどのような要因で引き起こされたのかを調べます。
より明確な図絵的表現
決定表は実装者にとっても分析者にとっても理解のための良いツールとして役に立ちます。

決定木と異なり、決定表は「結果」を図表的に意味のある方法でグループ化します。 考えを視覚化することで、問題、特に複雑すぎて直感的に認識することができない問題を理解するのに役立ちます。

例えば、 図 22 は、追加の分の料金が電話オペレータを使ったどうかに依存しないことを明確に示しています。この新しい理解により、私たちは 図 23 に示すように、単純化した表にすることができます。

_images/fig2-6.png

図 23 単純化した決定表

問題について考えることを忘れるぐらい分析ツールに夢中になります。構造化分析に関する本の著者が推奨するように、分析者は問題の全ての可能性をn番目の程度まで実行する以上のことをしなければなりません。そのアプローチは詳細を増やしてまいます。また問題解決者は問題の単純化を試みねばなりません。

ヒント

問題を単純化できるまでは、あなたは問題を理解していません。

分析の目的が理解だけではなく単純化である場合は、おそらく更なる作業が必要です。

私たちの修正された決定表( 図 23 )はマイルあたりの料金が料金が「full」か「lower」か「lowest」かによってのみ決まることを示しています。 つまり、表に示されている3つの次元のうちの1つだけが適用されます。 図 24 のように、この表を2つに分割するとどうなるでしょうか?

_images/fig2-7.png

図 24 分割した決定表

今度は、表のルックアップと計算の組み合わせによって答えを得ています。 1分あたりの料金の式は、擬似Forth定義として表すことができます。

: PER-MINUTE-CHARGE ( -- per-minute-charge)
        CONNECT-CHARGE  MILEAGE-CHARGE  + ;

「+」は、表に9回現れるのではなく、定義内に1回だけ表示されます。

計算の本質化をさらに一歩進めて、電話オペレータの使用が合計料金に対して1回だけ90セント(".90)を追加するだけであることに注意します(または元の、問題の文章から思い出してください)。 この意味で、電話オペレータ料金は3次元のいずれの機能でもありません。 それはより適切には「論理演算」として表現されます。つまり、論理と算術を組み合わせた機能です。

: ?ASSISTANCE
   ( direct-dial-charge -- total-charge)
   OPERATOR? IF .90 + THEN ;

(しかし思い出して下さい。この料金は最初の1分にのみ適用されます。)

_images/fig2-8.png

図 25 電話オペレータ料金無しの決定表

図 25 に示す単純化された表と、信頼できる計算表現が残りました。今、私たちはとりあえず何処かに到着しました。

話を PER-MINUTE-CHARGE に戻しましょう。

: PER-MINUTE-CHARGE ( -- per-minute-charge)
   CONNECT-CHARGE  MILEAGE-CHARGE  + ;

接続料金(connection charge)とマイレージ料金(mileage charge)の規則についてより具体的に説明しましょう。

接続料金は、最初の1分か追加の分かによって異なります。1分当たりの料金は2種類あるので、おそらく、 PER-MINUTE-CHARGE を2つの異なるワードに書き換えるののがもっとも簡単でしょう。

表から適切な料金を取得するコンポーネントを作成するとしましょう。 1MINUTE というワードは最初の1分間のレートを取得します。 +MINUTES は追加の分ごとに料金を得ます。 これらの語句は両方とも、fullレート、lowerレート、またはlowestレートのいずれかを使用するか決定するため、時刻に依存します。

これで、以下の通り、 PER-MINUTE-CHARGE を置き換える為のワードのペアを定義できます。

: FIRST  ( -- charge)
  1MINUTE  ?ASSISTANCE   MILEAGE-CHARGE + ;
: PER-ADDITIONAL  ( -- charge)
   +MINUTES  MILEAGE-CHARGE + ;

マイレージ(mileage)料金の規則は? とてもシンプルです。それは料金レート(100マイル当たり) × (100マイル単位の)マイル数です。以下のように、表からマイレージ料金レートを取得する、 MILEAGE-RATE というワードを定義できるとしましょう。

: MILEAGE-CHARGE  ( -- charge)
   #MILES @  MILEAGE-RATE * ;

最後に、通話の合計分数がわかっている場合は、直通ダイヤル通話料金の合計を計算できます。

: TOTAL   ( -- total-charge)
   FIRST                        ( first minute rate)
   ( #minutes) 1-               ( additional minutes)
      PER-ADDITIONAL *          ( times the rate)
   +  ;                         ( added together)

最後に、この特定の問題に対する規則は、単純な表と論理演算を組み合わせて表現しました。

(この例に関する最後の注意:実行中のForthアプリケーションに非常に近いものを書きました。ただし、これは疑似コードにすぎません。コメントが示す場所には値がスタックにあると仮定してスタック操作を避けました。 実際のコードでは短い名前が好まれます。 第5章 参照)。

完全なコードは 第8章 にあります。

データ構造の定義

インターフェイスを定義し、しばしば規則を定義した後、ときには特定のデータ構造も定義する必要があります。 ここでは、データ構造の実装についてではなく、それらの概念モデルの説明について説明します。

たとえば、図書館蔵書検索の自動化をしている場合、分析の重要な部分は、論理データ構造の開発に関係します。書籍ごとにどの情報を保存するかを決定する必要があります。タイトル、作者、主題など。これらの「属性」は、 BOOKS と呼ばれる「エンティティ」(一連の関連レコード)を構成します。 それから、ユーザーが効率的に BOOKS を検索できるようにするために、他にどのようなデータ構造が必要になるかを決定しなければなりません。

_images/img2-060.png

図 26 2つの妥当な解決策が与えられたら、正解はよりシンプルな方です。

特定の制約はデータ構造の概念モデルにも影響します。 図書館蔵書検索の例では、ユーザが必要とする情報だけでなく、ユーザがそれを入手するのを待つ時間も知っておく必要があります。

たとえば、出版年ごとに話題のリストを要求することができるとします。例えば、1900年から1910年の間の女性のランジェリーに関するすべてとか。もしそれがガードルのホックについての情報を期待しているなら、あなたは何年も掛けて詳細に話題を索引化しなければなりません。もし、あなたがまる一日待つことができるのであれば、図書館にあるすべての本をコンピュータに検索させることもできます。

シンプル化の成就

ヒント

シンプルさを保って下さい。

あなたが問題を理解するために、肝心の最初のステップを踏み出す時、以下のことわざを覚えておいてください。

2つの解決策が与えられた時は、正解は、よりシンプルな方です。

これは特にソフトウェア設計に当てはまります。 よりシンプルな解決策は、発見が困難なことが多いですが、発見できると様々な利点があります。

  • 理解するのが簡単
  • 実装するのが簡単
  • 検証とデバッグが簡単
  • 保守が簡単
  • もっとコンパクトに
  • もっと効率的に
  • もっと楽しく
シンプルさの最も説得力のある支持者の一人はムーアです。

あなたは問題の大きさを感じる必要があります。モノを実装するのにどれぐらいのコードが必要ですか?1ブロック?それとも3ブロック? そう感じる事は、とても便利な設計ツールだと考えます。それがささいな問題なのか、それとも大きな問題なのか、どれだけの時間と労力を費やすべきか、あなたが本質を感じる事を欲します。

あなたが作業を終えたら、振り返りして「私は合理的な解決策を考え出しただろうか?」と自分に問いかけます。もしあなたの解決策が6スクリーンに渡るのなら、それはあなたが蚊を殺すために大ハンマーを使った事があるのかもしれません。あなたの頭の中のイメージは問題の重要性に比例していません。

私はFORTRANで書かれた何十万行の核物理学プログラムを見たことがあります。そのコードが何するにしても、数十万行のコードを正当化する訳ではありません。おそらくそのプログラムの作者は問題を過度に一般化しています。彼らは大きな問題を解決しましたが、本当に必要なのはそのサブセットだけです。彼らは解決策が問題に一致するはずであるという原則に違反しています。

ヒント

一般化する事は通常、複雑さを伴います。 必要以上にあなたの解決策を一般化しないでください。 代わりに、変更可能にしてください。

ムーアは続けます。

課題が与えられたら、あなたはその解決策をコーディングできます。そうしたあと、それに明らかに不快な点を見つけたなら、あなたは前の段階に戻って課題を変更する事ができ、そしてよりシンプルな解決策に仕上げる事ができます。

「心配しない」状況を利用する、装置最適化(回路中のゲート数を最小化する)クラスがあります。それは実際には発生しないか、あるいは本当にあなたが心配しない為に起こります。でも、プログラミングを理解していない人々はしばしばこんな仕様を書きます。設計者は全ての場合を注意深く指定しているかも知れませんが、プログラマであるあなたにどれが本当に重要であるか伝えていないのかもしれません。

もしプログラマのあなたが前に戻って設計者の彼と議論し「心配しない」仕様を利用できるなら、あなたはもっと簡単な解決策を思いつく事ができます。

技術的なアプリケーションを使って、75トン金属粉プレスのように物事を打ち切って下さい。彼らは、以前使用されていた油圧制御の代わりに、コンピュータ制御バルブを設置したい。あなたはプレス機エンジニアからどのような仕様を得ますか?電気機械的な観点からセンサーは暫定的に設置されている可能性が最も高いものです。しかし今、彼らはそれをちゃんとした場所に移設できていました。が、プレス機エンジニアはそれを失念しているようです。あなたが説明を求めるなら、彼らプレス機エンジニアの想像の世界のモデルから遠ざかり現実の世界に近づく事ができます。

もう1つの例は、サーボ用のPID(比例積分微分)アルゴリズムです。 統合する1つの項、微分化する別の項、および平滑化する3番目の項があります。 あなたは30%の統合と10%の微分化とそれ以外を組み合わせます。 しかし、それはデジタルフィルタだけです。アナログの時代には、デジタルフィルタの特定の項を「これは積分器で微分器です。コンデンサでこれを作り、インダクタでそれを作ります。 」とできて便利でした。

再び、仕様を書く人は、電気機械的な解決策をモデル化した、アナログの解決策をモデル化するでしょう。そしてそれらは現実から隔たったモデルです。実際には、デジタルフィルタの2つまたは3つの係数ですべて置き換えることができ、はるかにクリーンでシンプルで効率的な解決策を実現できます。

ヒント

顧客がそれを解決しようとする前に、問題が何であったかに戻ってください。「気にしない」を利用します。

_images/img2-063.png

図 27 過度の一般化解決策

ムーアは続けます。

単純化の可能性がすぐには明らかにならない場合があります。

CADシステムのようなデジタル化されたグラフィックディスプレイでズーミングするというこの問題があります。 あなたは画面に絵を持っています、そしてあなたは詳細を見るために一部分にズームインしたいです。

カーソルを目的の位置に移動してからボタンを押すと、目的のサイズのウィンドウが表示されるまでズームします。 それが私がいつもやっていた方法です。 それが愚かだと気づくまでは。 私はそのような細かい解像度でズームする必要はありませんでした。

一度に1ピクセルずつカーソルを移動するのではなく、例えば10ピクセルずつジャンブさせます。そして箱の大きさをじわじわ増加させる代わりに、箱を段階的に大きくします。拡大率の選択肢はありません。4倍にズームします。中間の倍率には興味がありません。拡大は好きなだけ何度でもできます。

物事を大胆に量子化することで、作業が簡単になり、応答が良くなり、シンプルになります。

ヒント

シンプルに、量子化します。

ムーアは結論づけます。

「本当はこの意味では言ってませんでした」または「このページを外してこの表現に置き換えてもよろしいですか」と言って戻るのは傲慢です。顧客はいらいらします。顧客は、あなたに言ったとおりに、あなたがするのを求めます。

ラハール・スチュアートはForthを再設計したときにこのような態度を取りました。 [stuart80] 彼は入力バッファが好きではなかったので、彼はそれなしでForthを実装し、そして彼は本当に、入力バッファが必要でないことを発見しました。

あなたが問題を改善することができるならば、それは没頭するのが素晴らしい状況です。 実装よりも世界を再設計するほうが、はるかに楽しいです。

効果的なプログラマは、「これをこれに置き換えることの結果はどうなるのでしょうか」などと、危険を冒さない方法で、自分たちのアプローチを巧妙にし、指導することを学びます。

問題を単純化するもう1つの方法は以下です。

ヒント

シンプルにすることで、ユーザをトラブルから守って下さい。

ワープロの一部として、保存した文書のファイル名を1行に1つづつ画面に表示するよう設計しているとします。ユーザが任意の文書の名前の隣にカーソルを移動してから、選択したアクションを示す1文字のコマンドを入力するよう計画します。印刷の場合は「p」、編集の場合は「e」などです。

最初は、画面上の任意の場所にユーザがカーソルを移動できるようにしても問題ありません。 つまり、テキストがすでに表示されている場所は上書きされないように保護する必要があります。 これは、「保護フィールド」と特別な処理の概念を意味します。 より簡単なアプローチでは、カーソルを特定のフィールドに限定し、場合によってはユーザーに許容フィールドのエリアを表示させるために反転表示を使用します。

別の例は、アプリケーションがユーザに数値の入力を求めるときに発生します。 Enter を押すまで入力をチェックしないアプリケーションがよくあります。そのときには「invalid number」などのエラーメッセージが表示されます。タイプした各キーが数字以外の時は表示を許さないようチェックする方がもっと簡単です。

ヒント

簡単にするために、利用可能なものを利用してください。

ニューヨーク州ロングアイランドのForthプログラマ、Michael LaMannaは次のようにコメントしています。

私はいつも自分が手に入れることができる最も強力なプロセッサでアプリケーションを設計しようとします。 68000ベースのシステムと6809ベースのシステムのどちらで開発するかを選択できる場合は、68000ベースのシステムを選択してください。 プロセッサ自体は非常に強力なので、他の方法で解決しなければならない可能性がある多くの詳細をプロセッサで処理できます。

後で戻ってアプリケーションの一部を単純なプロセッサ用に書き直す必要がある場合は、問題ありません。 少なくとも私は自分の時間を無駄にしていないでしょう。

注意:試作を簡素化するために既存のコンポーネントを使用している場合は、そのコンポーネントが設計に影響を与えないようにしてください。 設計がコンポーネントの内部に依存しないようにする必要があります。

予算とスケジュール

分析段階のもう一つの重要なフェイズは、値札を付ける事です。繰り返しますが、このプロセスは予想以上に困難です。 あなたがその問題を解決するまで、あなたはその問題を知らないのに、あなたがそれを解決するのにどのくらい時間がかかるかを、どのようにして知ることができるのでしょうか?

物事は常にあなたが予想よりも時間がかかるので、慎重な計画が不可欠です。 確率の法則に基づいて、これについての理論があります。

_images/img2-066.png

図 28 紋切り型の知恵は複雑さを崇拝する

ヒント

アプリケーションにたった「2時間」追加する作業は、おおよそ12時間に膨れ上がります。

次のようなシナリオを想像してみてください。あなたが大きなアプリケーションを書いている最中に突然、比較的単純な機能を追加しようとしています。 あなたはそれが約2時間かかると思うので、それ以上の計画なしで、あなたはそれをするだけです。 検討してください。それは2時間のコーディング時間です。 アプリケーションの作業をしている間、必要性と設計をすばやく感じ取ることができたので、設計時間はカウントされません。 それであなたは2時間を見積もります(設計0時間、実装2時間)。

しかし、以下の可能性を考えてください。

  1. あなたの実装にはバグがありました。 当初見積の2時間経ってもうまくいかない。 それで、あなたはもう2時間見積を増やします(計4時間)。
  2. また、実装する前に、最初の設計(0時間)ではうまくいかないことに気付いたとします。再設計には2時間かかります。更に再設計に基づいて2時間かけてコーディングします(計4時間)。
  3. または、最初の設計が機能しないことに気付く前に、最初の設計で実装済(0+2時間)でした。 それで、あなたは再設計し(2時間)そして再実装します(2時間)。(計6時間)
  4. または、最初の設計(0時間)をコーディング(2時間)し、バグを見つけてコードを書き換え(2時間)、デザインの欠陥を見つけ、再設計し(2時間)、再コード化し(2時間))、新しいコードでバグを見つけ、再コード化(2時間)します。(計10時間)

まるで雪玉ですね。

  1. そして今、あなたの新機能を文書化しなければなりません。 上記に2時間を加えます。 (合計12時間)
  2. 2〜12時間かけて新しい機能を組み込んでしてデバッグした後、突然、アプリケーションの要素Yが破壊されることに気付きました。 さらに悪いことに、理由はわかりません。 あなたはその理由を理解しようとして、メモリダンプを読むのに2時間を費やします。 そうすると、要素Yの再設計にさらに12時間かかる(合計26時間)。次に、要素Yに対して行った構文の変更を文書化する必要があります(合計27時間)。

3人日以上の工数になってしまいました。これらすべてが一度にあなたを襲ったのだったら、あなたは精神科に掛かるでしょう。 もちろん、これほど悪くなることはめったにありませんが、どのプロジェクトでも、あなたの予想どおりに簡単である勝率は高くありません。

所要時間を正しく判断する可能性はどのように向上させることができますか? この話題については、特にフレデリック・ブルックスが表した「人月の神話」 [brooks75] など、多くの素晴らしい本が書かれています。 個人的な見解を除いて、私はこの知識体系に追加することはほとんどありません。

  1. 合計で推測しないでください。 問題をできるだけ小さい部分に分割してから、各部分の時間を見積もります。 ピースの合計は常に、合計で予想するよりも大きくなります(全体が部分の合計よりも少ないように見えます)。

  2. 項目を箇条書きにする際には、推測の余地が無いほど充分に理解しているものと、そうでないものを分けてください。2番目のカテゴリでは、顧客に範囲を与えます。

  3. ちょっとした心理学:常に顧客にいくつかの選択肢を与えなさい。 顧客は「オプション」が好きです。 「これは6,000ドルかかる」と言えば、顧客は「私は本当は4,000ドルで済ませたいのです」と答えます。これは、あなたを受け入れるか、仕事なしで行くという立場にあなたを置きます。

    そこで顧客に言います、「あなたが選んで下さい。4千ドルなら私はすたすた歩いて輪くぐりします。6千ドルなら私はジャンプして輪くぐりします。8千ドルなら私は旗を振りかざし踊りながら輪くぐりします。」

    ほとんどの顧客はジャンプして輪くぐりする事を選びます。

ヒント

考えることも含め、すべてがあなたが思うよりも時間がかかります。

概念モデルのレビュー

The final box on our iterative analytic wheel is labeled “Show Model to Customer.” With the tools we’ve outlined in this chapter, this job should be easy to do.

要求仕様を文書化する際には、仕様は雪だるまのようなものであることを忘れないでください。 それらは今凍っているかもしれませんが、熱があるときそれらは移動し、滑り、そして溶け去ります。 データフロー図を選択する場合でも、まっすぐなForth擬似コードを選択する場合でも、冗長性制限の概念を適用することを忘れないでください。

文書化された概念モデルを顧客に見せ、顧客が最終的に満足したら、次の大きなステップ、設計への準備が整います。

参考文献

[harris81]Kim Harris, "The Forth Philosophy," Dr. Dobb's Journal, Vol. 6, Iss. 9, No. 59 (Sept. 81), pp. 6-11.
[weinberg80]Victor Weinberg, Structured Analysis, Englewood Cliffs, N.J.: Prentice-Hall, Inc., 1980.
[stuart80]ラハール・スチュアート(LaFarr Stuart), "LaFORTH," 1980 FORML Proceedings, p. 78.
[brooks75]人月の神話 新装版;滝沢 徹、牧野 祐子、富澤 昇 訳;丸善出版;2010.12;ISBN:978-4-621-06608-9(Frederick P. Brooks, Jr., The Mythical Man-Month, Reading, Massachusetts, Addison-Wesley, 1975.)