TDD - Exterior adentro vs adentro hacia afuera


53

¿Cuál es la diferencia entre crear una aplicación Outside In versus construirla Inside Out usando TDD?

Estos son los libros que leí sobre TDD y las pruebas unitarias:
Desarrollo basado en pruebas: por ejemplo Desarrollo basado en
pruebas: una guía práctica: una guía práctica
Soluciones del mundo real para el desarrollo de marcos PHP de alta calidad y desarrollo basado en
pruebas de aplicaciones en Microsoft.
Patrones de prueba de NET xUnit: Código de prueba de refactorización
El arte de las pruebas unitarias: con ejemplos en
software orientado a objetos en crecimiento .Net , guiado por pruebas ---> Este fue realmente difícil de entender ya que JAVA no es mi idioma principal :)

Casi todos explicaron los conceptos básicos de TDD y las pruebas unitarias en general, pero con poca mención de las diferentes formas en que se puede construir la aplicación.

Otra cosa que noté es que la mayoría de estos libros (si no todos) ignoran la fase de diseño al escribir la aplicación. Se centran más en escribir los casos de prueba rápidamente y dejar que el diseño emerja por sí mismo.

Sin embargo, me encontré con un párrafo en xUnit Test Patterns que discutía las formas en que las personas se acercan a TDD. Hay 2 escuelas por ahí fuera, en contra adentro hacia afuera .

Lamentablemente, el libro no da más detalles sobre este punto. Deseo saber cuál es la principal diferencia entre estos 2 casos.
¿Cuándo debo usar cada uno de ellos?
Para un principiante de TDD, ¿cuál es más fácil de entender?
¿Cuáles son los inconvenientes de cada método?
¿Existe algún material que discuta este tema específicamente?


Los dos enfoques se describen en el sitio XUnit Test Patterns: xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . Es extraño que no estén en el libro.
guillaume31

Respuestas:


45

Inside-Out y Outside-In son términos bastante raros, más a menudo he oído / leído sobre la escuela clásica y la escuela de Londres .

  • Inside-Out (escuela clásica, de abajo hacia arriba ): comienza en el nivel de componente / clase (adentro) y agrega pruebas a los requisitos. A medida que el código evoluciona (debido a refactorizaciones), aparecen nuevos colaboradores, interacciones y otros componentes. TDD guía el diseño por completo.

  • Outside-In (escuela de Londres, top-down o "simulacro TDD" como lo llamaría Martin Fowler): conoce las interacciones y los colaboradores por adelantado (especialmente aquellos en los niveles superiores) y comienza allí (nivel superior), burlándose de las dependencias necesarias. Con cada componente terminado, pasa a los colaboradores previamente burlados y comienza con TDD nuevamente allí, creando implementaciones reales (que, aunque se usaban, no eran necesarias antes gracias a las abstracciones ). Tenga en cuenta que el enfoque de afuera hacia adentro va bien con el principio YAGNI .

Ninguno de los enfoques es el único ; ambos tienen su lugar dependiendo de lo que hagas. En las grandes soluciones empresariales, donde partes del diseño provienen de arquitectos (o existe por adelantado), uno podría comenzar con el enfoque de "estilo londinense". Por otro lado, cuando se enfrenta a una situación en la que no está seguro de cómo debería verse su código (o cómo debería encajar en otras partes de su sistema), podría ser más fácil comenzar con algún componente de gama baja y dejarlo evolucionan a medida que se introducen más pruebas, refactorizaciones y requisitos.

Cualquiera que use, la mayoría de las veces es situacional.

Para leer más, hay una publicación grupal de Google con una discusión bastante interesante sobre cómo se originó esta distinción y por qué Londres podría no ser el nombre más apropiado.


2
Interesante. ¿Cómo llegaste a la conclusión de que afuera en TDD hay TDD "simulacro"? Prefiero el pensamiento y el diseño de afuera hacia adentro y, por lo tanto, las pruebas (ver softwareonastring.com/2015/01/10/… ), sin embargo, el artículo de Fowler me coloca firmemente con Fowler en el campo clasicista. Si bien los simulacros siempre pueden usar un enfoque de afuera hacia adentro, no puede darle la vuelta y decir que el diseño y las pruebas de afuera hacia adentro son simulacros TDD. De afuera hacia adentro puede ser y mucho es practicado por los TDD clasicistas también.
Marjan Venema

@jimmy_keen - Con afuera hacia adentro, ¿en algún momento reemplazas las simulaciones en las pruebas de nivel superior con las implementaciones reales creadas más tarde? ¿O los deja como dependencias simuladas y luego ejercita todo el código de producción como prueba de integración?
thehowler

1
No estoy de acuerdo con que Classic / Mockist y Inside-Out / Outside-In estén relacionados. Son ortogonales. Puede usar Inside-Out / Outside-In con cualquiera.
Daniel Kaplan

De acuerdo con Daniel Estás comparando dos taxonomías que son diferentes. Aunque el desarrollo de afuera hacia adentro a menudo se asocia con la escuela de Londres (simulacro), no siempre es así.
guillaume31

No creo que esta sea una descripción correcta del proceso de afuera hacia adentro. Se trata de probar desde las interfaces públicas sin acoplar a internos, tanto como sea posible.
mcintyre321

15

Respuesta breve: como de costumbre, dependerá de su preferencia de codificación y enfoque de equipo.

La codificación de adentro hacia afuera es excelente porque siempre tienes algo funcionando. La desventaja es que no necesariamente te ayuda a llegar a un lugar radicalmente diferente. Es más difícil trazar un rumbo de esta manera. Del mismo modo, escribir código en el exterior tiene el inconveniente de no tener necesariamente el beneficio de un rápido desarrollo iterativo y no necesariamente ver todas las oportunidades y patrones que pueden surgir de la estructura profunda del código.

He llegado a creer que ambos estilos de desarrollo son importantes y que, de hecho, es útil tener una combinación de estilos en un equipo. La idea es que de adentro hacia afuera es excelente para crear bloques de construcción, y el exterior al pensar proporciona estructura de forma y dirección.

Parte de mi razonamiento proviene de una escuela de pensamiento muy popular que actualmente promueve el desarrollo iterativo, que a menudo es sinónimo de desarrollo de adentro hacia afuera. Creo que el desarrollo iterativo es excelente cuando no tienes que ir demasiado lejos. Pero creo que el pensamiento global, en oposición a un proceso puramente iterativo, es invaluable para ciertos tipos de innovación y para llegar a un lugar menos obvio. Administrar adecuadamente, de adentro hacia afuera y de afuera hacia adentro juntos puede ser una combinación muy efectiva.


8

Debe agregar Prinicples, patrones y prácticas ágiles en C # a esa lista. No sé por qué agregó "en C #" al final. Los libros no son el idioma en absoluto y la única razón por la que no obtuvo 5 estrellas en Amazon es de personas que estaban decepcionadas con C # de sus ejemplos.

El autor defiende que, siempre que sea posible, debe intentar escribir código de afuera hacia adentro y confiar en gran medida en el diseño evolutivo, y estoy de acuerdo con su declaración. Su razonamiento es que a medida que agregamos funcionalidad, nuestro diseño siempre evolucionará. Si comenzamos con componentes de bajo nivel a medida que se agregan características, nos daremos cuenta de que esos componentes no están haciendo lo que nos gustaría que hicieran, o que las cosas deben moverse. Esto podría ser bastante costoso, especialmente si cada vez que mueve la funcionalidad de una clase a otra, necesita hacer el mismo movimiento en todos los proyectos de prueba de la unidad.

Por otro lado, si determina qué debe hacer su aplicación en primer lugar, codifica la interfaz externa. A medida que se agregan características y el código bajo prueba crece en tamaño, refactoriza su aplicación en más clases, pero mientras continúa este esfuerzo de refactorización, las pruebas unitarias originales que ha escrito siguen siendo válidas. Entonces comienza completamente por fuera y continúa refactorizando en más y más clases de bajo nivel, mientras agrega pruebas de unidad adicionales a esas clases internas, pero rara vez tendrá que moverse y reescribir sus pruebas de unidad.

Sin embargo, si identifica un subsistema específico de bajo nivel que su aplicación necesitará (y tal vez su empresa ya necesita ese subsistema en otras aplicaciones), este sería el momento de comenzar con un bloque de construcción de bajo nivel primero y luego construir la aplicación además de eso.


7

A mi entender, el concepto de desarrollo de afuera hacia adentro realmente se extiende en 2 niveles. Gerard Meszaros los describe brevemente como " diseño de afuera hacia adentro " y " codificación de afuera hacia adentro / adentro hacia afuera ".

  • El primer nivel es un nivel organizacional y de proceso. El diseño de afuera hacia adentro se entiende en lugar de arriba hacia abajo (cascada / taylorista) y de abajo hacia arriba. Con un enfoque de afuera hacia adentro, nos enfocamos en la perspectiva del usuario final. Comenzamos con pruebas de historia, pruebas de ATDD o BDD y continuamos "hacia adentro" para inferir pruebas técnicas y código. Por lo tanto, el diseño de afuera hacia adentro suele ser lo que haría en un contexto ágil. Dan North tiene una gran charla sobre BDD, enfoques de arriba hacia abajo, de abajo hacia arriba y de afuera hacia adentro.

  • El segundo nivel es técnico y tiene que ver con capas aplicativas. La codificación de afuera hacia adentro básicamente significa comenzar desde la interfaz de usuario e ir hacia adentro a la capa central (generalmente la capa de negocios / dominio). Se refiere a la codificación de adentro hacia afuera, que comienza desde la capa central y codifica las capas externas en último lugar.

Por lo tanto, podría tener un diseño de afuera hacia adentro con codificación de afuera hacia adentro o de adentro hacia afuera.

Donde no estoy de acuerdo con Meszaros es cuando asocia la codificación de adentro hacia afuera con las pruebas de integración, argumentando que en un contexto de adentro hacia afuera "en realidad no probamos el software externo en aislamiento del software interno". Pero creo que nada te impide hacerlo. Puede elegir perfectamente probar los objetos de la capa externa burlándose de los objetos de la capa interna incluso si el código de producción para esos ya existe. Solo tiene que agregar interfaces y simulacros encima de los objetos concretos existentes en lugar de escribir las interfaces, burlándose de ellas y luego creando las implementaciones más tarde como lo haría con la codificación de afuera hacia adentro.

En otras palabras, el estilo TDD simulacro o clasicista es una OMI una preocupación ortogonal a la codificación de adentro hacia afuera / de adentro hacia afuera. Puede usar perfectamente un estilo simulado junto con un enfoque de adentro hacia afuera. La razón detrás de esto es que el estilo simulacro / clasicista se trata de dependencias de código, mientras que la codificación de adentro hacia afuera / de adentro hacia afuera se trata de capas aplicativas .

Otra cosa importante es que las dependencias no son solo entre capas, sino que también existen entre objetos en la misma capa. Por ejemplo, es posible que desee comenzar con un objeto en su capa empresarial central (enfoque de adentro hacia afuera) y usar simulacros para aislar su objeto de otros objetos de la capa empresarial con los que habla. Esto sucede mucho con IoC: las abstracciones de las que depende su objeto a menudo se declaran en la misma capa, pero las implementaciones concretas se encuentran en una capa diferente.

Robert "Tío Bob" Martin menciona brevemente la codificación de adentro hacia afuera y cómo no necesariamente entra en conflicto con una arquitectura desacoplada en su publicación " Arquitectura limpia ".

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.