web-dev-qa-db-fra.com

TDD - Outside In vs Inside Out

Quelle est la différence entre la construction d'une application Outside In et la construction Inside Out en utilisant TDD?

Voici les livres que j'ai lus sur le TDD et les tests unitaires:
Développement piloté par les tests: par exemple
Développement piloté par les tests: un guide pratique: un guide pratique
Real-World Solutions for Developing High-Quality PHP Frameworks and Applications
Développement piloté par les tests dans Microsoft .NET
Modèles de test xUnit: Refactoring Test Code
L'art du test unitaire: avec des exemples en .Net
Développement d'un logiciel orienté objet, guidé par des tests ---> Celui-ci était vraiment difficile à comprendre car Java n'est pas ma langue principale: )

Presque tous ont expliqué les bases de TDD et les tests unitaires en général, mais avec peu de mention des différentes façons dont l'application peut être construite.

Une autre chose que j'ai remarquée est que la plupart de ces livres (sinon tous) ignorent la phase de conception lors de l'écriture de l'application. Ils se concentrent davantage sur l'écriture rapide des cas de test et sur la création du design par lui-même.

Cependant, je suis tombé sur un paragraphe dans xUnit Test Patterns qui a discuté de la façon dont les gens abordent le TDD. Il y a 2 écoles là-bas Outside In vs Inside Out .

Malheureusement, le livre ne développe pas plus sur ce point. Je souhaite savoir quelle est la principale différence entre ces 2 cas.
Quand devrais-je utiliser chacun d'eux?
Pour un débutant TDD lequel est le plus facile à saisir?
Quels sont les inconvénients de chaque méthode?
Existe-t-il des documents traitant spécifiquement de ce sujet?

55
Songo

Inside-Out et Outside-In sont des termes assez rares, plus souvent j'ai entendu parler de École classique et École de Londres .

  • Inside-Out (école classique, de bas en haut): vous commencez au niveau composant/classe (inside) et ajoutez des tests aux exigences. Au fur et à mesure que le code évolue (en raison des refactorings), de nouveaux collaborateurs, interactions et autres composants apparaissent. TDD guide complètement la conception.

  • Outside-In (école de Londres, de haut en bas ou "mockist TDD" comme Martin Fowler l'appellerait): vous savoir sur les interactions et les collaborateurs dès le départ (en particulier ceux aux niveaux supérieurs) et commencer là (niveau supérieur), se moquant des dépendances nécessaires. Avec chaque composant terminé, vous passez aux collaborateurs précédemment moqués et recommencez avec TDD, créant des implémentations réelles (qui, bien qu'utilisées, n'étaient pas nécessaires auparavant grâce à abstractions). Notez que l'approche outside-in va bien avec le principe YAGNI .

Aucune des approches n'est la seule et unique; ils ont tous les deux leur place selon ce que vous faites. Dans les grandes solutions d'entreprise, où des parties de la conception proviennent d'architectes (ou existent à l'avance), on peut commencer par une approche de "style londonien". D'un autre côté, lorsque vous êtes confronté à une situation où vous n'êtes pas certain de l'apparence de votre code (ou de la façon dont il devrait s'intégrer dans d'autres parties de votre système), il peut être plus facile de commencer avec un composant bas de gamme et de le laisser évoluer à mesure que de nouveaux tests, refactorisations et exigences sont introduits.

Quelle que soit la méthode utilisée, le plus souvent, elle est situationnelle.

Pour une lecture plus approfondie, il y a publication de groupe Google avec une discussion assez intéressante sur l'origine de cette distinction (et pourquoi) et pourquoi Londres pourrait ne pas être le nom le plus approprié.

46
k.m

Réponse courte: Comme d'habitude, cela dépend de vos préférences de codage et de votre approche d'équipe.

Inside out le codage est génial car vous avez toujours quelque chose qui fonctionne. L'inconvénient est que cela ne vous aide pas nécessairement à vous rendre dans un endroit radicalement différent. Il est plus difficile de tracer un parcours de cette façon. De même, l'écriture de code extérieur en a pour inconvénient de ne pas nécessairement bénéficier d'un développement itératif rapide, et de ne pas nécessairement voir toutes les opportunités et les schémas qui peuvent survenir au plus profond de la structure du code.

J'en suis venu à croire que les deux styles de développement sont importants, et qu'il est en fait utile d'avoir un mélange de styles dans une équipe. L'idée est que l'intérieur vers l'extérieur est idéal pour créer des blocs de construction, et l'extérieur dans la pensée fournit la structure et la direction du formulaire.

Une partie de mon raisonnement vient d'une école de pensée très populaire qui promeut actuellement le développement itératif, qui est souvent synonyme de développement à l'envers. I je pense que le développement itératif est excellent quand vous n'avez pas trop loin pour aller. Mais je pense que la vision d'ensemble, par opposition à un processus purement itératif, est inestimable pour certains types d'innovation et pour arriver à un endroit moins évident. Une bonne gestion, à l'intérieur comme à l'extérieur ensemble, peut être une combinaison très efficace.

15
Yusubov

Vous devez ajouter Agile Prinicples, Patterns and Practices in C # to this list. Je ne sais pas pourquoi il a cloué sur "en C #" à la fin. Les livres ne sont pas du tout la langue et la seule raison pour laquelle il n'a pas obtenu 5 étoiles sur Amazon est de personnes qui ont été déçues par la C # -ness de ses exemples.

L'auteur préconise que, dans la mesure du possible, vous devriez essayer d'écrire du code de l'extérieur vers l'intérieur et de vous appuyer fortement sur la conception évolutive, et je suis d'accord avec sa déclaration. Son raisonnement est que lorsque nous ajoutons des fonctionnalités, notre conception évoluera toujours. Si nous commençons avec des composants de bas niveau à mesure que des fonctionnalités sont ajoutées, nous réaliserons que ces composants ne font pas ce que nous aimerions qu'ils fassent, ou que les choses doivent être déplacées. Cela pourrait devenir assez cher, surtout si chaque fois que vous déplacez une fonctionnalité d'une classe à une autre, vous devez effectuer le même mouvement dans tous les projets de test unitaire.

D'un autre côté, si vous déterminez ce que votre application est censée faire en premier lieu, vous codez pour une interface externe. Au fur et à mesure que des fonctionnalités sont ajoutées et que le code testé augmente en taille, vous refactorisez votre application en plusieurs classes, mais pendant que cet effort de refactoring se poursuit, les tests unitaires originaux que vous avez écrits restent valides. Vous commencez donc complètement à l'extérieur et continuez de refactoriser dans de plus en plus de classes de bas niveau, tout en ajoutant des tests unitaires supplémentaires à ces classes internes, mais vous auriez rarement à vous déplacer et à réécrire vos tests unitaires.

Cependant, si vous identifiez un sous-système de bas niveau spécifique dont votre application aura besoin (et peut-être que votre entreprise a déjà besoin d'un tel sous-système dans d'autres applications), ce serait le moment de commencer par un bloc de construction de bas niveau en premier, puis construire l'application en plus de cela.

8
DXM

Selon moi, le concept de développement Outside-in se propage vraiment sur 2 niveaux. Gerard Meszaros brièvement décrit les comme "design extérieur-intérieur " et "extérieur-intérieur/intérieur-extérieur codage ".

  • Le premier niveau est un niveau d'organisation et de processus. La conception extérieure est conçue par opposition à une approche descendante (cascade/tayloriste) et ascendante. Avec une approche de l'extérieur vers l'intérieur, nous nous concentrons sur la perspective de l'utilisateur final. Nous commençons par des tests d'histoire, des tests ATDD ou BDD et nous allons "vers l'intérieur" en inférant des tests techniques et du code. La conception extérieur-intérieur est généralement ce que vous feriez dans un contexte Agile. Dan North a une grande discussion sur les approches BDD, top-down, bottom-up et outside-in.

  • Le deuxième niveau est technique et concerne les couches applicatives. Le codage extérieur signifie essentiellement commencer à partir de l'interface utilisateur et aller vers la couche centrale (généralement la couche entreprise/domaine). Il est destiné par opposition au codage intérieur-extérieur qui part de la couche centrale et code les couches externes en dernier.

Vous pouvez donc avoir une conception extérieur-intérieur avec un codage extérieur-intérieur ou un codage intérieur-extérieur.

Là où je ne suis pas d'accord avec Meszaros, c'est quand il associe le codage à l'envers aux tests d'intégration, arguant que dans un contexte à l'envers "nous ne testons pas réellement le logiciel externe indépendamment du logiciel interne". Mais je crois que rien ne vous y empêche. Vous pouvez parfaitement choisir de tester vos objets de couche externe en simulant les objets de couche interne même si le code de production de ceux-ci existe déjà. Il vous suffit d'ajouter des interfaces et des maquettes au-dessus des objets concrets existants au lieu d'écrire les interfaces, de les moquer puis de créer les implémentations plus tard comme vous le feriez avec le codage extérieur.

En d'autres termes, le TDD de style mockiste ou classiciste est l'OMI une préoccupation orthogonale au codage extérieur-intérieur/intérieur-extérieur. Vous pouvez parfaitement utiliser un style moqueur avec une approche à l'envers. La raison derrière cela est que le style mockist/classicist concerne les dépendances de code tandis que le codage extérieur-intérieur/intérieur-extérieur est applicatif couches .

Une autre chose importante est que les dépendances ne sont pas seulement entre les couches, elles existent également entre les objets dans la même couche. Par exemple, vous souhaiterez peut-être commencer par un objet dans votre couche métier centrale (approche inside-out) et utiliser des maquettes pour isoler votre objet des autres objets de la couche métier avec lesquels il parle. Cela se produit souvent avec IoC - les abstractions dont votre objet dépend sont souvent déclarées dans la même couche, mais les implémentations concrètes sont dans une couche différente.

Robert "Uncle Bob" Martin mentionne brièvement le codage à l'envers et comment il n'entre pas nécessairement en conflit avec une architecture découplée dans son article " Clean Architecture ".

7
guillaume31