web-dev-qa-db-ja.com

トップダウンまたはボトムアップの設計が望ましいですか?

私が理解しているように、トップダウン設計は、最小のビルディングブロックが定義されるまで、抽象的な高レベルの概念をより小さな具体的でわかりやすい部品に洗練することです。一方、ボトムアップは低レベルのパーツを定義し、システム全体が形成されるまで徐々に高レベルのブロックを構築します。

実際には、2つの方法を組み合わせるのが最善とされています。まず、ドメインの知識、その関係、および制約を完全に指定するための高レベルの仕様から始めます。問題がよく理解されると、システムを構築するための最小のビルディングブロックが作成されます。

のプロセス:

  • 要件仕様の作成
  • 設計仕様を(図を使用して)作成する
  • 実装する
  • 届ける
  • 繰り返し(反復的な開発では、各フェーズでチャンク全体を実行するのではなく、少しずつ繰り返し実行し、お客様の動的な要件に適応するために毎日会議を行います)

私には完全に正常に見えます(仕様として計画を立てて)それには欠点がありますが、私たちが反復的な開発を行ったのはそのためです。1つのフェーズに時間を費やすのではなく、変化にさらされる(おそらく毎日)ドメイン知識のすべての可能なことを研究するための要件分析では、少し分析します、少し設計してから実装します。

別の方法は、各反復がミニウォーターフォール方式であり、分析が数日(または1週間)で行われることです。同じことがデザインにも当てはまります。残りの時間は実装に費やされます。反復的な開発と組み合わせたトップダウンアプローチには、本質的に何か問題がありますか?

彼のエッセイ Programming Bottom Up で、Paul Grahamは、ボトムアップから完全にビルドすること、またはボトムアップからプログラムすることを推奨しているようですが、要件分析/設計フェーズではありません。

経験豊富なLISPプログラマーは、プログラムを異なる方法で分割します。トップダウン設計と同様に、それらはボトムアップ設計と呼ぶことができる原則に従います-問題に合わせて言語を変更します。

私の知る限り、彼が意味することは、Lisperは依然としてトップダウン設計を実行しますが、プログラムはボトムアップですが、それは本当ですか?彼が書いた別のポイント:

ボトムアップ設計は、同じプログラムを異なる順序で書くだけではないことを強調する価値があります。ボトムアップで作業すると、通常は別のプログラムになります。単一のモノリシックプログラムの代わりに、より抽象的な演算子を備えたより大きな言語と、それに記述されたより小さなプログラムが得られます。まぐさの代わりに、あなたはアーチを得るでしょう。

これは、LISPでプログラムを作成している間、最終的に汎用ツールになるということですか?

32
Amumu

トップダウンは、知っていることを説明したり、すでに構築したものを再構築したりするのに最適な方法です。

トップダウンの最大の問題は、「トップ」がないことが非常に多いということです。システムの開発中およびドメインの調査中に、システムが何をすべきかについて考えを変えるでしょう。どのようにして、あなたが知らない何か(つまり、システムに何をしてほしいか)の出発点になることができますか?

「ローカル」のトップダウンは良いことです...コーディングの前に考えている人もいるでしょう。ただし、考えすぎているのは現実のシナリオではないため、考えすぎたり計画を立てすぎたりすることはありません(以前にそこに行ったことがない場合、つまり、構築せずに再構築している場合を除きます)。新しいものを構築する際のグローバルなトップダウンはナンセンスです。

問題の100%がわかっていなければ、ボトムアップ方式が(全体的に)アプローチでなければなりません。コーディングする既知のソリューションだけが必要であり、可能な代替ソリューションを探す必要はありません。

LISPアプローチは、蒸留されたボトムアップです。あなたはボトムアップを構築するだけでなく、あなたが彼らが必要とするようにレンガを形作ることもできます。何も修正されておらず、自由は完全です。もちろん自由には責任があり、この力を悪用することで恐ろしいことをすることができます。

しかし、恐ろしいコードはどの言語でも書くことができます。心の檻のような形をした言語でさえ、それらの言語でサルでさえ良いプログラムを実行できるように設計されています(非常に多くのレベルで間違っているので、考えるだけでも痛いです)。

あなたの例はウェブサーバーについてです。 2012年には、これは明確に定義された問題であり、従うべき仕様があります。 Webサーバーは単なる実装上の問題です。特に、そこにある他の膨大な数のWebサーバーと実質的に同一のWebサーバーを作成することを目的としている場合、いくつかの特徴点を除いて、何も実際には不明確です。 RSAについてのあなたのコメントでさえも、正式に定義された明確に定義された問題について話している。

明確に定義された問題、正式な仕様、および既知のソリューションでは、コーディングはドットで接続されています。トップダウンで問題ありません。これはプロジェクトマネージャーの天国です。

しかし、多くの場合、ドットを接続するために使用される実証済みのよく知られたアプローチはありません。実際、ドットが何であるかさえ言うのは非常に困難です。

たとえば、自動切断機に、カットするパーツを理論上の繰り返しロゴに完全には適合していない印刷物に合わせるように指示されたとします。機械で撮影した素材の部品と写真が提供されます。

配置規則とは何ですか?あなたが決める。パターンとは何ですか、それをどのように表すのですか?あなたが決める。パーツの位置合わせ方法は?あなたが決める。部品は「曲がる」ことができますか?状況によって異なりますが、そうではない場合もありますが、もちろんそれほど多くありません。材料が変形しすぎて部品を受け入れられない場合はどうすればよいですか?あなたが決める。すべての素材ロールは同じですか?もちろんそうではありませんが、すべてのロールに合わせて配置規則を調整するようにユーザーを悩ませることはできません...それは実際的ではありません。カメラにはどのような写真が表示されていますか?マテリアルは、意味が何であれ...それは色である場合もあれば、光の反射だけでパターンが明らかになる場合もあります。 平均パターンを認識することは何ですか?あなたが決める。

次に、この問題の解決策の一般的な構造を設計し、お金と時間で見積もりを出してみましょう。私の賭けは、あなたのシステムアーキテクチャさえ(はい、アーキテクチャ)は間違っているということです。コストと時間の見積もりは乱数になります。

私たちはそれを実装し、現在は機能するシステムになりましたが、システムの形そのものについて何度も考えを変えました。メニューからはアクセスできないサブシステム全体を追加しました。プロトコルでマスター/スレーブの役割を複数回切り替えました。たぶん今、私たちはそれをよりよく再構築しようとするのに十分な知識を持っています。

もちろん他の会社も同じ問題を解決しました...しかし、あなたがこれらの会社のいずれかに属していない限り、おそらくトップダウンの詳細なプロジェクトは冗談でしょう。トップダウンで設計できます。あなたが前にそれをしたことがないので、あなたはできません。

おそらく同じ問題も解決できます。ただし、ボトムアップで作業します。あなたが知っていることから始めて、あなたが知らないことを学び、合計します。

新しい複雑なソフトウェアシステムは、設計されずに成長しています。時々誰かが、大きく複雑で不適切な仕様のソフトウェアシステムをゼロから設計し始めます(大きな複雑なソフトウェアプロジェクトでは、3つの可能性しかないことに注意してください:a]仕様が曖昧である、b]仕様が間違っており、自己矛盾しているまたはc]両方...そしてほとんどの場合[c]がそうです)。

これらは、PowerPointスライドとUMLダイアグラムだけに何千時間も費やされる典型的な巨大企業プロジェクトです。恥ずかしいほど大量のリソースを焼き付けた後、必ず完全に失敗します...あるいは、非常に例外的なケースでは、最終的に、初期仕様のごく一部のみを実装する高額なソフトウェアを提供します。そして、そのソフトウェアは常にユーザーから深く嫌われています...購入するソフトウェアの種類ではなく、強制されているために使用するソフトウェアの種類。

これは、コードだけを考えるべきだと思いますか?もちろん違います。しかし、私の意見では、構築は下から開始し(レンガ、具体的なコード)、上に行く必要があります...そして、あなたの焦点と細部への注意は、あるものから遠ざかるにつれて、ある意味で「フェード」する必要があります。トップダウンは多くの場合、システム全体に同じレベルの詳細を一度に配置する必要があるかのように提示されます。すべてが明らかになるまですべてのノードを分割し続けるだけです...実際のモジュールでは、サブシステムはサブルーチンから「成長」します。特定の問題についてこれまでに経験がない場合、サブシステム、モジュール、またはライブラリのトップダウン設計は恐ろしいものになります。入れるべき関数がわかれば、良いライブラリを設計できます。その逆はできません。

LISPのアイデアの多くは一般的になりつつありますが(ファーストクラス関数、クロージャー、デフォルトとしての動的型付け、ガベージコレクション、メタプログラミング、インタラクティブな開発)、LISPは今日でも(私が知っている言語の中で)コードを簡単に作成するのがいかに簡単かという点で非常にユニークです。あなたが必要なもののために。

たとえば、キーワードパラメータはすでに存在しますが、存在しない場合は追加できます。私はそれを(コンパイル時のキーワード検証を含めて)行いました。実験を行っているおもちゃのLISPコンパイラーで、コードをあまり必要としません。

代わりにC++を使用すると、キーワードパラメータがあまり役に立たない、または非常に複雑で壊れたハーフバックアップテンプレートの実装が実際にはそれほど役に立たないというC++の専門家が集まります。 C++クラスはファーストクラスのオブジェクトですか?いいえ、それについてあなたができることは何もありません。実行時またはコンパイル時に内省できますか?いいえ、それについてあなたができることは何もありません。

LISPのこの言語の柔軟性は、ボトムアップビルドに最適です。サブルーチンだけでなく、構文や言語のセマンティクスも構築できます。そして、ある意味でLISP自体はボトムアップです。

36
6502

この回答がLISPにどのように適用されるかはわかりませんが、私は アジャイル原則、パターン、およびプラクティス を読み終えたばかりで、著者 ncle Bob が強く支持しています-私が完全に同意するC#のダウンアプローチ(C++にも適用可能)。

ただし、トップダウンアプローチは最初の対話ではドキュメントと全体的なデザインのみを提供するという意味であるという結論を導き出した他のいくつかの回答とは異なり、この本は別の方法を指します:TDDと進化的デザインの組み合わせ。

アイデアは、上から始めて、最高の抽象化レベル(またはローカルの最高レベル)を定義し、それらが定義されるとすぐに、機能#1がすぐに機能するように、それらに有用な作業を行わせることです。次に、機能を追加していくと、常に SOLIDの原則 を意識しながら、コードをリファクタリングし、必要に応じて設計を進化させます。このようにして、抽象化レイヤーが多すぎたり、アーキテクチャ全体に適合しない低レベルのデザインになったりすることはありません。これが何を意味するのかわからない場合は、上記の本に、開発者が概念を取り、UMLダイアグラムと低レベルのクラスから始める例を含む章全体が含まれています。実際にコーディングが始まると、これらのクラスの半分は必要ないことを理解するためだけです。このアプローチの本質では、プロジェクトでより高レベルの詳細が定義されると、低レベルのコードが自然にプッシュダウンされます。

そして最後に、SOLIDを実践する場合、高レベルの抽象化が定義されている状況に遭遇して、詳細に行き、突然OODや抽象化がないことに気付くべきではありません。これは実際にはトップダウン設計のせいではなく、遅延エンジニアリングです。

XPおよび進化的設計についての詳細を読みたい場合は、別の偉大な作家であるMartin Fowlerからの良い読み物を示します。 "Is Design Dead?"

6
DXM

私にとって、ポールグラハムの記事で最も重要な発言は次のとおりです。

[...] LISPプログラマー[...]は、ボトムアップ設計と呼ばれる可能性のある原則に従います。つまり、問題に合わせて言語を変更します。 LISPでは、プログラムを言語に向けて記述するだけでなく、プログラムに向けて言語を構築します。

または、C++サークルで知られているように:Library Design is Language Design(Bjarne Stroustrup)

トップダウン設計の主なアイデアは、最初に計画し、次にコーディングすることです。 Beanowは正しい 彼が書いている の場合、実行可能コードがプロセスの後半に来ると問題が発生する。ボトムアップ設計では、常にコードがあり、そのコードをテストできます。

また、コードはフラットではありません。つまり、抽象化のレベルが高くなる傾向があります。トップダウンの設計では、人々はしばしば、任意のレベルまでの大きな抽象化に終わり、その下には抽象化がまったくありません。ボトムアップOTOHで設計されたコードは、抽象化される可能性が高いため、低レベルの制御およびデータ構造が含まれることがよくあります。

3
pillmuncher

理想的には、LISPだけでなく、任意の言語でプログラムを作成すると、次のプログラムの開発を加速したり、現在のプログラムの拡張を加速したりできる汎用ツールのセット全体を作成できます。

実際には、これらのツールを追跡することは困難な場合があります。ドキュメントは貧弱でまとまりがなく、それを知っている人々は去っていきます。実際には、多くの場合、コードの再利用は、その価値よりも厄介です。しかし、コードが適切に文書化および整理されていて、プログラマーが固執している(または有用なコードを独自に用意している)場合、再構築するのではなく、ウェアハウスからコードを取得することで、膨大な作業を節約できます。

すべてのデザインはトップダウンである必要があります。そうしないと、自分が何をしているかわからなくなります。あなたは小屋や車を作っていますか?ボトムアップのデザインでそれを理解することはできません。しかし、左フロントホイールを作成する場合、このプロジェクトと他のプロジェクトの両方で、後でさらにホイールが必要になると思うかもしれません。また、再利用可能なホイールを構築すると、1つの価格で4つ使用できます。 (そして、あなたが次に構築しているそのトレーラーのために18、すべて無料で。)

実際の車や実際のホイールとは異なり、1つのソフトウェア「ホイール」を作成した場合、それらの数は無制限に作成されたことに注意してください。

トップダウン設計の詳細:これで開始する必要がありますが、できないホイールを構築する場合、それを見つける必要があることを指摘する義務がありますbefore =あなたはあなたの車に多くの仕事をします。したがって、トップダウンでの作業とほぼ並行してボトムアップで作業する必要があります。また、あなたが知っているcanホイールを構築することは、トラクタートレーラーのように、これまで考えられなかった多くのプロジェクトを示唆するかもしれません。トップダウンのアプローチが支配的である必要があると思いますが、veryの軽いタッチです。

したがって、Paul Grahamの言い換えを続けると、理想的には、プログラムを作成するときに、元のプログラムと他のプログラムの両方で多くの時間を節約できる多くの再利用可能な部分ができあがります。ポールグラハムから少し離れたところにありますが、これはどの言語でも機能します(一部のプロセスは他のプロセスよりも優れています)。

このほぼ魔法のようなプロセスの敵は、非常に短期的な見通しを持つプログラマーです。これは、人格の欠陥に起因する可能性がありますが、より一般的には、雇用会社の内部および企業間で、職務と責任の切り替えが速すぎることが原因です。

2
RalphChapin

反復開発と組み合わせたトップダウンアプローチの何が問題になっていますか?

反復的な開発でトップダウンアプローチを使用しても、最初の反復で機能するコードは提供されません。お客様からのフィードバックが難しい設計書などをお届けします。 「ええ、私は推測します(これは私には抽象的すぎる)」のような応答は、顧客が希望するシステムの詳細をさらに詳しく指定するのに役立ちません。

代わりに、要求されたものの一般的な概要のみを作成します。 (要件)完成品を定義するもの、および実装するために優先するに値するものの一般的なガイドラインとして使用する。そこから、お客様が実際にいじって、これが彼らの意図したものであったかどうかを確認するために、すべてのイテレーションの作業用製品を作成します。そうでない場合は、顧客の要求とは異なる動作をするシステムの設計に何百時間も費やされていないため、問題にはなりません。

ポール・グラハムは完全にボトムアップでのビルドを奨励しましたか?それとも、ボトムアップからプログラムするだけで、要件分析/設計フェーズではないのですか?

私は他の人のために話すつもりはありません。また、彼のエッセイは読みませんでした。私があなたに与えている答えは、私の教育と経験から来ています。

つまり、LISPでプログラムを作成している間、元のプログラムと同様のプログラムを作成するために使用できる汎用ツールができあがりますね。

このアプローチを使用すると、より抽象的な構成要素が作成されます。すぐに表示できるスタンドアロンサブシステムを構築する必要があるというだけの理由で、密接に絡み合って一度に実装する必要があるトップダウン設計を作成することはできません。再利用性、保守性が向上しますが、何よりも変更に対する柔軟な対応が可能になります。

1
Beanow