test serp seomofo scan google description check design architecture tdd agile

design - serp - ¿El desarrollo impulsado por la prueba toma el enfoque del diseño?



test seo tags (10)

En general, estoy de acuerdo con que TDD proporciona una especie de herramienta de diseño. La parte más importante de eso para mí es la forma en que se basa en la capacidad de hacer más cambios (ya sabes, cuando tienes ese momento de visión instantánea donde puedes agregar funcionalidad al eliminar el código) con un riesgo muy reducido.

Dicho esto, parte del trabajo más algorítmico que he contratado últimamente ha sufrido un poco en TDD sin un equilibrio cuidadoso de pensamiento de diseño. La afirmación anterior acerca de la refactorización más segura fue aún un gran beneficio, pero para algunos algoritmos TDD es (aunque sigue siendo útil) no suficiente para llegar a una solución ideal. Tome la clasificación como un simple ejemplo. TDD podría llevarlo fácilmente a un algoritmo subóptimo (N ^ 2) (y a las pruebas pasajeras que le permiten refactorizar a una clasificación rápida) como una ordenación de burbuja. TDD es una herramienta, una muy buena herramienta, pero al igual que muchas otras cosas, se debe usar de manera apropiada para el contexto del problema que se está resolviendo.

Tengo sentimientos encontrados sobre TDD. Aunque creo en las pruebas, tengo problemas con la idea de que la prueba impulse mi esfuerzo de desarrollo.

Cuando codifica para satisfacer algunas de las pruebas escritas para una interfaz para los requisitos que tiene ahora, puede cambiar su enfoque de construir código que se pueda mantener, desde el diseño limpio y desde la arquitectura de sonido.

Tengo un problema con conducir no con pruebas. ¿Alguna idea?


Estoy completamente de acuerdo con pjz. No hay una sola manera correcta de diseñar software. Si llevas TDD al extremo, sin ninguna previsión, excepto la próxima prueba unitaria, puedes hacer las cosas más difíciles para ti. Lo mismo ocurre con la persona que se embarca en un gran proyecto de software al pasar meses en diagramas y documentación, pero sin código.

Moderar. Si siente la necesidad de elaborar un diagrama rápido que le ayude a visualizar la estructura de su código, vaya por ello. Si necesita dos páginas, podría ser el momento de comenzar a escribir algún código. Y si quieres hacer eso antes de escribir tus pruebas, ¿qué? El objetivo es trabajar, software de calidad, no conformidad absoluta con ninguna doctrina particular de desarrollo de software. Haz lo que funcione para ti y tu equipo. Encuentra áreas donde se pueden hacer mejoras. Iterar.


Estoy completamente de acuerdo con usted en ese tema. En la práctica , creo que TDD a menudo tiene algunos efectos muy negativos en el código base (diseño defectuoso, código de procedimiento, sin encapsulado, código de producción lleno de código de prueba, interfaces en todas partes, código de producción difícil de refactorizar porque todo está estrechamente vinculado a muchas pruebas, etc. )

Jim Coplien ha dado charlas sobre este tema por un tiempo:

Estudios recientes (Siniaalto y Abrahamsson) de TDD muestran que puede no tener ningún beneficio sobre el último desarrollo de prueba tradicional y que en algunos casos ha deteriorado el código y que tiene otros efectos alarmantes (su palabra). El que más me preocupa es que deteriora la arquitectura. - El blog de Jim

También hay una discusión sobre InfoQ entre Robert C. Martin y James Coplien, donde abordan este tema.


Hay muchas opiniones informales aquí, incluida la opinión popular (de Jon Limjap) de que los malos resultados provienen de hacerlo mal, y las afirmaciones que parecen no respaldadas por algo más que la experiencia personal. La evidencia empírica de preponderancia y los resultados publicados apuntan en una dirección opuesta a esa experiencia.

La teoría es que un método que requiere que usted escriba pruebas antes de que el código lo lleve a pensar sobre el diseño a nivel de fragmentos de código individuales, es decir, programación en el pequeño. Dado que los procedimientos son todo lo que puede probar (aún prueba un objeto de a un método a la vez, y simplemente no puede evaluar las clases en la mayoría de los idiomas), su enfoque de diseño se dirige a los métodos individuales y la forma en que componen. Eso lleva, en teoría, a un diseño de procedimiento ascendente y, a su vez, a un mal acoplamiento y cohesión entre los objetos.

Los amplios datos empíricos corroboran la teoría. Siniaalto y Abrahamsson, ( estudio de caso comparativo sobre el efecto del desarrollo basado en pruebas sobre diseño de programas y cobertura de pruebas ), ESEM 2007, encontraron que "nuestros resultados indican que la cohesión puede ser peor (aunque Beck afirma que TDD produce sistemas altamente cohesivos) ). En nuestro segundo estudio notamos que las medidas de complejidad eran mejores con TDD, pero las métricas de administración de dependencias eran claramente peores ". Janzen y Saledian ( ¿El desarrollo impulsado por la prueba mejora realmente la calidad del diseño del software? IEEE Software 25 (2), marzo / abril de 2008, páginas 77 - 84) encontró que "[l] os resultados no respaldan las afirmaciones de un menor acoplamiento y mayor cohesión con TDD ".

Una revisión de la literatura descubrirá otras publicaciones que promueven estos casos.

Incluso mi querido amigo, el tío Bob escribe: "Uno de los mitos más insidiosos y persistentes del desarrollo ágil es que la arquitectura y el diseño vanguardistas son malos, nunca debes pasar el tiempo haciendo decisiones arquitectónicas, sino que debes evolucionar tu arquitectura y diseñar a partir de la nada, un caso de prueba a la vez. Perdónenme, pero eso es Horse Shit ". ("The Scatology of Agile Architecture", http://blog.objectmentor.com/articles/2009/04/25/the-scatology-of-agile-architecture )

Sin embargo , vale la pena señalar que el error más amplio es que las personas piensan que es una técnica de prueba en lugar de una técnica de diseño. Osherov señala una serie de enfoques que a menudo se equiparan casualmente con TDD. No puedo estar seguro de lo que significan los carteles aquí. Ver: http://weblogs.asp.net/rosherove/archive/2007/10/08/the-various-meanings-of-tdd.aspx .


Hay tres pasos para completar el software:

  1. Hazlo funcionar
  2. Hacer lo correcto
  3. Hazlo rápido

Las pruebas te dan el # 1. Su código no está hecho solo porque las pruebas hayan pasado. Preferiblemente tiene algún concepto de estructura de proyecto (Utilidades, objetos comúnmente accedidos, capas, marco) antes de comenzar a escribir sus pruebas / código. Después de escribir el código para que aprueben las pruebas, debe volver a evaluarlo para ver qué partes se pueden refactorizar a los diferentes aspectos de la aplicación. Puede hacerlo con confianza, porque sabe que mientras sus pruebas sigan pasando, su código sigue siendo funcional (o al menos cumple los requisitos).

Al comienzo de un proyecto, piense en la estructura. A medida que el proyecto avanza, continúe evaluando y reevaluando su código para mantener el diseño en su lugar o cambiar el diseño si deja de tener sentido. Todos estos elementos deben tenerse en cuenta cuando calcule, o terminará con el código spagetti, TDD o no.


Mi forma de pensar es escribir primero cómo quieres que se vea tu código. Una vez que tenga una muestra de su código objetivo (que en este momento no hace nada) ver si puede colocar un andamio de prueba sobre él. Si no puede hacer eso, descubra por qué no puede hacerlo. La mayoría de las veces se debe a que tomó una mala decisión de diseño (99%); sin embargo, si ese no es el caso (1%) intente lo siguiente:

  • Determine cuáles son los requisitos descabellados a los que debe atenerse y que no le permitirán probar su código. Una vez que comprenda los problemas, rediseñe su API.
  • si alguien más decide sobre estos requisitos, hable sobre él. Probablemente tengan una buena razón para el requerimiento y una vez que conozca la razón, podrá perfeccionar su diseño y hacerlo comprobable. Si no es así, ambos pueden volver a trabajar el requisito y ambos serán mejores para él.

Después de que tenga su código objetivo y el andamio de prueba. Implementa el código. Ahora incluso tiene la ventaja de saber qué tan bien progresa a medida que pasa su propia prueba (¡es un gran motivador!)

El único caso donde las pruebas pueden ser superfluas, por experiencia personal, es cuando se está haciendo un prototipo temprano porque en ese punto aún no se comprende el problema lo suficientemente bien como para diseñar o probar el código con precisión.


No.

Si se hace bien, Test Driven Development IS es su herramienta de diseño.

Espero que me perdonen por vincularme a mi propia entrada de blog, en la que analizo los peligros del desarrollo impulsado por prueba que salió mal simplemente porque los desarrolladores trataron sus pruebas como, simplemente, pruebas.

En un proyecto anterior, los desarrolladores usaron un patrón de singleton altamente dañino que forzó las dependencias a lo largo del proyecto, lo que simplemente lo rompió todo cuando se modificaron los requisitos:

TDD fue tratado como una tarea, cuando debería haber sido tratado como un enfoque. [...]

Hubo un error al reconocer que TDD no se trata de pruebas, se trata de diseño. El caso rampante de abuso de singleton en las pruebas unitarias lo hizo obvio: en lugar de que los escritores de pruebas pensaran "WTF son estos singleton = valor; las declaraciones de hacer en mis pruebas? ", los escritores de prueba acaba de propagar el singleton en las pruebas. 330 veces

La desafortunada consecuencia es que las pruebas implementadas por el servidor de compilación se hicieron pasar, lo que sea que tomara.

Test Driven Development, hecho correctamente, debe hacer que los desarrolladores sean muy conscientes de las trampas de diseño como el acoplamiento cerrado, las violaciones de DRY (no se repita), las violaciones de SRP (principio de responsabilidad única), etc.

Si escribe el código de aprobación para sus pruebas con el fin de pasar sus exámenes, ya ha fallado: debe tratar las pruebas difíciles de escribir como señales que le hagan preguntar: ¿por qué se hace así? ¿Por qué no puedo probar este código sin depender de otro código? ¿Por qué no puedo volver a usar este código? ¿Por qué se rompe este código cuando se usa solo?

Además, si su diseño es realmente limpio y su código realmente puede mantenerse, ¿por qué no es trivial escribir una prueba para ello?


Siempre es un equilibrio:
- Demasiada TDD y terminas con un código que funciona, pero es un dolor en el que trabajar.
- Demasiado "código de mantenimiento, diseño limpio y arquitectura de sonido" y terminas con Astronautas de Arquitectura que se han convencido a sí mismos de la parálisis de codificación

Moderación en todas las cosas.


Siempre existe el riesgo de exagerar el diseño de TDD o el diseño inicial. Entonces la respuesta es que depende. Prefiero comenzar con una historia de usuario / prueba de aceptación, que es la base del requisito que mis pruebas ayudarán a producir. Solo después de que establecí eso, comencé a escribir pruebas detalladas de unidad estilo TDD. Si el único diseño y pensamiento que usted tiene es a través de TDD, arriesga demasiado enfoque de abajo hacia arriba, lo que podría proporcionarle unidades y clases que son excelentes de forma aislada, pero cuando intente integrarlas en la tarea de cumplimiento de la historia del usuario, podría sorprenderse por haberlo hecho todo mal. Para obtener más inspiración sobre esto, mira att BDD .

Se ha registrado un gran "debate" sobre esto entre Robert C. Martin y James Coplien, donde el primero es un defensor del TDD y el segundo ha declarado que arruina el diseño de un sistema. Esto es lo que Robert dijo sobre TDD y diseño:

"Ha habido un sentimiento en la comunidad Agile desde el ''99 de que la arquitectura es irrelevante, no necesitamos hacer arquitectura, todo lo que tenemos que hacer es escribir un montón de pruebas y hacer muchas historias y hacer iteraciones rápidas y la el código se ensamblará mágicamente, y esto siempre ha sido una mierda. Incluso creo que la mayoría de los proponentes originales de Agile estarían de acuerdo en que era una tontería ".

James Coplien afirma que simplemente conducir su diseño desde TDD tiene un gran riesgo:

"Una de las cosas que vemos mucho, en muchos proyectos, es que los proyectos avanzan hacia el sur en su tercer sprint y se estrellan y arden porque no pueden ir más lejos, porque se han arrinconado arquitectónicamente. Y no se puede refactorice para salir de esto porque la refactorización tiene que ser en categorías de clase, en jerarquías de clase, y ya no se puede asegurar que tenga la misma funcionalidad ".

También da un gran ejemplo de cómo una cuenta bancaria probablemente se vería si la prueba la impulsó en comparación con el uso de su conocimiento inicial para impulsar la arquitectura:

"Recuerdo que cuando estaba hablando con Kent una vez, sobre los primeros días cuando estaba proponiendo TDD, y esto fue en el sentido de YAGNI y haciendo lo más simple que posiblemente podría funcionar, y él dice: ''Ok. Hagamos un cuenta bancaria, una cuenta de ahorros. '' ¿Qué es una cuenta de ahorro? Es un número y se puede agregar al número y se puede restar del número. Entonces, qué es una cuenta de ahorro, es una calculadora. Hagamos una calculadora, y podemos demostrar que puede agregar al saldo y restar del saldo. Esa es la cosa más simple que podría funcionar, todo lo demás es una evolución de eso.

Si haces un sistema bancario real, una cuenta de ahorros ni siquiera es un objeto y no vas a refaccionar tu camino hacia la arquitectura correcta desde esa. Lo que una cuenta de ahorro es, es un proceso que realiza una iteración sobre una pista de auditoría de transacciones de base de datos, de depósitos y reuniones de intereses y otros cambios de dinero. No es como que la cuenta de ahorro es algo de dinero en el banco de un banco, aunque esa sea la perspectiva del usuario, y usted debe saber que existen estas estructuras relativamente intrincadas en los cimientos de un sistema bancario para respaldar la gente de impuestos y los actuarios y todas estas otras personas, a las que no se puede acceder de manera incremental. Bueno, puedes, porque la industria bancaria ha llegado a esto después de 40 años. ¿Quieres darte 40 años? No es ágil ".

Lo interesante aquí es que tanto el proponente de TDD como el antagonista de TDD dicen que se necesita diseño por adelantado.

Si tienes tiempo, mira el video. Es una gran discusión entre dos expertos altamente influyentes, y solo dura 22 minutos.


Soy relativamente nuevo en TDD y pruebas unitarias, pero en los dos proyectos paralelos en los que lo he usado, he descubierto que es un asistente de diseño en lugar de una alternativa al diseño. La capacidad de probar y verificar componentes / subcomponentes de forma independiente me ha facilitado realizar cambios rápidos y probar nuevas ideas de diseño.

La diferencia que he experimentado con TDD es la fiabilidad. El proceso de trabajar en la interconexión de componentes en niveles más pequeños de componente al inicio del proceso de diseño, en lugar de más tarde, es que tengo componentes en los que puedo confiar que funcionarán antes , así que puedo dejar de preocuparme por los pedacitos y obtener para trabajar en los problemas difíciles

Y cuando inevitablemente necesito regresar y mantener las piezas pequeñas, puedo pasar menos tiempo haciéndolo, para poder volver al trabajo que quiero hacer.