TDD - Outside In vs. Inside Out


53

Was ist der Unterschied zwischen dem Erstellen einer Anwendung mit Outside In und dem Erstellen einer Inside Out- Anwendung mit TDD?

Dies sind die Bücher, die ich über TDD und Komponententests gelesen habe:
Testgetriebene Entwicklung: Am Beispiel
Testgetriebene Entwicklung: Ein praktischer Leitfaden: Ein praktischer Leitfaden
Reale Lösungen für die Entwicklung hochwertiger PHP-Frameworks und -Anwendungen, die auf
Tests basieren, in Microsoft. NET
xUnit-Testmuster: Refactoring von Testcode
Die Kunst des Komponententests: Anhand von Beispielen in
objektorientierter .Net -Software, die von Tests geleitet wird ---> Dieses Testmuster war wirklich schwer zu verstehen, da JAVA nicht meine Hauptsprache ist :)

Fast alle von ihnen erklärten die TDD-Grundlagen und Unit-Tests im Allgemeinen, ohne jedoch die verschiedenen Möglichkeiten zu erwähnen, mit denen die Anwendung erstellt werden kann.

Eine andere Sache, die mir aufgefallen ist, ist, dass die meisten dieser Bücher (wenn nicht alle) die Designphase beim Schreiben der Anwendung ignorieren. Sie konzentrieren sich mehr darauf, die Testfälle schnell zu schreiben und das Design von selbst entstehen zu lassen.

In xUnit Test Patterns stieß ich jedoch auf einen Absatz, in dem die Herangehensweise von Personen an TDD erörtert wurde. Es gibt zwei Schulen draußen, Outside In und Inside Out .

Leider geht das Buch nicht näher auf diesen Punkt ein. Ich möchte wissen, was der Hauptunterschied zwischen diesen beiden Fällen ist.
Wann sollte ich jeden von ihnen verwenden?
Welcher ist für einen TDD-Anfänger leichter zu erfassen?
Was sind die Nachteile jeder Methode?
Gibt es Materialien, die dieses Thema speziell behandeln?


Die beiden Ansätze werden auf der XUnit Test Patterns-Site beschrieben: xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . Es ist komisch, dass sie nicht im Buch sind.
Guillaume31

Antworten:


45

Inside-Out und Outside-In sind eher seltene Begriffe, häufiger habe ich von Classic School und London School gehört / gelesen .

  • Inside-Out (klassische Schule, Bottom-Up ): Sie beginnen auf Komponenten- / Klassenebene (Inside) und fügen den Anforderungen Tests hinzu. Während sich der Code (aufgrund von Refactorings) weiterentwickelt, erscheinen neue Mitarbeiter, Interaktionen und andere Komponenten. TDD leitet das Design vollständig.

  • Outside-In (Londoner Schule, Top-Down oder "Mockist TDD", wie Martin Fowler es nennen würde): Sie kennen die Interaktionen und Kollaborateure von vornherein (insbesondere die auf den obersten Ebenen) und beginnen dort (oberste Ebene), um die notwendigen Abhängigkeiten zu verspotten. Mit jeder fertigen Komponente wechseln Sie zu den zuvor verspotteten Mitarbeitern und beginnen dort erneut mit TDD, um tatsächliche Implementierungen zu erstellen (die, obwohl sie verwendet wurden, dank Abstraktionen zuvor nicht benötigt wurden ). Beachten Sie, dass der Outside-In- Ansatz gut zum YAGNI- Prinzip passt .

Keiner der Ansätze ist der einzige ; Sie haben beide ihren Platz, je nachdem, was Sie tun. Bei großen Unternehmenslösungen, bei denen Teile des Entwurfs von Architekten stammen (oder im Vorfeld existieren), könnte man mit dem Ansatz des "Londoner Stils" beginnen. Wenn Sie sich jedoch einer Situation gegenübersehen, in der Sie nicht sicher sind, wie Ihr Code aussehen soll (oder wie er in andere Teile Ihres Systems passen soll), ist es möglicherweise einfacher, mit einer Low-End-Komponente zu beginnen und sie zuzulassen Entwickeln Sie sich mit der Einführung weiterer Tests, Überarbeitungen und Anforderungen.

Was auch immer Sie verwenden, meistens ist es situationsabhängig.

Für die weitere Lektüre gibt es einen Google-Gruppenbeitrag mit einer interessanten Diskussion darüber, wie diese Unterscheidung entstanden sein könnte und warum London möglicherweise nicht der am besten geeignete Name ist.


2
Interessant. Wie sind Sie zu dem Schluss gekommen, dass TDD außerhalb von TDD "spöttisch" ist? Ich bevorzuge Outside-In-Denken und -Design und damit Testen (siehe softwareonastring.com/2015/01/10/… ), aber der Artikel von Fowler bringt mich fest mit Fowler in das Lager der Klassiker. Während Mockist immer einen Outside-In - Ansatz verwenden, können Sie es nicht umdrehen und sagen , dass von außen in Gestaltung und Prüfung ist Mockist TDD. Outside-In kann und wird auch von klassizistischen TDD-Machern praktiziert.
Marjan Venema

@jimmy_keen - Ersetzen Sie mit Outside-In zu irgendeinem Zeitpunkt die Mocks in den Tests auf höherer Ebene durch die später erstellten tatsächlichen Implementierungen? Oder lassen Sie sie als verspottete Abhängigkeiten und üben dann den gesamten Produktionscode als Integrationstest aus?
Thehowler

1
Ich stimme nicht zu, dass Classic / Mockist und Inside-Out / Outside-In verwandt sind. Sie sind orthogonal. Sie können Inside-Out / Outside-In mit beiden verwenden.
Daniel Kaplan

Stimme Daniel zu. Sie vergleichen zwei unterschiedliche Taxonomien. Auch wenn die Outside-in-Entwicklung häufig mit der Londoner (Spott-) Schule in Verbindung gebracht wird, ist dies nicht immer der Fall.
Guillaume31

Ich denke nicht, dass dies eine korrekte Beschreibung des Outside-In-Prozesses ist. Es geht darum, so viel wie möglich von den öffentlichen Schnittstellen aus zu testen, ohne an Interna gekoppelt zu sein.
Mcintyre321

15

Kurze Antwort: Wie üblich hängt es von Ihrer Kodierungspräferenz und Ihrem Teamansatz ab.

Inside-Out- Codierung ist großartig, weil immer etwas funktioniert. Der Nachteil ist, dass es Ihnen nicht unbedingt hilft, an einen radikal anderen Ort zu gelangen. Es ist schwieriger, auf diese Weise einen Kurs zu bestimmen. In ähnlicher Weise hat das Schreiben von Code außerhalb von Code den Nachteil, dass es nicht unbedingt den Vorteil einer schnellen iterativen Entwicklung hat und nicht unbedingt alle Möglichkeiten und Muster erkennt, die sich aus der Tiefe der Codestruktur ergeben können.

Ich bin zu der Überzeugung gelangt, dass beide Entwicklungsstile wichtig sind und dass es in der Tat hilfreich ist, einen Stilmix in einem Team zu haben. Die Idee ist, dass Inside-Out großartig ist, um Bausteine ​​zu schaffen, und das Äußere beim Denken die Struktur und Richtung der Form bestimmt.

Ein Teil meiner Überlegungen stammt von einer sehr populären Denkschule, die derzeit die iterative Entwicklung fördert, was oft gleichbedeutend mit Inside-Out-Entwicklung ist. Ich glaube, iterative Entwicklung ist großartig, wenn Sie nicht zu weit gehen müssen. Aber ich denke, dass Big-Picture-Denken im Gegensatz zu einem rein iterativen Prozess für bestimmte Arten von Innovationen und für das Erreichen eines weniger offensichtlichen Ortes von unschätzbarem Wert ist. Richtig verwaltet, von innen nach außen und von außen nach innen zusammen kann eine sehr effektive Kombination sein.


8

Sie sollten dieser Liste Agile Prinicples, Patterns und Practices in C # hinzufügen . Ich weiß nicht, warum er am Ende "in C #" angeheftet hat. Die Bücher sind überhaupt nicht die Sprache und der einzige Grund, warum sie bei amazon keine 5 Sterne bekommen haben, sind Leute, die von der C # -Natur seiner Beispiele enttäuscht waren.

Der Autor befürwortet, dass Sie, wann immer möglich, versuchen sollten, Code von außen nach innen zu schreiben und sich stark auf evolutionäres Design zu verlassen, und ich stimme seiner Aussage zu. Seiner Meinung nach wird sich unser Design immer weiterentwickeln, wenn wir Funktionen hinzufügen. Wenn wir mit Komponenten auf niedriger Ebene beginnen, während Features hinzugefügt werden, stellen wir fest, dass diese Komponenten nicht das tun, was wir möchten, oder dass Dinge verschoben werden müssen. Dies kann ziemlich teuer werden, insbesondere wenn Sie jedes Mal, wenn Sie Funktionen von einer Klasse in eine andere verschieben, in allen Unit-Test-Projekten den gleichen Schritt ausführen müssen.

Wenn Sie andererseits festlegen, was Ihre Anwendung in erster Linie tun soll, codieren Sie für die externe Schnittstelle. Wenn Features hinzugefügt werden und der zu testende Code an Größe zunimmt, gliedern Sie Ihre Anwendung in weitere Klassen. Während dieses Refactoring jedoch durchgeführt wird, bleiben die von Ihnen erstellten ursprünglichen Komponententests gültig. Sie fangen also ganz von außen an und setzen die Umgestaltung in immer niedrigere Klassen fort, während Sie diesen inneren Klassen zusätzliche Komponententests hinzufügen, aber Sie müssten sich selten bewegen und Ihre Komponententests umschreiben.

Wenn Sie jedoch ein bestimmtes Low-Level-Subsystem identifizieren, das Ihre Anwendung benötigt (und Ihr Unternehmen möglicherweise bereits in anderen Anwendungen ein solches Subsystem benötigt), sollten Sie zuerst mit einem Low-Level-Baustein beginnen und dann Bauen Sie die App darauf auf.


7

Aus meiner Sicht erstreckt sich das Konzept der Outside-In-Entwicklung wirklich auf zwei Ebenen. Gerard Meszaros beschreibt sie kurz als "Outside-In- Design " und "Outside-In / Inside-Out- Codierung ".

  • Die erste Ebene ist eine Organisations- und Prozessebene. Outside-In-Design ist im Gegensatz zu Top-Down (Wasserfall / Taylorist) und Bottom-Up gemeint. Bei einem Outside-In-Ansatz konzentrieren wir uns auf die Perspektive des Endbenutzers. Wir beginnen mit Storytests, ATDD- oder BDD-Tests und gehen "nach innen", um auf technische Tests und Code zu schließen. Daher ist Outside-In-Design in der Regel das, was Sie in einem agilen Kontext tun würden. Dan North hat ein großartiges Gespräch über BDD, Top-Down-, Bottom-Up- und Outside-In-Ansätze.

  • Die zweite Ebene ist technisch und hat mit applikativen Schichten zu tun. Outside-In-Codierung bedeutet im Grunde, von der Benutzeroberfläche aus in die zentrale Ebene (normalerweise die Geschäfts- / Domänenebene) zu gelangen. Dies ist im Gegensatz zur Inside-Out-Codierung gemeint, die von der zentralen Ebene ausgeht und die externen Ebenen zuletzt codiert.

Sie könnten also ein Außen-Innen-Design mit Außen-Innen-Codierung oder Innen-Außen-Codierung haben.

Ich bin mit Meszaros nicht einverstanden, wenn er Inside-Out-Codierung mit Integrationstests in Verbindung bringt und argumentiert, dass in einem Inside-Out-Kontext "die äußere Software nicht tatsächlich isoliert von der inneren Software getestet wird". Aber ich glaube nichts hindert dich daran. Sie können Ihre Objekte auf der äußeren Ebene perfekt testen, indem Sie die Objekte auf der inneren Ebene verspotten, auch wenn der Produktionscode für diese Objekte bereits vorhanden ist. Sie müssen lediglich Schnittstellen und Mocks zu den vorhandenen konkreten Objekten hinzufügen, anstatt die Schnittstellen zu schreiben, sie zu verspotten und die Implementierungen später zu erstellen, wie Sie es mit Outside-In-Codierung tun würden.

Mit anderen Worten, Mockist oder Klassiker TDD ist IMO ein orthogonales Anliegen zur Outside-In / Inside-Out-Codierung. Sie können einen spöttischen Stil perfekt mit einem Inside-Out-Ansatz kombinieren. Der Grund dafür ist , dass Mockist / klassizistisch über Code - Abhängigkeiten , während von außen nach innen / inside-out - Codierung über applicative ist Schichten .

Ein weiterer wichtiger Punkt ist, dass Abhängigkeiten nicht nur über Ebenen hinweg bestehen, sondern auch zwischen Objekten in derselben Ebene. Beispielsweise möchten Sie möglicherweise mit einem Objekt in Ihrer zentralen Business-Schicht beginnen (Inside-Out-Ansatz) und Mocks verwenden, um Ihr Objekt von anderen Business-Schicht-Objekten zu isolieren, mit denen es kommuniziert. Dies geschieht häufig mit IoC - die Abstraktionen, von denen Ihr Objekt abhängt, werden häufig in derselben Ebene deklariert, konkrete Implementierungen befinden sich jedoch in einer anderen Ebene.

Robert "Onkel Bob" Martin erwähnt in seinem Beitrag " Clean Architecture " kurz die Inside-Out-Codierung und wie sie nicht unbedingt mit einer entkoppelten Architektur in Konflikt steht .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.