TDD y Casos de Uso

Ya saben que me importa mucho usar Test-Driven Delopment. Yo diría que es lo primero a adoptar en un desarrollo, como “tecnología nueva”. Pero reconozco que no es fácil a veces transmitir la idea y convencer a la gente de adoptar TDD.

Por ejemplo, hay una idea flotando, que leí hace poco en una lista: “no uso TDD porque el sistema lo tengo que entregar en tres semanas”. Como si TDD fuera algo que alentece. Yo quisiera que se tomara el tiempo, entonces, en cuánto se gasta en la prueba manual o el tiempo que se ocupa usando el “debugger”.

Hace dos semanas, tuve el gusto de dar una charla aplicando TDD desde un “File, New Project”, gracias a la gente de @AltNetHispano (http://altnethispano.org/Inicio.aspx). Lo anuncié en VAN en Alt.NET Hispano: Desarrollando una Aplicación con TDD  y pueden ver el resultado en https://github.com/ajlopez/TddOnTheRocks/tree/master/TddApp con commits casi por test. Ese desarrollo fue orientado a terminar en 2 horas, y entonces se mostró cómo por refactor aparecen patrones, para mejorar el código en desarrollo, pero NO APARECEN desde el principio. Al comienzo, TDD brega por el “menor código” que pase el test. Todo mejoramiento de código pasa por refactor. Ese énfasis me hizo dejar algo de lado un tema importante, aunque lo aclaré en la charla: prefiero aplicar TDD escribiendo tests SOBRE CASOS DE USO.

Algo de ese “approach” aparece en la serie de post TDD paso a paso donde se ve cómo se va construyendo el software a partir de un problema planteado por el bueno de @hernanwilkinson. Vean cómo se hace poco diseño de implementación por adelantado: se puede hacer, pero en general con TDD se hace poco o de forma liviana. Los tests nos van guiando qué clases, métodos, estado interno NECESITAMOS debido a que vamos planteando los casos de uso.

En la charla de @AltNetHispano  se preguntó: ¿pero qué hacemos si en la primera iteración el cliente/”product owner” nos pide un diagrama de entidad-relación como entregable? Pues bien, respuesta corta: va a ser muy difícil aplicar TDD. Cualquier DER que entreguemos no se basará en casos de uso en concreto, sino que trataremos de “compilar” en nuestra cabeza un modelo POR ADELANTADO de lo que necesitamos. ¿Y eso es problema? No, si NO trabajan ágil y NO usan TDD. ¿Por qué es problema si quieren trabajar ágil y también quieren aplicar TDD? Porque cualquier DER que entreguen será un “dibujo”, algo medio inventado, basado en nuestra capacidad de visualizar qué se necesita SIN HABER planteado un solo caso de uso en concreto. Y hay un problema adicional: ese DER es una “bajada de línea”. En dos semanas más, alguien del equipo comenzará a decir: “no podemos hacer X porque rompemos el DER” y temas parecidos.

Otra bajada de línea aparece con: el “product owner” aparece ya desde el principio con un modelo de datos, de un sistema aún no construido (acepto mejor que venga con una base de datos de un sistema que YA se está usando).

De ahí mi énfasis en usar TDD guiado a su vez por CASOS DE USO. Hace que cada cosa que agregamos (clase, método, estado, entidades, etc…. ) HAGA SU APARICION por haber escrito los tests para un caso de uso. Hace un tiempo me encontré con ideas parecidas de parte de “Uncle Bob” Martin. Les recomiendo lectura de:

No DB

Un párrafo importante:

The center of your application is not the database. Nor is it one or more of the frameworks you may be using. The center of your application are the use cases of your application.

Sigo:

It makes me crazy when I hear a software developer describe his system as a “Tomcat system using Spring and Hibernate using Oracle”. The very wording puts the frameworks and the database at the center.

What do you think the architecture of that system would look like? Do you think you’d find the use cases at the center of the design? Or would you find the source code arranged to fit nicely into the pattern of the frameworks? Would you find business objects that looked suspiciously like database rows? Would the schema and the frameworks pollute everything?

Here’s what an application should look like. The use cases should be the highest level and most visible architectural entities. The use cases are at the center. Always! Databases and frameworks are details! You don’t have to decide upon them up front. You can push them off until later, once you’ve got all the use cases and business rules figured out, written, and tested.

Eso: “una vez que los casos de usos y las reglas de negocio se determinaron/descubrieron, escribieron, y PROBARON”.

A ver, repitan conmigo:

The center of your application are the use cases of your application.

De nuevo, por favor, en serio:

The center of your application are the use cases of your application.

The center of your application are the use cases of your application.

Bien, y ahora, a repetir cada día, frente al espejo:

Databases and frameworks are details!

Si, antes de lavarse los dientes a la mañana repetir:

Databases and frameworks are details!

Databases and frameworks are details!

;-)

Les aseguro que si repiten eso cada día, van a mejorar en sus “skills” de programación, van a mejorar en la calidad del software que engreguen, y van a desarrollar sin tener que pelearse con tecnologías adoptadas por que sí, o porque “era más fácil”.

Recuerden también: “fácil” no es “simple”, y bien puede que lo “fácil” conspire con lo “simple”. Para traer un ejemplo concreto: Rails es “fácil”, permite generar una aplicación web con dos o tres comandos. Ahora, vayan y vean si es “simple” el código.

Les recomiendo leer un “review” de alguna charla de “Uncle Bob” Martin, donde se evalúa lo de más arriba:

The delivery mechanism is an annoying detail

Ahí hay un Tweet de @unclebobmartin

A good architecture allows you to defer framework decisions. A good architecture allows frameworks to act as plugins to the app

Bien, yo diría que las disciplinas ágiles y TDD en particular, permiten también diferir las decisiones. Ese un punto importante. Por ejemplo, en el ejemplo de la charla que mencioné al principio, DIFERI el diseño de la base de datos. Eso permite hacer cambios en las primeras iteraciones, SIN TENER la carga, el peso de la inercia de tener un esquema de tablas, datos cargados, etc.. Pueden ver ese approach en los post:

Escribiendo una aplicación con TDD

Y lean un ejemplo de Ron Jeffries:

http://xprogramming.com/articles/but-we-need-a-database-dont-we/

http://xprogramming.com/articles/see-we-dont-need-a-database-yet/

Si en su equipo todavía hay resistencia a TDD, leer el post de Bob Martin:

http://blog.8thlight.com/uncle-bob/2012/01/11/Flipping-the-Bit.html

En mi charla se mencionó bibliografía. Uno de los libros mencionados fue el

http://www.dirigidoportests.com/el-libro

Les recomiendo leer el ejemplo que los autores describen al principio. Dos programadores, uno usando TDD, y otro trabajando rápido, adoptando frameworks, librerías, todo ya hecho, porque PARECE MAS FACIL, y hasta mejor. Lean el desenlace.

Les puedo comentar un caso, sin dar mucho detalle: en un sistema, había que realizar las tareas A, B, C. Con TDD hubiéramos ido avanzando, tal vez escribiendo un método que invoque a A, B, C, y viendo de revisar, en los tests, los resultados de esas tareas. En vez de eso, se adoptó un “Job Engine”, porque “ya estaba hecho”. Como ese “job engine” funciona dentro de un entorno de tecnología que necesita (usando colas en la nube, monitoreo, etc…), probar que las tareas A, B, C se realicen, es todo un problema. Un año y medio despues, todavía se está analizando por qué algunas tareas se traban en el sitio de producción, o por qué un “job” tarda 15 o más minutos en lanzarse, desde que el pedido se puso en la cola.

Bien, fue un post largo, y espero que haya sido de provecho para alguien. Un resumen:

- Usen TDD guiado por los casos de uso, aceptando lo menos posible “bajadas de línea” sin justificación

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

This entry was posted in 10549, 11699, 3463. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>