05-07-2010 Luis Artola
El software muchas veces se desarrolla en un escenario poco definido que irá cambiando a lo largo del desarrollo. Sin duda, es el gran caballo de batalla de los desarrolladores de software de hoy en día. Por consiguiente, el objetivo de cualquier equipo, es orientar su desarrollo a descubrir “la forma” de su software de la manera más rápida y confiable posible.
Para ello hay que buscar una manera que guíe tu desarrollo. Algo que “driven tu development”.
. Test Driven Development (TDD), Model Driven Development, loquesea Driven Development.
TDD seguramente sea una de las mejores maneras de descubrir el diseño de tu software, entendiendo el diseño de software como un conjunto de clases con unas responsabilidades y unas relaciones entre sí. Además, si eres realmente bueno haciendo TDD, se habilita la posibilidad de realizar refactoring y mejorar el diseño de tu código, los patrones que sigue, y su orientación a objetos, hasta dejarlo impecable. Además, se habilitan una serie de ventajas más. Algunos incluso afirman que si tienes TDD ya no necesitas nada más ( una idea provocadora y algo punky que me encanta, pero me parece algo excesiva).
Pero… ¿Qué pasa cuando el diseño (a nivel de OO y patrones) no es el principal caballo de batalla de tu aplicación?
Hace cuatro años, en mis comienzos profesionales y de este blog, definí algo torpe y ponpósamente el concepto de Template Driven Development, tras ver que la gente de 37 Signals tenía ideas parecidas a las mías con su concepto de Interface First. Y es que cuando tienes un cliente que es incapaz de visualizar aquello que le estás contando, es muy difícil capturar su feedback y saber si estás consiguiendo satisfacer sus requisitos. Necesitan un prototipo visual, y tú necesitas no perder el tiempo con prototipos inútiles. Es algo de lo que también habla la gente de Linking Paths: para descubrir lo que el cliente quiere, funcione muy bien crear un prototipo lo más real posible, “sin rellenar el funcionamiento”, por ejemplo. Quizá sea hacer, dentro del MVC, la V y la C…pero no la M.
Practico TDD en serio desde hace unos meses. A día de hoy todavía no soy capaz de confiar en mis pruebas unitarias lo suficiente porque no soy suficientemente bueno haciéndolas. TDD me ha descubierto que no soy tan bueno haciendo OO como creía. Me ha descubierto errores de diseño, bugs habituales… pero las pruebas automatizadas me está empezando a ahorrar bastante tiempo, la verdad.
A veces se utilizarán unas técnicas, otras veces otras, y otras veces varias a la vez, pero no creo que haya que aceptar dogmáticamente ninguna de ellas. Son diferentes herramientas y cada una tiene su utilidad. Pero utilizar TDD para todo, en mi opinión, es un error.
Lo que probablemente nunca funcione será hacer un gran superdiseño y luego intentar programar diez meses seguidos sin salirse de él.
Un par de links de Torres Burriel sobre integración entre diseño centrado en el usuario y metodologías ágiles. (link1, link2)
1. Venkman | julio 5th, 2010 at 10:30 am
“[Loquesea] como dogma y para todo, es un error”
2. Abel | julio 5th, 2010 at 11:00 am
Mmm, de buen rollito, ¿vale?, pero me da que estás mezclando churras con merinas.
Coincido contigo en que lo verdaderamente importante es darle a la persona (que no usuario ni cliente ni demás etiquetas que usamos a veces) que va a usar tu desarrollo lo que necesita (que no siempre es lo que quiere, ni lo cree que quiere, ni lo que cree que necesita, ni lo que le estamos intentando vender, ni lo que le han aconsejado que compre, …)
Bueno, igual no te he entendido, pero vienes a decir que empezar tu desarrollo con pruebas unitarias porque es lo que manda TDD (o el xDD que esté más de moda en este momento) no siempre es buena idea, y que igual es mejor empezar haciendo un prototipo sin funcionalidad, mostrarlo al cliente para confirmar que eso es lo que busca e ir rellenando la funcionalidad.
No sé, a mi esto de suponer que TDD implica que empieces tu desarrollo con pruebas unitarias me empieza a aburrir y a parecer una idea caduca, por limitada y reduccionista.
Después de ver herramientas como Cucumber (muy buena, por cierto, la presentación de BDD de Aceptación con Ruby http://www.slideshare.net/cavalle/bdd-de-aceptacin-con-ruby), que te permiten comenzar tu TDD (o BDD o como queramos llamarlo) con el interfaz de usuario, después de leer libros como el de #goos (http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627), que hacen lo mismo con una aplicación Swing (que no todo es J2EE es esto del java
), cada vez me queda más claro que hay otras opciones para hacer TDD, y que la primera herramienta de pruebas a incorporar en el desarrollo no tiene porque ser el jUnit o testNG de turno.
My 2 Cents,
Abel
3. Luis Artola | julio 5th, 2010 at 11:06 am
Hola @Abel,
no te sigo muy bien. Comentas: “No sé, a mi esto de suponer que TDD implica que empieces tu desarrollo con pruebas unitarias me empieza a aburrir y a parecer una idea caduca, por limitada y reduccionista. ”
La clave de TDD es hacer primero las pruebas y luego implementar el código…
Mi idea principal en este artículo es que TDD (hacer pruebas unitarias y luego implementar la clase, pasito a pasito) es una herramienta más, muy importante, pero una herramienta más. Y que, en cada situación, hay que ser flexible y elegir qué driven tu development…
gracias por los links!
4. Enrique Amodeo | julio 5th, 2010 at 12:43 pm
Hola señor@s, hay algunas cosas que hay que matizar sobre el TDD.
La primera es que TDD no significa sólo hacer test unitarios, también implica hacer tests de integración y más importante los tests de aceptación. Para mi herramientas como cucumber, son herramientas para hacer tests de aceptación.
La segunda es que aprender a hacer TDD sin nadie que te guie es muy difícil. Yo tardé un año hasta que le cogí el punto.
La tercera es que el TDD no dice que debes empezar tus proyectos con test, sino que debes hacer primero un test antes de escribir código de implementación. El orden correcto es: análisis de requisitos, test de aceptación, tests unitarios e implementación.
Para cada cosa se necesitan unas herramientas distintas. Para el análisis de requisitos podemos usar una combinación de historias de usuario y prototipos de interface de usuario. Esto de hacer prototipos es lo mismo que se propone en lo de “interface first” y es una idea bastante antigua. Si la interface que prototipais para aclarar requisitos es la definitiva o de usar y tirar, es cuestión de gustos. Para las pruebas de aceptación podemos usar cucumber o cualquier otro framework. Yo personalmente nunca pruebo las vistas de mi interface de usuario, sólo el controlador y el modelo (asumo que es MVC), con lo que no necesito cucumber, pero eso es algo polémico.
La cuarta y última es esto del BDD. Para mi BDD y TDD es lo mismo, nunca hubo distinción. Cuando leí por primera vez esto de BDD mi reacción fue de “y qué hay de nuevo en esto?”. Asi que los que vean diferencia, pensad que cuando digo TDD, me refiero a BDD.
Por cierto, el lubre de “Growing Object Oriented Software Guided Tests” es genial y lo recomiendo, ya que resume muy bien la idea que yo tengo de TDD.
Saludos !
5. Yeray Darias Camacho | julio 5th, 2010 at 12:44 pm
Estoy totalmente de acuerdo en que no se puede ser muy fanático o como algunos dicen “Talibán” en estos temas, aunque no estoy seguro que Enrique (en el artículo reseñado) quisiera decir que tienes que empezar con TDD y solo TDD y nada más que TDD
, porque seguro que lo primero que él hace es analizar el problema, aunque no me voy a meter en esa discusión interminable
Con respecto al tema del uso de prototipos o esqueletos sin lógica de negocio, tengo muy malas experiencias, y conozco mucha gente que también las ha tenido, porque dejas que gente que no desarrolla el código “real” se ponga a hacer prototipos y luego la cosa no es tan sencilla como diseñar pantallas con el Dreamweaver o el Frontpage (aunque no digo que no pueda ser una opción perfectamente válida). De todas maneras al capítulo “Paper Prototyping” del libro de Joel Spolsky (Joel on Software) me remito
, pongo un enlace (http://www.joelonsoftware.com/news/20030516.html) aunque ya está anticuado, recomiendo el capítulo del libro que solo son dos hojas de nada.
6. Luis Artola | julio 5th, 2010 at 12:54 pm
@Enrique Amodeo
estoy de acuerdo con todos tus matices.
Pero dices: “Esto de hacer prototipos es lo mismo que se propone en lo de “interface first” y es una idea bastante antigua. Si la interface que prototipais para aclarar requisitos es la definitiva o de usar y tirar, es cuestión de gustos.”
Si es una idea antigua o no.. no me parece importante. Imagino que lo que quieres decir es que está superada por el TDD, y que el TDD es mejor. Ahí es donde no estamos de acuerdo. TDD es mejor y es una maravilla… a veces.
Respecto a si los prototipos son de usar o tirar o no… y que eso es cuestión de gustos… pufff…¡para nada de acuerdo!. Trabajar la V y la C de tu MVC… no es exactamente prototipar… porque van a ser la VC definitiva. Lo bueno, es que al no implementar la M, puedes hacer cambios y adaptarte al feedback que te vaya dando el cliente de manera muy ágil y rápida. Y ayuda mucho a aclarar las necesidades del cliente.
Luego si eso ya te pones con la M, y ahí aplicas TDD a gogó …
7. Enrique Amodeo | julio 5th, 2010 at 1:16 pm
Cuando digo que es una idea antigua, me refiero a eso, a que es antigua, ni mejor ni peor. Puedes hacer prototipos y TDD, yo no lo veo excluyente. Simplemente el prototipado cubre la fase de análisis de requistios, mientras que TDD cubre la parte de tests de aceptación y unitarios. Cada requisito genera al menos un test de aceptación. Si para definir bien el requisito necesitas un prototipo, me parece bien, una imagen vale más que mil palabras.
Si usas MVC para tus UI, necesita tests también para el controlador, no sólo el modelo. La C suele ser compleja y propensa a fallos con lo que en este punto el TDD te puede ayudar. Si no puedes hacer tests de la C, tal vez es que tu UI no es realmente MVC o la tecnología/framework que uses para hacer la interface de usuario no lo sea o te impida hacer TDD. Yo lo de probar la vista no lo veo, pero es mi opinión.
Quizás no estamos de acuerdo en eso de hacer “prototipos definitivos”, y si encima no tienen tests en su parte controladora, peor. El prototipo te puede servir como semilla de tu UI pero nada más, excepto en los casos sencillos.
La interface de usuario no equivale a requisitos, puedes implementar los mismos requisitos con diseños diferentes en las interfaces de usuario, o incluso tener varios diseños/implementaciones de la UI en una aplicación multicanal o accesible AA, ¿qué ocurre si tienes diferentes canales de entreda: web, móbiles, desktop, mail?. De hecho el diseño de la UI es bastante volátil y el usuario tiende a querer cambiarlo frecuentemente.
Cierto, la UI te da una forma fácil de entenderte con el usuario, pero no es tu aplicación ni tus requisitos. Centrar el desarrollo de una aplicación en sólo la UI, me parece tan peligroso como centrar el desarrollo sólo en la BBDD.
Los desarrollos hay que centrarlos en los requisitos, hay que descubrirlos y no perder de vista que pueden cambiar. Los requisitos los implementas en tu core de negocio, no en la BBDD ni en la UI. La BBDD y la UI son partes periféricas del sistema, que deberían poderse cambiar de forma “sencilla” a petición del usuario.
Bueno, ya me salió la vena fanática…
8. Luis Artola | julio 5th, 2010 at 3:50 pm
jo, Enrique, gracias por tus parrafadas y por tu tiempo. En serio.
A ver, algunos matices:
Yo sí hago pruebas unitarias a mis C´s. Pero las hago después de hacer las C´s. Osea que no hago TDD, pero sí pruebas unitarias.
Y no hablo de utilizar siempre y todo el rato un “desarrollo dirigido por la VC”, sino que en ciertas situaciones puede aportarte más sobre el descubrimiento de la forma final de tu aplicación que hacer TDD.
gracias de nuevo por las aportaciones!
9. Enrique Amodeo | julio 5th, 2010 at 4:21 pm
De nada hombre. La verdad es que soy un poco verborreico, je, je…
Gracias por tus matizaciones, queda todo perfectamente claro.
¡ A seguir con tu blog ! En este mundo del software hace falta mucha discusión y difusión de ideas en nuestro idioma.
10. Dani Latorre | julio 6th, 2010 at 10:21 pm
Mmm…
Entiendo que se está “enfrentando” TDD con empezar trabajando en la interfaz de usuario, cosa que no acabo de entender.
En mi opinión, lo ideal es empezar entendiendo las necesidades de los usuarios que utilizarán la aplicación, trabajar sobre wireframes/prototipos de algún tipo, y a partir de ahí empezar a programar. Y una vez que se programa no tiene porqué haber problema alguno en hacer TDD(o yo no lo veo).
Y por supuesto que hay ocasiones que no tiene sentido hacer TDD(o yo tampoco lo veo XD). Por ejemplo ahora mismo estoy part-time con un proyecto de importación de una base de datos, a día de hoy no he visto sentido a escribir si quiera una línea de código de testing.