Estoy últimos días e visto platicas, post ( uno de ellos es este ) y mensajes en el twitter sobre cuestiones “agiles” y temas afines, aunque un tema en particular atrajo mi atención, es sobre TDD o como algunos lo conocen, y ya no pude evitar querer dar mi opinión al respecto; aunque antes que nada me veo obligado a dar unas premisas, en las cuales basare mi “punto”
Premisas ( o como las quieran llamar) :
- No todos los Programadores tienen el mismo Nivel : Esto es conocido por todos, aunque no aceptado públicamente – cuestiones de orgullo –, así como hay programadores que no necesitan documentación – un amante de gnu por allí de ejemplo? –, y otros que no necesitan pruebas unitarias para hacer programas con cero errores o quizá un numero mínimo de ellos… así también hay programadores, que con toda la documentación, capacitación y pruebas unitarias les falla la aplicación.. causas? quizá algún gen maligno, magia negra, el chupa cabras, la CIA interfiriendo nuestras ondas cerebrales con algún aparato electrónico a lo “Agente 86”… o quizá algo mas de experiencia y aprender de los errores pasados sumado un poquito de mucho estudio y practica.
- Que exista cierta metodología o proceso, implica que hay personas a las que SI les funciono, pero no significa que a todos les funcionara. que exista RUP, SCRUM, etc. significa que hay personas a las que siguiendo los pasos que le fueron indicados, tuvieron éxito en lo que buscaban, pero esto a su vez no implica que a todos les ira bien, posibles factores son muchos –
- Las Metodologías, técnicas, etc., no son Leyes : aunque suene feo, si obviamos usar determinada metodología “así tal cual viene en la caja”, si evitamos usar rup, scrum, etc etc etc.. esto no implica que nuestro software tenga muchos errores, o no sea optimo, las metodologías solo son una guía en la cual nos podemos basar para intentar tener un buen resultado con un mínimo costo / tiempo, OJO no estoy impulsando a no usarlas, solo quiero aclarar que no es un pecado capital “el no usarlas”, lógicamente que es como el juego de la ruleta rusa, nos puede ir bien o nos puede ir mal, personalmente no soy de los que usa algo “tal cual viene en la caja” sino que lo personalizo hasta poder sacar el máximo rendimiento.
- Un Programador no piensa igual que alguien involucrado a fondo en el área de pruebas – a menos que tenga extrema experiencia en el tema- : en este punto e tenido algunas discusiones – muy placenteras – con algunos colegas; tengo algunos años – no muchos si los comparo con algunos de los maestros que rondan por aquí en geeks.ms – e trabajado junto a desarrolladores de al menos 2 países ( Perú y México) y con mas de 6 años de experiencia en pruebas, y e podido constatar – eso sin tomar en cuenta a lo que ya dicen muchos respecto al tema –, que la forma de pensar de un programador “promedio” – ojo con la premisa 1 – su forma de ver las cosas es como “construir” algo, su mente este abocada a armar software y es muy difícil – por no decir casi imposible – en pensar a fondo en pruebas, lógicamente se le ocurrirá una que otra, de cosas simples o básicas, pero no de las que son a profundidad; a diferencia de alguien involucrado en pruebas – y no me refiero a los pica botones – en el cual su mente esta abocada a “Destruir” y pensar en como destrozar algo que otro realizo, se que muchos me dirán que no es cierto, pero e realizado la prueba con muchos programadores -soy del tipo que le gusta hacer experimentos son la gente- y los resultados fueron muy claros. Lógicamente hay personas con algo de experiencia – y que no tienen perdida de memoria – y con el transcurrir el tiempo van pensando en pruebas cada vez mas complejas, lamentablemente este ultimo grupo es muy reducido. – no me extiendo mas, sino me auto robo el tema del siguiente post, que espero sacarlo ahora si –
- Una prueba unitaria básicamente es: probar que metiendo A datos a X función me devuelva Y; pero esto no implica que si meto B me devolverá Z: el titulo habla por si solo, me extenderé en esto mas adelante.
- Basarse “solamente” en una forma de medir el software puede ser tu perdición : aquí es simple, el usar “solo X” puede ser la causa que un proyecto se venga abajo, ya que en el software interviene el factor humano, el cual es capaz de romper cualquier regla, en otras palabras, el hombre esta aplica principio de incertidumbre de Heisenberg, y por lo mismo quizá una forma única de ver las cosas nos diría que estamos en lo correcto, mientras que otra medida nos diría que no. ( al hablar de medidas me refiero a pruebas )
Veamos ahora algunos puntos acerca de TDD – por comodidad me fusilare los pasos descritos en wikipedia –
- Escribir El Requerimiento.
- Esto es algo que se repite en cualquier metodología/ y forma de trabajar, el error en este punto varia directamente proporcional al que recoge los requerimientos… aunque de aquí depende mucho el avance del proyecto, sobre que tantos y que tan buenos fueron los requerimientos recogidos –aquí hay material para extenderse otro post –
- Escribir las Pruebas.
- Bueno:
- El fin aquí es escribir el menor código “funcional” – de la app – al hacer que el programador se dedique a generar código que pase las pruebas, estas pruebas están basadas en los requerimientos establecidos, aquí el nivel de efectividad depende de la calidad de requerimientos.
- El echo de escribir la prueba antes que la funcionalidad, nos abre un poco mas la vista sobre que es lo que realmente necesita la aplicación de acuerdo a determinado requerimiento – ya que hay casos en que el error es que simplemente no se entendió bien el requerimiento –.
- Cuando hay cambios en la aplicación, se puede correr las pruebas y verificar que la aplicación “aun” supere las pruebas.
- Las Pruebas unitarias no son el chupa cabras : algo que es absoluto es que Si o SI se tienen que hacer pruebas a la aplicación, ya sea antes o después – como puso Rodrigo en este post , aunque para algunos, escribirlas después hace que ya NO sea TDD-; personalmente las prefiero después.
- Muchos de los beneficios los integro Ibon Landa en varios links de este post, que seria bueno que lo vean.
- Malo:
- El Echo de que TDD pida que se hagan las pruebas antes, implica que el programador hace tareas de el encargado de pruebas : algo que se puede subsanar dando las pruebas para que lo realice una tercera persona, o se realicen luego de escrita la funcionalidad, lo cual podría traer líos con los puristas de TDD
- Algunas veces para intentar cubrir todo, se crean requerimientos redundantes, que traen a su vez pruebas redundantes, lo que implica una perdida de tiempo que se puede entender por perdida de $$.
- En Algunos casos las pruebas terminan siendo mas complejas que la funcionalidad en si, haciendo que mas que una ayuda, sea un lastre para el proyecto – ojo que no es en todos los casos-
- Muchas personas – no aplica en todos los casos – consideran que es una perdida de tiempo escribir las pruebas antes que el código, esto también depende de la pericia del programador y a como este acostumbrado a trabajar, personalmente no soy “fan” de escribir las pruebas antes, aunque si me gusta desde la etapa de requerimientos, definir las pruebas que debería pasar la aplicación.
- que tenga 3000 ( o mas ) pruebas unitarias, no implica que este tomando en cuenta la totalidad de “posibilidades”, ya que una cuestión es probar valores puntuales en funcionalidad puntual y otra muy diferente tomar valores y estados en conjunto, ya que por ejemplo tomando un universo de 10 variables, estas 10 independientemente pueden funcionar a la perfección, pero en conjunto, en determinada situación pueden causar un error, que quizá no será un error de aplicación, sino un error de lógica y a su vez obtener valores erróneos,
- Trabajar con demasiadas pruebas puede hacer que uno caiga en la desesperación como en este caso , que por cierto tiene gran parte de razón, ya que las pruebas se pueden extender infinitamente, y un proyecto que pudo desarrollarse en 3 meses podría extenderse 2 años por el puro echo de ir programando pruebas, a la hora de hacer las pruebas, hay que saber en que punto detenerse.
- Algunas personas llegan a creer que por el echo de que la aplicación haya pasado las pruebas unitarias significa que ya esta lista para irse a producción: Lamentablemente aun hay personas y empresas, que toman a menos a los encargados de pruebas, quizá por que en muchos casos se contrata a personas sin – o muy bajos – conocimientos técnicos y esto hace que los programadores y jefes de proyectos tomen a menos a los del área de pruebas. – aunque si hay casos en el que el razonamiento es justificado –; esto sumado al ego – si, ya se, estoy desvariando, los programadores no tenemos el ego grande, ni tenemos complejo de todopoderosos, son alucinaciones mías –, han llegado al punto de hacer que en ciertos casos los programadores minimicen o ignoren errores reportados – me consta- , los cuales luego tronaron – fallaron – en producción y trajeron muchos dolores de cabeza, este tipo de problema es algo complejo de resolver, por que escapa a lo “profesional” y se va a lo personal. algo que si es definitivo es que a pesar de todas las pruebas unitarias que le hagamos, aun la aplicación debe de pasar por un proceso de pruebas, algo mas especializadas y quizá no automatizadas.
- Las pruebas Automatizadas no aseguran que la aplicación este libre al 100% de errores : ya que muchos de los causantes de sitios web hackeados, son por vulnerabilidades que las pruebas automatizadas no detectaron, sino miren el ejemplo de MS y que le paso por confiar en sus pruebas automatizadas , por eso es casi de ley hacer pruebas de esas que son basadas en el “ojímetro” – espero poder dar ejemplo prácticos sobre esto en un futuro no muy lejano –
- Verificar que la prueba falla:
- Aquí verificaremos que el error se presente… el problema es que pudimos habernos pasado unos 30 minutos o 1 hora escribiendo cierta prueba, que a las finales no falla, y no necesariamente por que la prueba este mal, lo que implicaría de nuevo una perdida de tiempo, aunque a su vez nos podría confirmar que X funcionalidad trabaja correctamente.
- Escribir la implementación:
- aquí escribimos la funcionalidad de la aplicación, la cual deberá integrar las validaciones necesarias para poder superar la o las pruebas, en teoría – si estuviéramos en con Alicia en el país de las maravillas – la aplicación debería de funcionar sin problemas, la codificación de la aplicación debería de ser mínima, lamentablemente es algo que no pasa muy seguido a menos que el programador ya tenga una amplia experiencia, lo cual nos saca del foco del “programador promedio”.
- Ejecutar las pruebas automatizadas:
- Aquí la aplicación debería de pasar todas las pruebas, pueda darse que la aplicación pase las pruebas a la primera corrida, pero esto no implica que este libre de errores, solo indica que puntualmente la aplicación esta respondiendo con determinados datos, pero no a todos
- Eliminación de duplicación: aquí vamos refactorizando, algo útil, que a su vez es una inversión, este proceso no es malo, siempre y cuando se haga mesuradamente, ya que existen personas que se trauman demasiado con la optimización – si, ya se, estarán pensando “perro hablando de pulgas” – y hacen que se pierda demasiado tiempo en esto.
- Actualización de la lista de requerimientos: como el nombre lo dice, reordenamos los requerimientos y si es posible a repetir el proceso!.
Mi Experiencia Personal: no es exactamente TDD, pero usaron el modelo de pruebas.
Creo que ya lo conté en algún post…, no me canso de ponerlo, por el impacto del proyecto – de algunos millones de pesos – , erase un soft, al cual se le hizo un listado de requerimientos, y fue construido tal cual los requerimientos, el soft había pasado las pruebas planteadas en los requerimientos; si uno usaba el soft tal cual indicaba el manual – las funciones puntuales trabajaban a la perfección – la aplicación funcionaba súper bien, el problema era cuando alguien daba un clic de mas, o presionaba en otro botón, o hacia cualquier acción no contemplada en el proceso del manual de usuario; en ese momento la aplicación tronaba, fallaba,hacia BOOM…, no participe en la construcción de ese proyecto, aunque si en la destrucción – viendo como tronaba igual al pop corn- cual fue su error? basarse “exclusivamente” en las pruebas echas en base a los requerimientos, y no ir “mas allá” error en el cual algunos caen por que se confían demasiado en “las pruebas unitarias”, lógicamente esto también depende con que se cuente con un área de pruebas, ya que existen empresas en las cuales el programador tiene que hacerlas de tester, y eso puede volverse un gran problema.
Mi Opinión y conclusiones :
El echo de que TDD exista, es por que hay personas a las cuales les funciono, pero antes que nada tenemos que tomar en cuenta el tipo de personas que lo usan, ya que de acuerdo al nivel de las personas, es que podemos hacer determinadas cosas, por ejemplo yo no podría hacer algo al mismo ritmo de alguno de los Scott – que salen por todos lados – , o un recién egresado a mi ritmo, por lo mismo no todas las metodologías funcionarían con todas las personas – por mas que la teoría diga que si se puede.
Escribir las pruebas antes que la aplicación, en la mayoría de casos – por no decir casi todos-, involucra que el programador realice funciones que no le corresponde, por eso mismo, personalmente prefiero las pruebas luego que el código de la aplicación y mas aun, prefiero que el que escriba las pruebas sea uno encargado de pruebas, así el programador se enfoca básicamente a programar la aplicación, aunque podría ir escribiéndose las pruebas y la aplicación en paralelo, esto depende de si se cuenta con personal capacitado para esto – si el de pruebas sabe programar pruebas, o solo es un pica botones –
Por que no estoy muy conforme con TDD?
como ya lo puse, así como el modelo lo muestra, – y como es implementado normalmente- el programador tiene que hacer las pruebas y la aplicación, lo que implica doble trabajo y hacer tareas que deberían tocarle a otras personas; estoy totalmente de acuerdo en que se deben de hacer pruebas, pero a mi parecer, lo debería de hacer alguien mas, y mas aun que esta persona debe de estar integrada al equipo desde la etapa de diseño – esto es del siguiente post – . Lógicamente existen en nuestro medio personas excepcionales, que programan a una gran velocidad, y estas personas pueden programar pruebas y la funcionalidad aun en menos tiempo, de lo que un programador promedio podría hacerlo, si esta fuera la situación, que se da, en no todos los casos, pero se da, allí no tendría ningún problema con que el programador haga las pruebas que quiera; pero lamentablemente esto no pasa en todos los casos.
Jorge Gamba me dijo vía twitter que BDD es mejor que TDD… ya habrá tiempo para opinar sobre eso.
Para terminar creo que TDD no es del todo malo, siempre y cuando se apliquen pruebas exhaustivas aun luego de que estas pasen las pruebas unitarias o pruebas automatizadas, confiar “solo” en estas pruebas unitarias, seria un grave error – se que Jersson dirá de que en TDD tbm se hacen pruebas – , el problema que hay es cuando personas con poca experiencia en el desarrollo de software usan esta metodología, es muy fácil que sientan que con las pruebas unitarias, ya tienen todo a la perfección y alli empiezan los problemas.
por si alguien quiere saber las mensadas que suelo poner – y que no llego a poner aquí por lo corto de las ideas, pueden encontrarme en el twt http://twitter.com/ddaz – y lo de las mensadas es muy en serio eh xD –, se que dicen que el twt no es un chat, pero hay ideas que hay que replicar en caliente, sino se va la inspiración.
espero sus opiniones y retroalimentación al respecto, no olviden que es mi apreciación personal :), quizá se me paso escribir algunas cosas que en este momento no se me vienen a la mente… pero de todas maneras este paso a ser otro “Testamento de Dacito”, veamos cuantos llegan a leer hasta este punto.
y como lo prometi…. lo publique antes de irme a dormir… siendo las 3:36 am.. fugo para dormir…
Salu2
Ddaz – El Dacito –