web-dev-qa-db-ja.com

TDD-アウトサイドインとインサイドアウト

TDDを使用してアプリケーションを構築するOutside Inと構築するInside Outの違いは何ですか?

これらは、TDDとユニットテストについて読んだ本です。
テスト駆動開発:例による
テスト駆動開発:実践ガイド:実践ガイド
高品質を開発するための実際のソリューションPHPフレームワークとアプリケーション
Microsoft .NETでのテスト駆動開発
xUnitテストパターン:リファクタリングテストコード
ユニットテストの技術:.Netの例を使用
Growing Object-Oriented Software、Guided by Tests --->これはJavaが私の主要言語ではないため、理解するのが非常に困難でした: )

それらのほとんどすべてがTDDの基本と単体テストを一般的に説明しましたが、アプリケーションの構築方法の違いについてはほとんど触れていません。

私が気付いたもう1つの点は、これらの本のほとんど(すべてではないにしても)が、アプリケーションの作成時に設計フェーズを無視していることです。彼らは、テストケースを迅速に記述し、設計を自動的に出現させることに重点を置いています。

しかし、私は人々がTDDにアプローチする方法を論じているxUnitテストパターンの段落に出くわしました。 2つの学校がありますOutside InvsInside Out

悲しいことに、この本はこの点については詳しく述べていません。これら2つのケースの主な違いは何ですか。
それぞれをいつ使用すればよいですか?
TDDの初心者にとって、どちらが理解しやすいですか?
各方法の欠点は何ですか?
このトピックについて具体的に説明している資料はありますか?

55
Songo

Inside-OutとOutside-Inはかなりまれな用語で、Classic schoolについて聞いたり読んだりすることが多いロンドンの学校

  • Inside-Out(クラシックスクール、bottom-up):コンポーネント/クラスレベル(内部)から始めて、要件にテストを追加します。 (リファクタリングにより)コードが進化するにつれて、新しい共同編集者、相互作用、その他のコンポーネントが登場します。 TDDは設計を完全にガイドします。

  • アウトサイドイン(ロンドンスクール、トップダウンまたは "mockist TDD" マーティンファウラーがそれを呼び出すため):あなたインタラクションとコラボレーター(特にトップレベルのユーザー)について事前に知り、そこから開始し(トップレベル)、必要な依存関係を模倣します。すべての完成したコンポーネントを使用して、以前にモック化されたコラボレーターに移動し、そこで再びTDDを開始して、実際の実装を作成します(使用されていたとしても、abstractionsのおかげで以前は不要でした)。 outside-inのアプローチは [〜#〜] yagni [〜#〜] の原則に適しています。

どちらのアプローチも唯一のものではありません;彼らはあなたが何をするかに応じて彼らの場所を持っています。大規模なエンタープライズソリューションでは、設計の一部が建築家から(または事前に存在して)いる場合、「ロンドンスタイル」のアプローチから始めることができます。一方、コードの外観(またはシステムの他の部分にどのように適合するか)が不明な状況に直面した場合は、ローエンドコンポーネントから始めて、テスト、リファクタリング、要件が追加されるにつれて進化します。

どちらを使用しても、状況に応じて異なります。

さらに読むために Google group post があり、この区別がどのようにして始まったのか(あるかもしれない)、なぜロンドンが最も適切な名前ではないのかについてかなり興味深い議論があります。

46
k.m

短い回答:いつものようにdependコーディングの好みとチームのアプローチに依存します。

裏返しコーディングは素晴らしいことです。欠点は、根本的に異なる場所に行くのに必ずしも役立つとは限らないことです。この方法でコースをチャート化することは困難です。同様に、コードの作成outside inには、迅速な反復開発の利点が必ずしもあるとは限らず、コードの構造の深部から生じる可能性があるすべての機会とパターンが必ずしも見られないという欠点があります。

私は両方の開発スタイルが重要であり、チームに複数のスタイルを混在させることは実際に役立つと信じるようになりました。考え方は、裏返しはビルディングブロックを作成するのに最適であり、表側はフォームの構造と方向性を提供するというものです。

私の推論の一部は、現在反復的な開発を促進している非常に人気のある学派から来ています。これは、しばしば裏返しの開発と同義です。私反復的な開発は素晴らしいと思います遠くに行けないとき。しかし、純粋に反復的なプロセスとは対照的に、全体像を考えることは、特定のタイプのイノベーションにとって、およびあまり明白でない場所に到達するために非常に貴重であると思います。適切に管理された、裏返しと裏返しの組み合わせは、非常に効果的な組み合わせになります。

15
Yusubov

そのリストに C#でのアジャイル原則、パターン、およびプラクティス を追加する必要があります。彼が最後に "C#で"取り組んだ理由がわかりません。本はまったく言語ではなく、Amazonで5つ星を獲得できなかった唯一の理由は、彼の例のC#性に失望した人々からのものです。

著者は、可能な場合は常にコードを外側から内側に書き、進化的設計に大きく依存するべきであると主張し、私は彼の発言に同意します。彼の推論は、機能を追加すると、デザインは常に進化するということです。機能が追加されたときに低レベルのコンポーネントから始めると、それらのコンポーネントが私たちが望んでいることを実行していないか、または物事を移動する必要があることに気付くでしょう。これは、機能をあるクラスから別のクラスに移動するたびに、すべての単体テストプロジェクトで同じ移動を実行する必要がある場合に、かなり高価になる可能性があります。

一方、アプリケーションが最初に何をすべきかを決定する場合は、外部インターフェース用にコーディングします。機能が追加され、テスト対象のコードのサイズが大きくなると、アプリケーションをより多くのクラスにリファクタリングしますが、このリファクタリング作業が行われている間、作成した元の単体テストは引き続き有効です。したがって、完全に外側から始めて、内部クラスにユニットテストを追加しながら、より多くの低レベルクラスにリファクタリングを続けますが、ユニットテストを移動して書き直す必要はほとんどありません。

ただし、アプリケーションが必要とする特定の低レベルサブシステムを特定した場合(そして、おそらく他のアプリケーションでこのようなサブシステムがすでに必要である場合)、まず低レベルのビルディングブロックから始めて、次にその上にアプリを構築します。

8
DXM

私が見ているように、アウトサイドイン開発のコンセプトは、実際には2つのレベルに広がっています。 Gerard Meszarosは簡単に describes 「outside-indesign」と「outside-in/inside-outcoding "。

  • 最初のレベルは、組織レベルとプロセスレベルです。アウトサイドインのデザインは、トップダウン(滝/仕立て屋)やボトムアップとは対照的です。アウトサイドインアプローチでは、エンドユーザーの視点に焦点を当てます。ストーリーテスト、ATDDまたはBDDテストから始めて、技術的テストとコードを「内向き」に推論します。したがって、通常、外部から内部への設計は、アジャイルのコンテキストで行うことになります。 Dan Northは、BDD、トップダウン、ボトムアップ、アウトサイドインのアプローチについて、素晴らしい talk を持っています。

  • 2番目のレベルは技術的で、アプリケーションレイヤーに関係しています。アウトサイドインコーディングとは、基本的にUIから始まり、中央層(通常はビジネス/ドメイン層)に向かうことを意味します。これは、中央層から開始して外部層を最後にコーディングするインサイドアウトコーディングとは対照的です。

したがって、outside-inコーディングまたはInside-outコーディングのいずれかを備えた、outside-inデザインを使用できます。

Meszarosに反対するのは、裏返しのコーディングを統合テストに関連付けて、裏返しのコンテキストで「実際には外側のソフトウェアを内側のソフトウェアから切り離してテストするのではない」と主張する場合です。しかし、私はあなたがそうすることを妨げるものは何もないと信じています。内側のレイヤーオブジェクトのプロダクションコードがすでに存在する場合でも、内側のレイヤーオブジェクトをモックアウトすることで、外側のレイヤーオブジェクトをテストすることを完全に選択できます。インターフェースとモックを既存の具象オブジェクトの上に追加するだけで、インターフェースを記述してモック化し、outside-inコーディングで行うように後で実装を作成するだけです。

言い換えれば、モック主義または古典主義のスタイルのTDDは、IMOであり、アウトサイドイン/インサイドアウトコーディングとは関係ありません。あなたは完全にモック主義のスタイルを裏返しのアプローチと一緒に使うことができます。この背後にある理由は、モック主義/古典主義のスタイルはコードdependenciesに関するものであり、一方、outside-in/inside-outコーディングは適用的なものlayers

もう1つの重要なことは、依存関係はレイヤー間だけでなく、同じレイヤー内のオブジェクト間にも存在することです。たとえば、中央のビジネスレイヤーの1つのオブジェクトから始め(インサイドアウトアプローチ)、モックを使用して、オブジェクトが通信する他のビジネスレイヤーオブジェクトからオブジェクトを分離することができます。これはIoCでよく起こります。オブジェクトが依存する抽象化は同じレイヤーで宣言されることがよくありますが、具体的な実装は別のレイヤーで行われます。

Robert "Uncle Bob" Martinは、彼の投稿 " Clean Architecture "で、裏返しのコーディングと、それが分離アーキテクチャと必ずしも競合しない方法について簡単に述べています。

7
guillaume31