TDD experiencia negativa [cerrado]

94

¿Cuál es el lado negativo de su experiencia TDD? ¿Le parecen molestos e inútiles los pequeños pasos (la solución más simple para hacer que la prueba sea verde)? ¿Encuentra pruebas sin valor (cuando la prueba tiene sentido inicialmente pero en la implementación final verifica la misma lógica que otras pruebas)? etc.

Las preguntas anteriores son sobre cosas con las que me siento incómodo durante mi experiencia TDD. Por lo tanto, me interesa saber si otros desarrolladores tienen sentimientos similares y qué piensan de ellos.

Agradecería los enlaces a los artículos que describen los lados negativos de TDD (Google se llena de artículos positivos y a menudo fanáticos).

revs Idsa
fuente
10
Supongo que no escuchará muchas respuestas honestas sobre las experiencias negativas de las personas, porque TDD todavía se encuentra en un estado de "adopción temprana" y la mayoría de las personas interesadas y comprometidas para intentarlo no son lo suficientemente objetivas para evaluarlo por sus méritos relativos. Por lo general, la industria tarda varios años en establecer realmente los efectos a largo plazo de los nuevos procesos y técnicas, e incluso entonces es difícil obtener respuestas directas debido a la falta de controles. ¡Buena pregunta, sin embargo, y buena suerte para obtener respuestas útiles!
Aaronaught
20
¿Tienes problemas para encontrar negatividad en Internet?
Eric Wilson
44
@Job (y posiblemente otro): no olvide que le preguntó sobre TDD, no sobre pruebas unitarias. TDD! = Prueba unitaria.
n1ckp
2
Estoy tentado a responder esta pregunta, pero realmente no quiero comenzar porque me llevará la mitad de mi día.
Rei Miyasaka
2
Cuando me encuentro gastando suficiente tiempo en errores que parece que podría pasar menos tiempo escribiendo pruebas para cada cosa que escribo antes de escribirlo, no adoptaré test-first-all-things-TDD. En cambio, me avergonzaré y comenzaré a buscar una nueva carrera. ¿No sobre los errores que dices? ¿Diseño? Si. Eso es. Eso es exactamente. Y no has aprendido nada sobre el diseño robusto al darte una red de seguridad y una licencia para seguir trabajando estúpidamente. Guarde el IDE e intente leer su código si desea descubrir el verdadero problema.
Erik Reppen

Respuestas:

94

Como todo lo que viene bajo el lema "Agile", TDD es algo que suena bien en teoría, pero en la práctica no está tan claro qué tan bueno es (y también como la mayoría de las cosas "Agile", se le dice que si no lo hace me gusta, lo estás haciendo mal).

La definición de TDD no está grabada en piedra: los tipos como Kent Beck exigen que se escriba una prueba que no se compila antes de una sola línea de código y cada línea de código se debe escribir para aprobar una prueba fallida. El diseño inicial es mínimo y todo se manejapor las pruebas. Simplemente no funciona. He visto una gran aplicación empresarial desarrollada utilizando esa metodología y espero que sea el peor código que veo en mi carrera (no estará muy lejos; y eso fue a pesar de tener algunos desarrolladores talentosos trabajando en ello). Por lo que he visto, da como resultado una gran cantidad de pruebas mal pensadas que validan principalmente que ocurren llamadas a funciones, que se lanzan excepciones cuando las variables son nulas y el marco burlón obtiene un entrenamiento completo (whoop-de-whoop); su código de producción se acopla mucho a estas pruebas y el sueño de una refactorización constante y fácil no aparece; de ​​hecho, las personas son aún menos propensas a corregir un código incorrecto debido a todas las pruebas que se romperán.

Por el contrario, he oído a personas argumentar que TDD significa diseñar las pruebas por adelantado en un alto nivel como parte de la fase de planificación, junto con el diseño arquitectónico. Estas pruebas pueden cambiar durante el desarrollo a medida que hay más información disponible, pero se han considerado cuidadosamente y ofrecen una buena guía sobre lo que el código debería hacer realmente. Para mí eso tiene mucho sentido.

usuario23157
fuente
77
+1 "diseñar las pruebas por adelantado en un alto nivel como parte de la fase de planificación, junto con el diseño arquitectónico" También me parece mucho más razonable.
Steven Jeuris
11
@Aaronaught Agile no significa que no hay planificación, significa que es justo a tiempo .
Adam Jaskiewicz
25
@ Adam Jaskiewicz: Me encanta la cosa de "no planificar por adelantado". Vamos, la planificación es directa por definición . Si no planifica de antemano pero durante el evento no está planeando en absoluto; Estás improvisando. ;-)
CesarGon
34
@Adam: "¿Realmente las personas saltan directamente a la codificación el primer día de una iteración? erm sip. Ese es el hombre "ágil". El último lugar donde trabajé (y me despidieron por no ser "ágil") hicieron un ciclo completo de lanzamiento de 3 meses sin planear una sola línea de código o hacer una sola página de documentación. Y sí, el código era terrible y sí, el software era lento, torpe y con errores. El día que me uní, el gerente me dijo con orgullo que eran "La tienda más ágil de Londres". Seguro que lo fueron.
77
Puede agregar otro problema: siempre que pase la prueba, debe ser bueno. No importa que la prueba en sí misma pueda ser defectuosa y, por lo tanto, cause falsos negativos y / o falsos positivos. Y, por supuesto, requiere una "cobertura de prueba del 100%" y todo lo que tiene es, por definición, perfecto, lo que provoca pruebas inútiles que en realidad no prueban nada, sino que están escritas únicamente para lograr esa cobertura del 100%, código que no está documentado porque su contador de cobertura cuenta comentarios como código descubierto, etc., etc.
partir del
66

Esta ( autor de Clojure ) entrevista de Rich Hickey contiene lo siguiente. Me siento 100% comprensivo:

La vida es corta y solo hay un número finito de horas en un día. Entonces, tenemos que tomar decisiones sobre cómo gastamos nuestro tiempo. Si lo pasamos escribiendo pruebas, ese es el tiempo que no estamos gastando haciendo otra cosa. Cada uno de nosotros necesita evaluar la mejor manera de pasar nuestro tiempo para maximizar nuestros resultados, tanto en cantidad como en calidad. Si la gente piensa que pasar el cincuenta por ciento de su tiempo escribiendo pruebas maximiza sus resultados, está bien para ellos. Estoy seguro de que eso no es cierto para mí, prefiero pasar ese tiempo pensando en mi problema. Estoy seguro de que, para mí, esto produce mejores soluciones, con menos defectos, que cualquier otro uso de mi tiempo. Un mal diseño con un conjunto de pruebas completo sigue siendo un mal diseño.

Otra declaración similar de Donald Knuth en la entrevista del libro Coders at Work , copiada y pegada desde aquí :

Seibel: Hablando de trabajo práctico, en medio de trabajar en El arte de la programación de computadoras tomaste lo que se convirtió en un descanso de diez años para escribir tu sistema de composición tipográfica TeX. Entiendo que escribiste la primera versión de TeX completamente lejos de la computadora.

Knuth: Cuando escribí TeX originalmente en 1977 y '78, por supuesto, no tenía programación alfabetizada, pero tenía programación estructurada. Lo escribí en un cuaderno grande a mano, a lápiz. Seis meses después, después de completar todo el proyecto, comencé a escribir en la computadora. E hice la depuración en marzo del '78 mientras comencé a escribir el programa en octubre del '77. El código para eso está en los archivos de Stanford, todo está escrito a lápiz, y, por supuesto, volvería y cambiaría una subrutina a medida que aprendiera lo que debería ser. Este era un sistema de primera generación, por lo que muchas arquitecturas diferentes eran posibles y tuvieron que descartarse hasta que viví con él por un tiempo y supe lo que había allí. Y era un problema de huevo y gallina: no se podía escribir hasta que se tenían las fuentes, pero no se podían tener las fuentes hasta que se podían escribir. Pero la programación estructurada me dio la idea de invariantes y saber cómo hacer cajas negras que pudiera entender. Así que tenía la confianza de que el código funcionaría cuando finalmente lo depurara. Sentía que ahorraría mucho tiempo si esperaba seis meses antes de probar cualquier cosa. Tenía suficiente confianza en que el código era aproximadamente correcto.

Seibel: ¿Y el ahorro de tiempo sería porque no pasarías tiempo construyendo andamios y trozos para probar el código incompleto?

Knuth: bien.

Joonas Pulakka
fuente
24
Creo que tienes que mirar el tipo de trabajo que estás haciendo. Knuth y Hickey están hablando sobre el diseño de nuevas aplicaciones (innovadoras). Si observa dónde es popular el TDD (sobregeneralización amplia), entonces se da cuenta de que la mayoría de las aplicaciones escritas de manera TDD ya tienen una arquitectura bien conocida.
sebastiangeiger
44
Puedo ver lo que Rich Hickey significa, pero me gustaría agregar esto: mi experiencia es que cuando escribes las pruebas, necesitas pensar realmente en tu diseño y pensar en cómo hacer que tu código sea comprobable, lo cual, en mi experiencia, resultados en un mejor diseño.
Niklas H
3
Al ver que el OP solicita experiencias negativas con TDD, ninguno de sus ejemplos parece relevante para esta pregunta, ya que ninguno muestra un ejemplo de TDD en acción.
Winston Ewert
55
@Michael Borgwardt: es relativamente fácil agregar pruebas a un buen diseño existente para eliminar errores en la implementación. Pero deshacerse del mal diseño a menudo significa una reescritura completa. Por lo tanto, el objetivo principal debe ser lograr el diseño correcto; La ejecución es más fácil de arreglar más adelante.
Joonas Pulakka
44
La mayoría de las aplicaciones comerciales no tienen el beneficio de ser escritas y / o mantenidas por Donald Knuth. La vida útil de una aplicación suele ser MUCHO más larga que su desarrollo principal. Ojalá la gente hubiera escrito más pruebas por adelantado en mi proyecto actual. Ahora el mantenimiento es como un campo minado de regresiones infinitas.
Matt H
58

Mi experiencia negativa con TDD fue la primera. TDD sonó genial para mí, había hecho control de calidad durante años y todavía tenía los horrores frescos en mi mente. Quería eliminar todos los errores antes de que se convirtiera en una compilación. Desafortunadamente, usar TDD no garantiza que escribirás buenas pruebas. De hecho, mi predisposición inicial era escribir pruebas simples que generaran código simple. Código realmente simple que contenía pocas abstracciones. Pruebas realmente simples que se entrelazaron con las partes internas de la clase. Y una vez que tenga algunas miles de pequeñas pruebas en su lugar, seguramente no sentirá que se está moviendo más rápido cuando tenga que cambiar un centenar de ellas para refactorizar su código para usar el concepto de dominio X muy importante.

La luz se encendió para mí: TDD no es una habilidad de prueba. Es una habilidad de diseño. Solo puede llevarlo a un código bueno, simple y viable con práctica y un conocimiento constante de las instrucciones de diseño en las que lo lleva. Si está escribiendo pruebas por el bien de la cobertura del código, creará pruebas frágiles. Si está escribiendo pruebas para ayudarlo a diseñar sus abstracciones, entonces es solo una forma más rigurosa de escribir código de arriba hacia abajo. Primero puede ver el código desde la perspectiva de la persona que llama, lo que lo alienta a facilitarle la vida, en lugar de reflejar las partes internas de una clase en su borde exterior.

Creo que TDD es útil, pero no soy dogmático al respecto. Si esas "pruebas sin valor" dificultan el mantenimiento, ¡bórrelas! Trato las pruebas de la misma manera que el resto del código. Si se puede refactorizar y simplificar las cosas, ¡hazlo!

No lo he visto personalmente, pero he oído que algunos lugares rastrean la cobertura del código y los recuentos de pruebas. Entonces, si la recopilación de métricas es un efecto secundario de TDD, entonces podría ver eso también como negativo. Eliminaré con entusiasmo 1000 líneas de código, y si eso obsoleta 20 pruebas y cae el% de cobertura de mi código, bueno.

Steve Jackson
fuente
77
Lo has clavado en el párrafo 2.
Sheldon Warkentin
44
"No lo he visto personalmente, pero he escuchado que algunos lugares rastrean la cobertura del código y los recuentos de pruebas". He vivido en un entorno así y, de hecho, nunca se descartó ningún código porque al hacerlo podría fallar una prueba. Hasta que comencé a depurar las pruebas reales, es decir, y encontré que muchas de ellas tenían fallas tan serias que obligaron al código a producir resultados incorrectos para que las pruebas pasen. Fue entonces cuando acuñé la pregunta: "quién está probando las pruebas" a lo que hasta ahora nunca he tenido una respuesta satisfactoria de la comunidad TDD. Pruebas unitarias para pruebas unitarias, ¿alguien?
Jwenting
@jwenting - Y esta anécdota apoya bastante bien el argumento de Rei. He descubierto que el aspecto de protección de regresión de TDD es exagerado en la práctica, incluso si es una idea sólida en teoría. Las pruebas deben realizarse para que se mantengan al mismo nivel que el código de producción para que funcione, y no es natural tratar el código que no es de producción de esta manera: veo la misma "descomposición del código" con simuladores de hardware, generadores de código, etc todo el tiempo.
Steve Jackson
"Pruebas realmente simples que se entrelazaron con los elementos internos de la clase" <- ahí está tu problema. Prueba solo para interfaces públicas. TDD! = UT
Steven A. Lowe
2
@ StevenA.Lowe - Lo sé ahora, pero hace 9 años no estaba tan claro :) "TDD no es una habilidad de prueba"
Steve Jackson
41

Voy a arriesgarme aquí y declarar con brutal honestidad que es literalmente una pérdida ritual de tiempo. (En la mayoría de las situaciones).

Compré un libro sobre Pruebas unitarias que también hablaba de TDD, y aunque estoy de acuerdo con los beneficios de UT, después de aproximadamente cien horas de probar TDD, renuncié a él por una infinidad de razones. Estoy haciendo publicaciones cruzadas aquí, pero TDD:

  1. No es mejor documentación que la documentación real.
  2. No detecta errores o regresiones .
  3. Realmente no hace que mis diseños sean mejores de lo que terminan siendo si aplico algunos conceptos funcionales de programación y composibilidad
  4. Es el tiempo que podría pasar mejor haciendo revisiones de código o puliendo documentación y especificaciones.
  5. Da a los gerentes una falsa sensación de seguridad cuando ven una lista de cientos de íconos verdes.
  6. Mejora la productividad en la implementación de algoritmos con asignaciones limitadas de entrada-salida.
  7. Es torpe porque puede saber lo que está haciendo como resultado de TDD, pero no está entendiendo por qué funciona tan bien, por qué sus diseños salen como lo hacen.

Otra preocupación es el grado de perfección debatido al que se debe hacer TDD para hacerlo con éxito. Algunos insisten en que si TDD no es realizado de manera persistente por todos en el equipo desde el comienzo del proyecto, solo sufrirá. Otros insisten en que nadie hace TDD por el libro. Si esto es cierto, se deduce que los practicantes de TDD están sufriendo, se den cuenta o no.

Por supuesto, si se argumenta que al hacer las cosas de una manera similar a TDD, obtendrá diseños que pueden funcionar fácilmente con TDD, bueno, hay formas mucho más rápidas de lograrlo, es decir, estudiando realmente los conceptos de componibilidad Hay muchos recursos por ahí, mucha teoría matemática rigurosa incluso (en gran parte en programación funcional pero también en otros campos). ¿Por qué no pasar todo su tiempo TDD aprendiendo ?

Culturalmente, TDD muestra síntomas de ser una práctica ritualista. Se basa en la culpa; fomenta el procedimiento sobre la comprensión; tiene toneladas de doctrinas y lemas ("fingir hasta que lo consigas" es realmente alarmante si lo miras objetivamente). La definición de Wikipedia de la palabra "ritual" es de hecho bastante apropiada:

En psicología, el término ritual a veces se usa en un sentido técnico para un comportamiento repetitivo utilizado sistemáticamente por una persona para neutralizar o prevenir la ansiedad; Es un síntoma de trastorno obsesivo-compulsivo.

Rei Miyasaka
fuente
Perspectiva muy interesante re: ritual. También tiene la sensación, en algunos círculos, de que el compromiso de un programador con su oficio se considera únicamente proporcional a su adhesión al TDD.
yalestar
Yo diría que en algunas situaciones puede mejorar un diseño, pero sobre todo es cuando el diseño debe ser altamente modular con una interfaz pública muy bien definida y fácil de usar. Escribir las pruebas antes de implementar la biblioteca en esos casos puede ayudar a resolver los errores en la interfaz pública, así como forzar esa modularidad.
Jwenting
8
@jwenting Las personas hacen TDD porque no saben qué hace que un diseño sea modular, por lo que nunca pueden quitar sus ruedas de entrenamiento de 35 "de sus bicicletas de 40". Hacer un diseño modular siempre es una tarea manejable si comprende los conceptos, porque cada dilema en su diseño será de un tamaño manejable debido a que, en su concepción, está en proceso de convertirse en modular. No estoy en desacuerdo con que TDD sea efectivo para forzar la modularidad, pero no estoy de acuerdo con que uno deba ser forzado a crear diseños modulares. El diseño modular es una habilidad que se puede enseñar y aprender perfectamente.
Rei Miyasaka
@jwenting Con respecto a la usabilidad de las interfaces públicas, hay dos escuelas de pensamiento entre los profesionales de TDD sobre el tema, las cuales son indeseables: hacer que todo sea público para que pueda probarse, o dejar las cosas privadas si no deberían probarse de todos modos . El primero obliga a exponer detalles de implementación innecesarios a los usuarios finales (que pueden ser mal utilizados o explotados), y el último obliga a las pruebas unitarias a estar más cerca de las pruebas del sistema. Claro, podría usar herramientas de prueba de unidad para acceder a privados, pero eso no tiene mucho sentido en TDD.
Rei Miyasaka
1
@Kall En esa entrevista, dice "entre un 15 y un 35% más de tiempo", no solo el 15% como lo ha citado. El estudio también solo involucra Java / C ++ / C # (probablemente C # 2, dada la fecha): todos los lenguajes del mismo paradigma imperativo de OOP. Ciertamente, soy más del 15% y probablemente más del 35% más productivo en un lenguaje funcional (e incluso en C # 3), y produzco muchos menos errores al escribir código sin estado y componible, el mismo tipo de errores que las pruebas mejoran, porque ambas cosas resuelven exactamente los mismos tipos de problemas. En otras palabras, claro, 60-90% de reducción en errores, pero ¿en comparación con qué ?
Rei Miyasaka
18

Para agregar, otra preocupación con TDD que noté es:

¡TDD provoca un cambio inadvertido en el enfoque del equipo de desarrollo de Código de calidad a Casos de prueba y cobertura de código! ¡Personalmente no me gustó TDD ya que me hace menos creativo y hace que el desarrollo de software sea un proceso mecánico aburrido ! Los casos de prueba unitarios son útiles cuando se usan juiciosamente pero se convierten en una carga cuando se trata el objetivo del desarrollo de software.

Conozco a un tipo que es gerente y que técnicamente es aburrido una vez que se obsesionó con TDD. Fue algo tan mágico para él que creía que aportaría soluciones mágicas a todos los problemas en su software mal diseñado con un código menos mantenible. Sin decir lo que sucedió con ese proyecto, falló miserablemente en sus manos, mientras que todas sus cajas de prueba eran verdes. Supongo que TDD lo ayudó a obtener algún tipo de información estadística, como "99/100 de mis casos son verdes", etc., y esa fue la razón de su obsesión, ya que nunca podría evaluar la calidad o sugerir mejoras en el diseño.

Kiran Ravindranathan
fuente
2
Suena como el infierno de PHB! Me recuerda a las empresas que introducen esquemas de bonificación; lo que sucede, por supuesto, es que los desarrolladores en lugar de centrarse en el código de calidad, se centran en cumplir los requisitos de bonificación. Inevitablemente, obtienes un código más desagradable. (También hay una analogía aquí con la crisis bancaria actual :-))
TrojanName
Bueno, TDD no es una técnica de gestión de proyectos, por lo que no es de extrañar que su aspirante a gerente haya fallado. Por otro lado, no me siento menos creativo, incluso me siento más creativo porque desarrollar pruebas automáticamente me da otra vista sobre mi código. Sin embargo, estoy de acuerdo en que el enfoque debe ser el código de producción, y las pruebas no deberían estropear una buena arquitectura de software.
Alex
La cobertura del código es una preocupación de Pruebas unitarias, no de TDD. TDD solo se preocupa por las funciones y pruebas a través de interfaces públicas.
Steven A. Lowe
14

Mi experiencia negativa principal es tratar de usar TDD para editar el código de otro programador que no tiene pruebas, o pruebas de integración muy, muy básicas. Cuando voy a agregar una función o corregir un problema con dicho código; Preferiría escribir una prueba primero (la forma TDD). Desafortunadamente, el código está estrechamente acoplado, y no puedo probar nada sin mucha refactorización.

La refactorización es un gran ejercicio de todos modos, pero se requiere para llevar el código a un estado comprobable. Y después de este paso, no tengo controles ni saldos para ver si mis cambios rompieron algo; antes de ejecutar la aplicación y examinar cada caso de uso.

Por otro lado, agregar funciones / corregir errores a un proyecto TDD se vuelve muy sencillo. Por naturaleza, el código escrito con TDD suele estar bastante desacoplado con pequeñas piezas para trabajar.

En cualquier caso, TDD es una guía. Sígalo hasta el punto en que encuentre que obtiene la máxima efectividad. Cobertura de prueba decente y código desacoplado, código bien escrito.

Sheldon Warkentin
fuente
1
Si es difícil escribir pruebas unitarias, generalmente hay una separación deficiente de las preocupaciones. No veo esto como culpa de TDD, en todo caso rápidamente hace que estos problemas sean obvios.
Tom Kerr
77
Esa no es una experiencia negativa con TDD, es una experiencia negativa con un código malo.
Rei Miyasaka
13

Hice la experiencia de que a veces confío demasiado en mis pruebas cuando se trata del diseño del sistema. Básicamente, soy demasiado bajo en los detalles de implementación esenciales para dar un paso atrás para ver el panorama general. Esto a menudo resulta en un diseño innecesariamente complejo. Lo sé, se supone que debo refactorizar el código, pero a veces tengo la impresión de que podría ahorrar mucho tiempo dando un paso atrás con más frecuencia.

Dicho esto, si tiene un marco como rieles donde sus decisiones arquitectónicas son muy limitadas, estos problemas son básicamente inexistentes.

Otro problema es cuando confía ciegamente en sus pruebas. La verdad es que, como cualquier otro código, sus pruebas también pueden tener errores. Sea tan crítico con sus pruebas como lo es con su implementación.

sebastiangeiger
fuente
2
¡Tal vez deberías escribir algunas pruebas para tus pruebas! : p ...... I Kid, I Kid
Aren
+1 +1 +1 +1 (si tuviera 3 cuentas ficticias). La oración # 2 es muy perspicaz y está libre del sesgo de confirmación de TDD que es demasiado frecuente.
tgm1024
11

Como gran fanático de TDD, a veces veo estos inconvenientes

  • La tentación de escribir demasiadas pruebas en aras de una cobertura de código de casi el 100%. En mi opinión no es necesario escribir pruebas
    • para captadores / establecedores de propiedades simples
    • para cada caso cuando se lanza una excepción
    • que verifica la misma funcionalidad a través de diferentes capas. (Ejemplo: si tiene una prueba unitaria para verificar la validación de entrada para cada parámetro, entonces no es necesario repetir todas estas pruebas a través de una prueba de integración)
  • Costos de mantenimiento del código de prueba para pruebas similares, que varían solo levemente (creado a través de la duplicación de código (también conocido como copiar-pegar-herencia)). Si ya tiene uno, es fácil crear uno similar. Pero si no refactoriza el código de prueba, al eliminar la duplicación de código en métodos auxiliares, es posible que necesite algo de tiempo para corregir las pruebas si los detalles de implementación de su código comercial cambian.

  • Si está bajo presión de tiempo , puede verse tentado a eliminar las pruebas rotas (o comentarlas) en lugar de arreglarlas . De esta manera pierdes la inversión en las pruebas

k3b
fuente
2
+1: "Tentación de escribir demasiadas pruebas por casi el 100% de cobertura de código": caí en esta trampa una vez, y después de pasar tantas horas escribiendo todas esas pruebas unitarias, los únicos tres errores que encontré en mi código fueron no está cubierto por las pruebas unitarias y se puede encontrar fácilmente depurando el código paso a paso.
Giorgio
9

Todavía tengo que encontrar más de un escenario como desarrollador de juegos donde valió la pena TDD. Y la instancia en la que se encontraba era un código que era de naturaleza puramente matemática y necesitaba un enfoque sólido para probar una gran cantidad de casos extremos simultáneamente, una necesidad poco frecuente.

Tal vez algo, algún día cambie de opinión, pero entre las prácticas de XP, la idea de refactorizar sin piedad y de que el código desarrolle su propia forma es mucho más importante y me lleva a la mayor productividad, cf. una cita de un artículo de James Newkirk :

Simplicidad: "¿Cuál es la cosa más simple que podría funcionar?"
El mensaje es muy claro. Teniendo en cuenta los requisitos de hoy, diseñe y escriba su software. No intentes anticipar el futuro, deja que el futuro se desarrolle. A menudo lo hará de maneras muy impredecibles, haciendo que la anticipación sea un costo que a menudo es demasiado costoso ".

Los conceptos de coraje y de apretar los circuitos de retroalimentación que menciona también son, en mi opinión, clave para la productividad.

Ingeniero
fuente
99
El problema es que, sin pruebas unitarias, ¿cómo sabes que tu refactorización despiadada da como resultado un código que hace lo mismo? ¡En mi experiencia, descubrí que, dependiendo del problema, me puede tomar menos tiempo escribir pruebas + código que escribir el código por sí mismo! La razón se reduce principalmente al hecho de que, para algunos problemas, puedo probar un re-factor y volver a probar automáticamente mucho más rápido de lo que podría probarlo manualmente, lo que puede aumentar la velocidad de las iteraciones de manera bastante significativa.
Mark Booth
66
Para los juegos, muy a menudo se pueden ver los resultados. Si pueden verse y parecer lo suficientemente buenos, serán aceptados, ya que un juego pretende ser una experiencia subjetiva de todos modos. Por otro lado, tomando eg. Diablo 2 como ejemplo, el número de errores en las fórmulas de combate mostró dónde TDD habría aportado un gran valor y les habría ahorrado grandes cantidades de trabajo en parches. Para problemas muy bien definidos, como la resolución de ecuaciones, y donde estos no pueden ser juzgados por salidas visuales en tiempo de ejecución, TDD es imprescindible para garantizar la corrección. Pero eso es una pequeña fracción del código en la mayoría de los juegos.
Ingeniero
También vale la pena mencionar que, debido a la velocidad a la que se ejecutan las simulaciones, es mejor observar las variables en tiempo real, en pantalla, a medida que se ejecuta el sim, que sentarse con archivos de registro de millones de líneas para revisar el hecho.
Ingeniero
3
Las pruebas unitarias hacen que la refactorización sea mucho más fácil, en mi experiencia.
Tom Kerr el
1
@Nick El gran problema en la industria del juego son los plazos, que siempre son "tuvimos que entregar hace medio año". Creo que el tiempo juega contra pruebas unitarias en entornos de tiempo limitado. En algunos casos, no es una decisión correcta, pero en la mayoría de los casos el envío sin prueba de escritura es más rápido. Depende, realmente depende ...
Codificador
7

¡Mi experiencia negativa de TDD, por limitada que sea, es simplemente saber por dónde empezar! Por ejemplo, intentaré hacer algo TDD y no tengo idea de dónde comenzar a prohibir probar cosas triviales (¿puedo renovar un Fooobjeto, puedo pasar un Quuxa Baz, y cosas por el estilo? Pruebas que no prueban nada ), o si estoy tratando de implementarlo en un proyecto existente, entonces encuentro que tendría que reescribir varias clases para poder usarlas en TDD. El resultado final es que abandono rápidamente la noción por completo.

Probablemente no ayuda que a menudo soy la única persona en toda la empresa que sabe qué es la prueba de unidad (TDD o no) y por qué es algo bueno.

Wayne Molina
fuente
1
Aquí es donde entran en juego los marcos de simulación. Cree una instancia Foocon objetos simulados en lugar de Quuxy Bazdirectamente, luego puede llamar a la función que desea probar y luego verificar que los simulacros se llamaron con las funciones que espera. Los objetos simulados son la tecnología habilitadora que ayuda a desacoplar unidades y hacer que las unidades sean comprobables. Es por eso que los singletons son malvados, ya que a menudo no puedes simplemente burlarte de ellos. * 8 ')
Mark Booth
7

TDD fanáticos.

Para mí, son solo una de una larga lista de locos religiosos que llaman a mi puerta, tratando de demostrar que mi forma de hacer las cosas está irreparablemente rota y que el único camino hacia la salvación es Jesús, Kent Back o Unit Testing.

En mi opinión, su mayor mentira es que TDD te llevará a la salvación de un mejor diseño de algoritmo. Vea el famoso solucionador Soduku escrito en TDD: aquí , aquí , aquí , aquí y aquí

Y compárelo. El solucionador de sudoku Peter Norvig no se hizo usando TDD, sino usando ingeniería antigua: http://norvig.com/sudoku.html

rev. Cesar Canassa
fuente
Mira, podríamos discutir una y otra vez sobre esto. Pero tengo mucho trabajo que hacer desde que me gradué de la universidad Fullsail con mi título en diseño de juegos. Basado en mis cursos y mi trabajo muy exigente, puedo decir que TDD realmente triunfa sobre el desarrollo frenético línea por línea (falta de diseño) de programadores perezosos. Mire, no lo diría, pero es cierto: la mayoría de los desarrolladores que asistieron al programa de CS de una universidad normal en su mayoría no se graduaron, los pocos que lo hicieron abrumadoramente no se movieron al desarrollo de software, y además de eso, muchos de ellos apenas logran pasar , linea por linea. Fullsail university tiene un
Zombies
curso completo en desarrollo basado en pruebas solo y eso realmente pone a los desarrolladores en el camino correcto (en lugar de implementar una lista vinculada en c ++).
Zombies
Los enlaces están rotos amigo!
lmiguelvargasf
Esto es muchos años después, pero @Zombies, busca en "Confirmación Bias". Mucho de lo que se nos enseña a todos en CS en la universidad cae precisamente en esa categoría. Eche un vistazo al
descarte directo
Jajaja, estaba troleando ... Escribí que hace mucho tiempo me había olvidado de esa pequeña joya.
Zombies
5

Si utiliza TDD de estos artículos "fanáticos", tendrá la sensación de seguridad errónea de que su software no tiene errores.

Dainius
fuente
1
¿Puede sentir algo más que saber que para un conjunto dado de entradas su software devuelve un conjunto dado de salidas?
siempre y cuando comprenda que tdd es un proceso de desarrollo y no una regla de oro para resolver cualquier tipo de problema, está bien. Pero la mayoría de las personas que proponen usar este proceso olvidaron que es un proceso de desarrollo y, como cualquier otro proceso, tiene el lado positivo y el lado oscuro. Dicen para todos que si usarás tdd tendrás un software libre de errores, porque usarás test para cubrir todas las funciones. Y generalmente no está bien. De la mejor manera, habrá pruebas para cada caso (o al menos característica), pero las pruebas son programas (que tienen errores) y son solo pruebas de caja negra.
Dainius
4

TDD tiene algunos beneficios:

  • Te enfocas en cómo llamar a tu código y qué esperar primero (mientras escribes la prueba primero) en lugar de enfocarte en resolver el problema y luego pegar una llamada desde la aplicación. La modularidad hace que sea más fácil burlarse y envolverse.
  • Las pruebas aseguran que su programa funcione igual antes y después de una refactorización. Esto no significa que su programa esté libre de errores, sino que sigue funcionando de la misma manera.

TDD se trata de inversiones a largo plazo. El esfuerzo vale la pena cuando alcanza el modo de mantenimiento de su aplicación, y si la aplicación no está planificada para llegar a ese punto, es posible que nunca recupere la inversión.

Considero que el ciclo TDD rojo-verde con los pequeños pasos es similar a una lista de verificación para un avión. Es molesto y tedioso revisar todas y cada una de las cosas en el avión antes del despegue, especialmente si es trivialmente simple (los pequeños pasos del TDD) pero se ha descubierto que aumenta la seguridad. Además de verificar que todo funciona, esencialmente restablece el plano . En otras palabras, un avión se reinicia antes de cada despegue.

usuario1249
fuente
3
El punto de beneficio 2 se puede lograr con pruebas unitarias simples sin un enfoque TDD también. Beneficio 1 que deberías estar haciendo de todos modos. (Centrándose en la API) Todavía es completamente posible crear una API deficiente utilizando TDD, pero sí, tiene la garantía de que funcionará (para las pruebas escritas).
Steven Jeuris el
2
La pregunta no era preguntar sobre los beneficios de TDD. Ya hay muchas otras preguntas al respecto.
Aaronaught
1
@aaronaught, estoy abordando sus puntos débiles.
Las respuestas deben abordar la pregunta .
Aaronaught
1
@aaronaught, luego escribe algunos de esos.
3

Mi experiencia negativa sobre TDD es algo que siento con muchas cosas nuevas e publicitadas. De hecho, disfruto de TDD porque garantiza la validez de mi código, y aún más importante: puedo reconocer las pruebas fallidas, después de agregar un nuevo código o cualquier tipo de refactorización.

Lo que me molesta acerca de TDD es el hecho de que hay muchas reglas o pautas al respecto. Como todavía es bastante nuevo, la mayoría de nosotros experimentamos ser principiantes en TDD. Entonces, lo que funciona bien para algunos de nosotros, podría no funcionar para otros. Lo que quiero decir es que no existe una forma real "incorrecta o correcta" de realizar TDD: existe la forma que funciona para mí y para mi equipo si tengo uno.

Por lo tanto, siempre que escriba pruebas, antes o después de que el código de producción realmente no importe, en mi humilde opinión, no estoy seguro de si las pruebas conducidas realmente significan que debe seguir todas las pautas que se indican en este momento, ya que aún no se ha demostrado que sean La solución ideal para el trabajo diario. Si encuentra una mejor manera de escribir pruebas, debe publicarla en un blog, discutirla aquí o escribir un artículo al respecto. Entonces, en diez años más o menos, podríamos haber compartido suficiente experiencia para poder determinar qué regla de TDD se puede suponer que es buena o no en una determinada situación.

Alex
fuente
+1 Excelente comentario. Realmente no tiene que ser la única forma verdadera o ninguna manera.
antipático el
3

Tengo, en más de una ocasión, un código escrito que descarté al día siguiente porque era torpe. Reinicié con TDD y la solución fue mejor. Por lo tanto, no he tenido demasiada experiencia negativa en TDD. Sin embargo, dicho esto, he pasado tiempo pensando en un problema y encontrando una mejor solución fuera del espacio TDD.

usuario23356
fuente
1
Por lo general, un segundo intento le dará más información sobre el problema que el primer intento, TDD o no.
wobbily_col
3

Descubrí que TDD funciona mal cuando se trata de sistemas emergentes. Soy un desarrollador de videojuegos, y recientemente usé TDD para crear un sistema que usa múltiples comportamientos simples para crear un movimiento de aspecto realista para una entidad.

Por ejemplo, hay comportamientos responsables de alejarlo de áreas peligrosas de diferentes tipos, y otros responsables de moverlo hacia áreas interesantes de diferentes tipos. Amalgamar la salida de cada comportamiento crea un movimiento final.

Las tripas del sistema se implementaron fácilmente, y TDD fue útil aquí para especificar de qué debe ser responsable cada subsistema.

Sin embargo, tuve problemas a la hora de especificar cómo interactúan los comportamientos y, lo que es más importante, cómo interactúan con el tiempo. A menudo no había una respuesta correcta, y aunque mis pruebas iniciales fueron aprobadas, el control de calidad podía seguir encontrando casos extremos en los que el sistema no funcionaba. Para encontrar la solución correcta, tuve que repetir varias conductas diferentes, y si actualizaba las pruebas cada vez para reflejar las nuevas conductas antes de comprobar que funcionaban en el juego, podría haber terminado tirando las pruebas una y otra vez. Así que eliminé esas pruebas.

Posiblemente debería haber tenido pruebas más fuertes que capturaron los casos extremos que QA descubrió, pero cuando tienes un sistema como este que se encuentra en la parte superior de muchos sistemas de juego y física, y estás lidiando con comportamientos con el tiempo, se vuelve un poco pesadilla para especificar exactamente lo que está sucediendo.

Es casi seguro que cometí errores en mi enfoque y, como dije para las entrañas del sistema, TDD funcionó de manera brillante e incluso admitió algunos refactores de optimización.

tenpn
fuente