lunes, 27 de diciembre de 2010

Editorial de fin del año del 2010 - De vuelta a las bases

Henos aquí al final del año 2010. Primer fin de año de este blog que esperamos que sea el primero de muchos.

La verdad, en estos casi 9 meses de vida (chiste obvio al margen) nos hemos dado algunos gustos. Como dicen por ahi, justamente los gustos hay que darselos en vida y así lo hicimos.

Recuerdo cuando era chico miraba series de televisión (y aquí voy a delatar nuestra edad, ey, tengan en cuenta que la mitad de nosotros somos treintañeros todavia!! mas respeto!) como los angeles de charlie, los dukes de hazzard, BJ (la del camionero con el mono), el Sheriff Lobo (imperdible), el hombre de la Atlantida (ju juuu por DioS!), buck roger o el auto fantástico. Cuando terminaba la temporada de estas series era habitual que el ultimo capitulo fuera en realidad una selección de las mejores partes de los capítulos que se habían emitido este año. Va aquí nuestro homenaje a esta práctica, como modo de resumen del año 2010.

Hemos repasado algunos principios básicos de objetos en la-ley-de-demetrio-y-otras-yerbas-oo y en poo-ejemplos-de-la-ley-de-demeter. No quiero olvidarme tampoco de la seria sobre patrones de tests de unidad: patterns-de-tests-de-unidad-1-como-deberian-ser-los-tests-de-unidad, patrones-de-test-de-unidad-2-humble-objects o como-lograr-tests-de-unidad-rapidos.

Estos principios y patrones parecen bastante obvios y trillados(bah, así nos parecían) pero charlando con mi amigo y co-autor de Blog nos hemos dado cuenta que en estos tiempos muchas veces debido a la falta de recursos para programación o porque hay otros temas mas "fashions", lo cierto es que muchos programadores nuevos no conocen ni a estos ni a los principios más básicos de la Programación Orientada a Objetos.

Hemos recién empezado a charlar sobre un tema muy interesante, importante como buena practica pero bastante extenso como son los Code Smells en code-smells, desgranando algunos en detalle como: desconfien-de-los-parametros-booleanos, o obsesion-primitiva y comentarios

Emprendimos una batalla, desigual desde ya, tratando de aclarar cuestiones muchas veces malentendidas o mal interpretadas de las metódologías ágiles, como en con-scrum-no-alcanza o estas-realmente-haciendo-desarrollo-Agil y dos en particular que me gustaron mucho, por la repercusión que tuvieron y porque fueron generadas con discusión dentro de la comunidad ágil iberoamericana: metaforas-del-desarrollo-de-software-i y metaforas-del-desarrollo-de-software-ii. Para terminar con el articulo fundamental de como encarar el aprendizaje de cualquier nuevo conocimiento y en particular de una metodología ágil : el-camino-del-conocimiento-de-aprendiz-a-maestro.

Como niños buenos e hijos de la generación "La inmaginacion al poder", hemos discutido como debe ser un buen líder y otras cuestiones de liderazgo en liderazgo-i y liderazgo-ii. Pero por otra parte, cuestionando nuestra conciencia, nos hemos encargado de recordar las obligaciones que tenemos como verdaderos profesionales de formarnos constantemente: cuantos-libros-tecnicos-leiste-este-año, y trabajar sobre lo que tienen importancia como en mantenibilidad-vs-reusabilidad, por-que-funciona-pair-programming y nos hemos auto-retado cuando perdemos el tiempo como en larga-el-twitte o productividad-la-espartana.

Para finalizar queremos resaltar dos articulos en particular, ambos han tenido mucha difusión, y creemos saber, al menos parte de, la causa: El primero es flexibilidad-ante-el-cambio que habla sobre porque hay que estar preparados para el cambio en todo proyecto de desarrollo, sobre como descubren lo que quieren los usuarios y como el cambio es esencialmente imparable porque es sencillamente parte de la realidad. Y el otro es pasos-de-bebe-el-fin-del-debugging, una de las herramientas menos utilizadas, difundidas y comprendidas de la programación pero que nosotros le asignamos una importancia capital para enfrentar el caos de la complejidad que impone El Cambio sobre el desarrollo de software, junto, claro está con las prácticas de TDD y pair programming.

Para cerrar el balance , además de los artículos, este año organizamos dos Code Retreats, que nos permitieron compartir tiempo con otros locos (perdón, quiero decir: con otros entusiastas de estos temas) capaces de juntarse un sábado a las ocho de la mañana a programar de a pares, resolver problemas y razonar sobre como mejorar nuestro arte.

Bueno, eso es todo. Lo que hemos tratado humildemente de hacer este primer año desde este espacio es describir y promover conceptos, libros, técnicas y herramientas que consideramos poco habituales dentro del ámbito de la programación.

Creemos que la terrible presión de la ola de información junto con la inundación de nuevos lenguajes, herramientas y frameworks impone tal ritmo al programador profesional que arrasa con cuestiones de base y produce que todo se confunda en un lodazal de conocimientos superficiales y la Ultima-bala-de-plata-que-viene-a-solucionar-todos-tus-problemas.

Lo que se necesita en realidad es adquirir buenos hábitos, aplicar Buenas Practicas de desarrollo y volver a las bases.

Por eso brindamos. Salud!.





La foto del brindis es propiedad de larrazun. Algunos derechos reservados.

jueves, 16 de diciembre de 2010

Productividad a la espartana

En mi primer trabajo tuve muchísimo tiempo libre. Al principio por estar en la típica situación del junior al que nadie le da bola y después porque dejaron de pagar los sueldos y se decretó una especie de "huelga virtual" : íbamos a la oficina pero no hacíamos nada.

Así que me pasaba 8 horas al día delante de mi terminal Unix (era una espectacular SUN workstation, con monitor de 25 pulgadas, nada mal eh), sin nada para hacer. De puro aburrido, me puse a mirar scripts, a probar comandos, distintos shells, a leer páginas del man y, para cuando se terminó de ir la empresa al tacho, había aprendido bastantes cosas nuevas.

¿Qué pasaría si estuviera en la misma situación ahora? Creo que aún con lo que me gusta mi trabajo no le dedicaría la misma cantidad de tiempo a aprender que en esa época y el principal motivo de esto es que actualmente hay muchas más distracciones disponibles que en mis viejas terminales VT100.

De hecho, hace un tiempo que me venía molestando el tiempo que le estaba dedicando a algunos sitios web, tiempo que sin ser para nada excesivo me parecía que podia dedicar a otras actividades (no necesariamente trabajo: leer un libro, escribir artículos para este blog, etc.). Por lo tanto, decidí implementar una idea que había encontrado varias veces: bloquear esos sitios.

La solución técnica es sencilla: hay que tomar el archivo hosts (qué en Linux se encuentra en /etc y en Windows en \WINDOWS\system32\drivers\etc ) y agregarle líneas del estilo:

0.0.0.0 ole.com www.ole.com www.ole.com.ar

De esta manera, el sitio quedará bloqueado y no podremos acceder más. Por supuesto que así como bloqueamos el sitio podemos desbloquearlo, pero lo importante es que esto exige una acción de nuestra parte y por lo tanto una decisión consciente: ¿quiero ir a leer que dice Carusso Lombardi o prefiero hacer otra cosa?

Adicionalmente, podemos redireccionar los sitios a una lista de cosas para hace, como para que las alternativas a Carusso sean mas claras.

Una cosa más: creo que esto es una excelente idea cuando podemos tomar por nosotros mismos la decisión de hacerlo o no. En cambio, si como jefes bloqueamos el acceso de nuestra gente a cargo estamos dando un mensaje de desconfianza total y además incentivando la búsqueda de maneras de burlar nuestros controles (recuerdo haber escrito un script Perl que cambiaba 12 veces mi password, para burlar una directiva de seguridad que me prohibía reutilizar las últimas 12 passwords, otra vez instalamos servidores proxies para salir a internet sin ser detectados y muchas otras mas que no podemos comentar porque todavía no prescribieron).

Por ultimo, quizás podemos parecer pesados de tanto insistir en administrar de una manera mas productiva nuestros tiempos, o dicho de otra manera de cuanto insistimos en dejar de pavear y perder el tiempo. Bueno, si, es verdad, lo somos.

El problema es que muchas veces nos encontramos diciendo "No tengo tiempo", "No me alcanza el tiempo", "Estoy hasta las manos y no me queda tiempo", cuando en realidad siempre tenemos la misma cantidad: Cada día tenemos 24 horas. El modo en que decidamos como utilizarlo, ahí esta la diferencia.

miércoles, 8 de diciembre de 2010

Saros, Programación de a Pares Distribuida?

Whole Team

Todos sabemos que la forma de comunicación más efectiva que existe es la cara a cara, en un mismo lugar físico, adonde cada uno de los participantes de la comunicación pueda ver las expresiones del otro, sus gestos, y hasta la postura del cuerpo, ademas de escuchar su voz y percibir los cambios de tono.

Por eso una de las practicas centrales que proponía para un equipo de desarrollo eXtreme Programming era Whole Team, todo el equipo, incluyendo usuarios, debían trabajar juntos en un mismo lugar, para que la información fluyera , sin barreras.

En mil y una oportunidades los autores de este blog hemos comprobado cuan cierto es esto.

Outsourcing

Sin embargo, somos realistas, y lo que ha sucedido desde hace varios años es que el modelo económico mundial Globalizado basado en la premisa de buscar fuerza de programación, de análisis, testing o Diseño allí donde sea más barato hace que cada vez sean mas comunes encontrar proyectos distribuidos. Viviendo en paises como Argentina, Chile, Bolivia, Uruguay, Perú, Colombia, Ecuador, Venezuela, Mexico o el mismo Brasil (la unica duda que tengo es España y perdón si me olvido de algún otro País), adonde se recibe cada vez mas proyectos "tercerizados", todos sabemos de lo que hablamos.
De cualquier manera, bienvenido sea el trabajo, ademas porque brinda una gran oportunidad para mostrar la clase de profesionales de primera que tenemos en toda hispanoamerica!.
Las mismas metodologías ágiles lo han terminado aceptando (en algunos casos) y asi existen rios de e-tinta sobre Scrum Distribuido para nombrar una.

Nuevos remedios

Hay una frase de Francis Bacon que es una de mis frases favoritas : "Aquel que no aplica nuevos remedios debe esperar viejos males".

Uno de los problemas más importante ha resolver tiene que ver cuando el equipo de programación esta distribuido. Para ello, para desarrollar sistemas con programadores trabajando en distintos lugares se necesitan nuevas herramientas.

Los que escribimos este blog alguna vez hemos intentado trabajar con herramientas de escritorios compartidos como VNC, TeamViewer, LogMeIn, etc. pero la tasa de refresco de pantalla, la modalidad misma de ver toda la maquina del compañero, no poder hablar al mismo tiempo, todo esto hace difícil el trabajo compartido prolongado y en tiempo real.

Saros

A este respecto hace muy poco nos encontramos con este articulo de Kent Beck que atrajo nuestra atención:
"A Few tips for using Saros for Remote Pairing"

Saros es un plugin de eclipse que permite hacer Pair Programming, programación de a pares distribuida! Prometedor verdad?

Aqui tienen el sitio del proyecto Saros.

Tambien puede ver un video de como se trabaja con Saros.

Tips de Instalacion

Les dejo por ultimo unos tips de instalación, porque hay ciertas cosas que solo funcionan por ahora siguiendo por el caminito de piedras...

1 - El proyecto que compartan lo deben tener ambos desarrolladores ya bajados del repositorio de fuentes o tener muy pocos cambios de diferencia. Lo mejor es empezar con un proyecto nuevo, limpio.

2 - Todos los que vayan a formar parte del pair programming tienen que tener cuentas en el mismo servidor Jabber.

3- La única manera que logre hacerlo funcionar detrás de un entorno VPN con firewall (que impedia acceder a un server Jabber externo) fue primero instalando un servidor de Jabber local en una maquina de la misma LAN, por ejemplo el servidor OpenFire 3.6.4.

4- En las pruebas que hice no funcionó creando las cuentas Jabber por afuera de eclipse. Solo anduvo cuando las creamos desde el menú que instala el plugin en eclipse "Saros\create account", ahí recién el plugin reconocio las cuentas, permitio conectarse y pudimos compartir proyectos.

El plugin esta en un estado de desarrollo beta, pero avanzando a grandes pasos. Al respecto Dice Kent Beck: "...en 15 o 20 años la mayoría de los programas serán escritos a través de colaboración en tiempo real distribuida, así que vale la pena un poquito de dolor ahora para experimentar el futuro."

miércoles, 1 de diciembre de 2010

Sherlock Holmes

"Una vez descartado lo imposible, lo que queda, por improbable que parezca, debe ser la verdad"

Esta frase fue escrita por Arthur Conan Doyle para su personaje Sherlock Holmes y resume el mecanismo de las investigaciones en la mayoría de las novelas policiales: ir descartando posibles explicaciones hasta llegar a la única posible.
Lo difícil, tanto en los casos de Sherlock como en la vida real, es poder descartar N-1 explicaciones, porque N es grande y porque descartar cada explicación no es fácil (creo que no lo podría haber dicho de una manera más nerd o geek, como se dice ahora).

Pero nosotros no necesitamos resolver cosas en la vida real. Sólo necesitamos que nuestros programas anden y existen factores que hacen viable comportarnos como si fuéramos Sherlock Holmes (o el Dr. House, para un ejemplo más moderno).

En primer lugar, las computadoras son determinísticas. Esto significa que si una computadora recibe dos veces exactamente el mismo input el resultado que va a producir va a ser exactamente el mismo. Esta idea no se condice con nuestra experiencia de todos los días (sobre todo si somos usuarios de ciertos sistemas operativos), pero no deja de ser una verdad absoluta, por lo menos para computadoras de nuestra época que no planeen tomar el mundo.

¿Cual es la consecuencia para nuestro método Sherlockiano? Que podemos descartar todas las hipótesis que sean del estilo "no cambié nada y dejo de andar". Si dejó de andar, es por un motivo; quizás nunca podamos descubrirlo; quizás lo haya hecho otra persona, pero existió un motivo (siempre quise poner un punto y coma escribiendo en castellano, es raro porque odio hacerlo cuando programo).

Este es un punto muy importante, porque nos permite liberar nuestro cerebro de mucho trabajo inútil. Si algo deja de funcionar, solo necesitamos ver que cosas cambiaron desde la última vez que anduvo y podemos estar seguros que alguno de esos cambios va a ser el culpable. Teniendo pocos sospechosos, siempre es más fácil descubrir al criminal.

Es aquí donde, además de las características inherentes de nuestro medio, entran en juego hábitos que permiten mantener la lista de sospechosos corta. En el párrafo anterior hay una frase tramposa: solo necesitamos ver que cosas cambiaron desde la última vez que anduvo. Parece sencillo, pero para saber esto se necesita poder determinar primero cual fue la última vez que nuestro programa anduvo y segundo que cosas cambiaron desde entonces.

¿Cómo podemos ser capaces de saber cuándo fue la última vez que nuestro programa funcionó? Si se trata de un problema que aparece en nuestro ambiente de desarrollo, las técnicas que mencionamos aquí son muy eficientes. Si dejamos pasar poco tiempo entre pruebas, es facil saber cuando fue que nos equivocamos. Los tests de unidad en estilo TDD son particularmente eficaces: si corremos los tests cada 10 minutos, un test fallado debe tener un sospechoso bastante obvio.

Si se trata de un problema que apareció en producción o en testing la cosa es más complicada. Hay que recrear los ambientes anteriores para poder verificar en que momento apareció el bug, lo cual a veces es difícil y consume mucho tiempo. Pero nada de esto es nuevo, siempre supimos que dejar llegar bugs a producción es muy caro.

La otra mitad del problema es determinar que cambió para que nuestro programa dejara de andar y aquí entra en acción un hábito muy querido por los autores de este blog: los commits frecuentes. Digamos que logramos determinar que el programa dejó de andar la noche del 24 de julio a las 3AM y que podemos considerar todos los cambios ocurridos cerca de ese momento como sospechosos. Si un programador estuvo modificando código sin commitear durante un mes e hizo commit a las 2AM, todos esos cientos de cambios son igualmente sospechosos. En cambio, si trabajamos de manera de poder commitear todos los días, el conjunto de sospechosos (la cantidad del codigo commiteado) es mucho más corto.

La misma solución se puede aplicar para los problemas en Producción, si no para evitarlos por lo menos para minimizarlos, aplicando las práctica de Integración Contínua y Entregas Frecuentes. La idea es la misma: No esperar a tener mil cambios en la aplicación para pasarla a productivo porque eso implica que cualquier error tiene miles de "sospechosos". Mientras que si uno hace mini-implementaciones y entrega frecuentemente, cada bug tendrá unos pocos "posibles" sospechosos.

Por supuesto, hay variaciones de estos problemas en equipos de trabajos grandes, con gente que modifica a la vez las mismas partes del programa, pero la regla general se mantiene: si algo dejo de andar fue por algún cambio y cuando más fácilmente puedas determinar ese cambio tu vida va a ser más fácil.

Elemental Watson!, Diria Sherlock Holmes (Claro que esa frase no la dice en ninguno de los cuentos o novelas que escribió Arthur Conan Doyle, "Urban Legend" que le dicen).

martes, 23 de noviembre de 2010

Code Smell: Comentarios

El valor de los comentarios es una de las guerras religiosas más antiguas de la programación. Por eso, cuando en una charla o un artículo se menciona a los comentarios como un Code Smell (y nada menos que uno de los citados en la lista original de smells) se suele armar una linda discusión.

¿Cómo puede ser que algo que nos vienen inculcando desde que empezamos a programar sea negativo? ¿Puede ser que todas esas veces que nos negamos a comentar nuestro código teníamos razón? Bueno, para ser exactos lo que dicen Fowler y Beck no es que los comentarios sean un smell en si mismos si no que se utilizan para disimular smells. Es decir, tenemos código que no es tan bueno como debería y en vez de mejorarlo lo comentamos. Como dice Bob Martín en su libro Clean Code, cuando usamos comentarios lo que estamos haciendo es admitir que fallamos en producir código lo suficientemente claro como para no necesitarlos.

Veamos algunos ejemplos de comentarios que se utilizan normalmente y como hacerlos innecesarios y eliminarlos hace mejor nuestro código

1. Comentario obvio
 class Route {
  int id; //the id of this route
 }

¿Y que otra cosa va a ser el field id de una clase Route? Sin embargo, este tipo de comentarios son muy comunes, normalmente porque algún standard corporativo exige que todos los campos tengan un comentario descriptivo.

Hay casos más estúpidos todavía (y juro que he visto esto en la realidad):

 i++; //Increments i

2. Comentario reemplazable por código

 const int MAX_QUEUE = 5; //Max number of queue per process

Aquí el comentario tiene más información que el código, pero sería mucho mejor escribirlo directamente así:

 const int MAX_QUEUE_PER_PROCESS = 5;

Consiguiendo de esta manera documentar no solo la declaración si no el uso de la constante. Otro ejemplo:

 //verify if the request is a cancelation
 if(request.equals(Constants.CANCEL_SMS_JOB) ||
  request.equals(Constants.CANCEL_MMS_JOB) ||
  request.equals(Constants.CANCEL_WAPPUSH_JOB)) {
  //Some code
 }

Lo cual sería mucho más claro si se escribiera asi

 if(request.isACancelation()) {
  //Some code
 }


 boolean isACancelation() {
  return equals(Constants.CANCEL_SMS_JOB) ||
    equals(Constants.CANCEL_MMS_JOB) ||
    equals(Constants.CANCEL_WAPPUSH_JOB);
 }

Además de ser más claro, esta alternativa brinda la posibilidad de reutilizar la lógica en caso de ser necesario.

3. Comentarios históricos
 //2010-09-01 George Creation
 //2010-09-03 John   Add edit funcionality

¿Cuál es el problema? ¿Tu SCM ya no funciona?

4. Trackeo de posición en el codigo
 while(condition1) {
  if(condition2) {
  } else { // end if condition2
  // ...
  // lots and lots of pre...
  // ...
  } //end else conditionN
 } //end while condition1

Este tipo de comentarios parecen totalmente lógicos y de hecho ayudan a guiarse en código complicado. Sin embargo, no son una solución y están enmascarando un problema más grave: el código es demasiado complejo y el método es innecesariamente largo. La verdadera solución al problema de fondo es partir el método en varios métodos cortos y no tener bajo ninguna circunstancia estructuras lógicas que no sean visibles en su totalidad en una pantalla.

Con estos ejemplos no queremos decir que todos los comentarios son inútiles. Pero en general son sospechosos y vale la pena tener siempre en mente la frase de Kent Beck: nunca comentes código de mala calidad, refactorizalo y hacelo excelente.

lunes, 15 de noviembre de 2010

Metaforas del Desarrollo de Software (II)

Introducción

Como hablábamos en (I) una correcta aplicación de metaforas ayuda a encontrar soluciones que se han aplicado con éxito dentro del contexto de la metáfora original, pero cuando la metáfora no aplica....entonces el daño es grande.

En el post anterior hemos revisado alguna de las metáforas que se aplicaron y se aplican al desarrollo de software y que han causado más daño que efectos benéficos. En este vamos a tratar de hacer un repaso por otros contextos e ideas que se ajustan mucho más a lo que realmente es la actividad del desarrollo de software.

Planteamos este tema al foro-agiles de la comunidad Hispano-Americana de metodologías ágiles, y las ideas que surgieron, y el ida y vuelta de metáforas fue de lo más interesante. Vamos a intentar aquí resumir el espíritu de la discusión.

Cuidado con las metáforas

@Carlos Pantelides plantea que no importa cual sea la metáfora se debe conocer del contexto en cuestión para aplicarla correctamente al desarrollo de software.

Un ejemplo, alguien puede afirmar que tal cosa es como una Orquesta Sinfónica. Ahora, esta afirmación sola, así presentada, es ambigua. Si uno no sabe como realmente trabaja una Orquesta Sinfónica quizás malinterprete la afirmación o la simplifique demasiado tomando elementos y soluciones erróneas en lugar de filtrar y aplicar las correctas.

Es claro que una metáfora se la puede utilizar solo como un medio de comunicación "liviano", para trasmitir una idea general, al hablar con un interlocutor que conozca poco del tema. Pero por el otro lado, una persona que realmente conozca del Dominio de la metáfora en cuestión puede estudiarla, analizar las buenas prácticas que dieron buenos resultados en el Dominio original y tratar de ponerlas en práctica en el nuevo dominio.

Decía yo en la discusión:

"Mi idea es que alguien con conocimiento o estudio de la metafora, supongamos por ejemplo Fernando Claverino, analice el dominio en cuestion, , escalar montañas y proponga ideas o soluciones a "extraploar" para aplicar al desarrollo de software. Si despues esas ideas no terminan siendo utiles, practicables o buenas, simplemente se las descarta o no cuajaran dentro de la cultura. Pero no digo que cualquier ñato sin saber escalar, como por ejemplo yo (y sin estudiar del tema), vaya a tirar soluciones a partir de un conocimiento superficial de la metafora , eso es peligroso.

Ahora, si viene Claverino, un grosso del Alpinismo, y me dice...che, mira existe en escalamiento esto llamado "Escalada de a dos", adonde uno hace de soporte del otro y ambos evaluan los riesgos y termina siendo mas rapido, porque ambos evaluan la dificultad de determinadas partes.... y aplican sus conocimientos cruzados. Y si uno es nuevo, lo entrena rapidamente, etc etc.... y me dice, porque no probamos esto en Desarrollo? Yo lo intentaria....

"

Nuevas Metáforas

Pero bueno, vayamos entonces a las nuevas metáforas propuestas como similitud del desarrollo de software por la comunidad ágile (de hispanoamerica=):

  • Grupo de Jazz, Orquesta, grupo de música (Adrian Lasso) : Es similar en el sentido de que igual que en el desarrollo de software, la producción de un grupo de jazz depende de la calidad de los participantes, y el grupo debe tener una fuerte dedicación a practicar. Hay obras más simples y más complejas, igual que hay sistemas más simples y complejos, y el resultado de ejecutarlas depende de la experiencia y calidad del Grupo. Igual que con el desarrollo de software, para hacer un sistema simple no se necesita un equipo muy experimentado con gente de calidad, pero a medida que el sistema se vuelve más complejo, es esencial.
  • Como una obra de teatro (Artful Making, Juan Gabardini) , pueden ver el análisis de esta metáfora y la información de la charla sobre Artful Making de Lee Devin en el blog de Juan http://softwareagil.blogspot.com/2009/07/artful-making.html . Básicamente la idea es que en ambos dominios, a diferencia de por ejemplo la construcción de puentes, el costo de iteración es relativamente bajo, por eso es conveniente iterar (dado el beneficio inmenso del feedback inmediato, la mejorar continua, etc). Agregaba Diego Fontedevila : "El costo de iteración es el costo de reconfiguración (cambiar lo que teníamos) más el costo de exploración (descartar lo que probamos que no sirve). Si ese costo es bajo, vale la pena hacer como decíamos, es decir, hacer software con las manos."
  • Como el trabajo de un artesano (Jose Manuel Beas, software craftsmanship) En el sentido de que la gente que trabaja en Desarrollo se preocupa por la calidad de su producto, práctica y refina sus habilidades y va dando forma a su "obra" de a poco, cuidando el resultado. En definitiva, la calidad de lo "hecho a mano" en contraposición a la producción en cadena. A mi juicio es muy valida porque justamente en desarrollo de software cada sistema que hacemos es totalmente distintos al sistema anterior, como las obras de un artesano, de un artista, no hay dos iguales.
  • El software en si como Urbanismo (es decir, no el proceso de desarrollo sino el software mismo visto como el proceso de desarrollo Urbano, cambiante, reconfigurable, de una ciudad), de Carlos Pantelides.
  • Como la grabación de una película (Federico Freund): Tenemos un período donde se hacen las tomas hasta que quedan bien (en forma iterativa e incremental como en el desarrollo de software), Tenemos actores (programadores) que pueden llegar a repetir las tomas que hicieron por errores que tuvieron o simplemente para perfeccionarlas (corrección de issues), Tenemos un director (que puede ser el lider de proyecto), Tenemos un area revisión de tomas (área de testing), El guionista (puede ser el cliente que define que es lo que desea para su producto), El productor (el owner?), Los que ven la película (los usuarios finales)"
  • Como escalar una montaña (mia y Fernando Claverino) : El equipo tiene un objetivo que es llegar a la cima (entregar el sistema), el lider, ademas de lider es un Guia (coach), aunque muchas veces hay tecnicos expertos que saben mas que el lider de la montaña/Tecnología en cuestión, los distintos caminos de alcanzar la cima son distintas formas de modelar la solucion... Si hay un programador o Analista top, con ego demasiados grandes, suelen ser contrarios a la productividad del equipo porque se cortan solos o quieren imponer su camino hacia la cima, y en la montaña...estar solo redunda en peligros para todos. Yendo a la metodología se pueden subir montañas con equipos "pesados", instalando campamentos intermedios, planificando detalladamente la subida, con equipos grandes, subiendo de a poco. O bien se pueden subir con un equipamiento "ligero" con equipos chicos, ágiles, la exposición es menor ya que todo se hace más rápido. Este último estilo es considerado más elegante y limpio, generalmente lo realizan alpinistas con mucha experiencia. Un tema que mencionó Fernando dentro de esta metáfora es la cordada de 2 personas, donde escala un viejo con mucha experiencia y un joven con mucho potencial. Hablamos en la lista que se parecía de alguna manera a Pair Programming.
  • Hubo otras que se discutieron menos, como ser Escribir una novela de manera cooperativa, metáforas con el arte, la definición de productos de negocios.

Para terminar los dejo con una frase de Juan Gabardini, el prefiere la palabra Analogía en lugar de metáforas, y decía.

Las analogías son resbalizas! Pueden darte ideas, pero esas ideas hay que validarlas!

Material Adicional para ver (Surgido de la thread de foro-agiles)

  1. Emilo gutter sugiere como material una charla de Alistair Cockburn en Agile-2009: http://www.infoq.com/presentations/cockburn-bury-not-praise-agile y un par de charlas de Joshua Kerievsky http://stickyminds.com/Media/Video/Detail.aspx?WebPage=169 y David Hussman de http://agiles2009.agiles.org/es/session.php?id=58 sobre una metáfora de grupo de Musica.
  2. Jose Manuel Beas, metafora de diseño de interiores de Joshua Kerievsky https://elearning.industriallogic.com/gh/submit?Action=PageAction&album=blog2009&path=blog2009/2010/remodeling&devLanguage=Java
  3. Blog de Juan sobre Artful Making: http://softwareagil.blogspot.com/2009/07/artful-making.html

lunes, 8 de noviembre de 2010

Metaforas del desarrollo de software (I)

Lo que el desarrollo de software NO es

El hecho de aplicar metáforas provenientes de una rama de la industria a otra ha sido , al menos durante el siglo XX, una manera común de buscar soluciones ante nuevos problemas que se han aplicado exitosamente dentro del contexto original adonde fueron ideadas. No obstante, estos paralelismos entrañan a veces ciertos riesgos cuando las metáforas son válidas solo de manera superficial o en algún aspecto o contexto en particular y al aplicarlos a la nueva rama producen daños que a veces se extienden por años y se vuelven parte de la cultura de la rama en cuestión.

Vamos a ver a continuación un par de metáforas que se han aplicado erroneamente al desarrollo de software con la (buena) intención de encontrar soluciones provenientes de otros contextos que sirvieran para mejorar la productividad, costo y calidad del desarrollo de sistemas pero que causaron (y causan) gran daño toda vez que se trata de metáforas fallidas, que no representan correctamente la actividad real que se debe llevar a cabo al desarrollar un sistema.

El desarrollo de software como una ingeniería

En el año 1968 Peter Naur propuso que tratemos al desarrollo de software como una Ingeniería. Es decir, se fijo que el desarrollo de software se ocupaba de proyectos, como si fuera un proyecto de ingeniería de construcción de puentes o represas, adonde había un producto final entregable, un cliente y un "Equipo" con ingenieros que se ocupaban de construir el producto. En consecuencia se busco aplicar los valores, principios y buenas practicas que se usaban con éxito en las Ingenierías existentes en ese momento (Civil, eléctrica, metal mecánica, etc.) al desarrollo de software. Fue apropiadamente bautizada como Ingeniería de Software

El impacto que esta metáfora tuvo en el desarrollo de software no es fácil de medir pero nadie puede acusarnos de exagerados si decimos que fue inmenso. Como prueba, hasta algunas carreras universitarias tomaron el nombre y comenzaron a llamar a los recibidos: Ingenieros de Software.

Cuales son los problemas que trajo aparejado el querer manejar al desarrollo de software como un proyecto de Ingeniería?

1- En los proyectos de ingeniería en general el producto final se encuentra claramente definido desde el principio del proyecto y es un objeto real, palpable. Se conocen sus características, sus prestaciones y los criterios de cumplimiento. Por ejemplo, un puente debe tener tales y tales características, se hará de tal material, con tal forma, los cálculos de estructura son estos, debe aguantar tanto peso, etc. y etc..

En contraposición el desarrollo de software se esta construyendo una abstracción completa, algo no palpable, que no existe ni existirá físicamente, a partir de requerimientos vagos y necesidades imprecisas de los usuarios, que se dan cuenta lo que no necesitan solo cuando lo ven funcionando. Los criterios de cumplimiento en general son desconocidos hasta que empieza a ser utilizado en producción.

2- En los proyectos de ingeniería la experiencia de un proyecto se traslada casi directamente al siguiente proyecto porque en definitiva se construye una y otra vez el mismo producto. Es decir, un equipo que se encargue de construir represas, una vez ha realizado la primera, en la segunda la experiencia adquirida es totalmente aplicable y las herramientas y subproductos utilizados son muy similares sino los mismos. En el desarrollo de software cada proyecto de un sistema es completamente distinto al anterior. Si bien parte de la experiencia a nivel técnico de un determinado lenguaje o plataforma es capitalizada en siguientes proyectos la experiencia misma del proyecto no lo es, ya que jamas se construyen dos veces el mismo sistema, como si se hacen n veces represas, puentes o plataformas petroleras.

3- Al estar trabajando con productos físicos, palpables, es relativamente sencillo construir modelos a escala o prototipos con propiedades similares al producto final y probarlos en condiciones que luego son extrapolables a las condiciones reales. Piensen sino en la construcción de un modelo de avión, que se puede hacer en escala, respetando las relaciones entre partes y los materiales. Las pruebas que se hagan luego sobre el prototipo son totalmente válidas sobre el producto final también.

En el desarrollo de software por otro lado ha habido innumerables intentos de proveer herramientas que permitan prototipar sistemas. Para no ser tajantes una enorme mayoría de estos intentos han terminado en un fracaso total. Es muy complejo armar un prototipo de un sistema funcionando de manera que el prototipo contenga todas las propiedades que tendrá el sistema final, porque hacerlo lleva taaanto tiempo como hacer el sistema real mismo. Por ello solo se han encontrado algunos pequeños logros limitados en la prototipación de interfaces de usuarios teniendo el cuidado de entender y hacer entender al usuario que no es real y la navegación de la ui no es la definitiva.

4 - La planificación en un proyecto de ingeniería es imprescindible y un diagrama de Gantt del proyecto provee una excelente herramienta para gestionar el proyecto de ingeniería porque, por un lado los entregables están definidos desde el principio del proyecto y rara vez cambian, las tareas a realizar son conocidas y el esfuerzo que llevan es estimable, y la tasa de avance es, por lo generar, fácil de determinar y se mantiene luego constante hasta finalizar el proyecto, salvo claro algunos imprevistos y cambios, que se minimizan con una adecuada Gestión de riesgos. El cambio en un proyecto de ingeniería no es común y se lo trata por lo tanto como un cambio de alcance de proyecto.

En el desarrollo de software, por otro lado una planificación up-front del proyecto es sólo una proyección ideal de la información al momento de armar el Gantt, los entregables están definidos pero no de una manera detallada , las tareas no son conocidas y estimarlas implica caer en el arte de la adivinación, y la tasa de avance por muy predecible que los gerentes quieran que sean siempre adolece del problema de pareto, es decir el 80% de un sistema se hace en un 20% del tiempo pero el 20% restante lleva el 80% (y muchas veces mucho mas) del resto del proyecto. Por si fuera poco el cambio en el desarrollo de software es algo común, es una parte esencial de desarrollo de un sistema, ya hemos hablado de esto en este post.

El desarrollo de software como una fábrica

Factory

El objetivo de La producción de una Fabrica es producir uno o unos pocos productos de forma repetitiva, hay relativamente muy poca innovación o resolucion de problemas en el proceso. Tiene un proceso conocido de antemano, inputs repetibles y outputs predefinidos. La especificación del producto a producir esta perfectamente definida de antemano. Los trabajadores de una fabrica realizan una y otra vez la misma tareas o un conjunto limitados de ellas, acotadas y sin necesidad de aplicar gran conocimiento, utilizando herramientas tradicionales o no pero probadas miles de veces en cadenas de producción. Son los trabajadores de la era de la revolución industrial.

Desarrollo de software

Construye un solo producto por primera y UNICA vez, lo cual implica un monton de innovación y resolución de problemas a la vez y nunca se construye otro igual (una copia digital alcanza). Muchas veces parte del desarrollo implica definir el proceso, las entradas son múltiples y variables y los outputs no se conocen con certeza hasta terminar el sistema. La especificación del producto a construir es imposible de hacerla de antemano. Los trabajadores del desarrollo de software, sean programadores, Analistas, Testers o especialistas en infraestructura, son trabajadores altamente calificados, su tarea se basa en aplicar gran cantidad de conocimiento en la resolución de problemas y el diseño de modelos abstractos de desarrollo, utilizando herramientas y tecnologías nueva, cambiantes y muchas veces poco testeadas. Son trabajadores de la Era del Conocimiento.

Es por todos bien conocidas las consecuencias que ha traído la aplicación reciente de esta metáfora sobre todo en la realidad devaluada de Latinoamerica y varios países del mundo "en vias de desarrollo", a saber:

La Aparición de las llamadas "Factorías de Desarrollo de Software", o "Software Factories" que equiparan a los Programadores con obreros trabajando en fabricas (a más "obreros" más productividad, sin tener en cuenta la calidad del trabajo o el nivel de experiencia), adonde se les entregaba una especificación del sistema que tenían que "Construir" (palabra también proveniente de la misma metáfora), se les daba el Diseño del producto que debían seguir y se les aconsejaba "No Pensar".

Juro que en una factoría de una empresa en la que trabajé evaluaron la posibilidad de contratar dos turnos de desarrolladores para contar con una fuerza de desarrollo de 24 horas!!!

A aquel que sabe y conoce lo que se necesita para desarrollar sistemas de calidad la frase anterior le debería haber puesto la piel de gallina.

Buscando una salida

En conclusión, dos de los principales Contextos-Modelo elegidos para tomar soluciones para el desarrollo de software han llevado a aplicar numerosas técnicas fallidas, principios y modelos organizacionales que han causado gran daño a la industria y que todavía al día de hoy siguen creando confusión hasta en la forma de tratar a los trabajadores del desarrollo de software.

La historia no estaría completa si no buscáramos alguna salida para esta encrucijada. En un próximo Post contaremos las soluciones que plantean la gente del foro ágil de Hispanoamérica, foro-agiles, veremos entonces algunas metáforas que aplican un poco mejor al desarrollo de software y como han surgido y pueden seguir surgiendo de allí soluciones realmente válidas.

lunes, 1 de noviembre de 2010

Liderazgo (II)

En el post anterior hablamos un poco de cuales son las características deseables en un Líder, parte de una discusión que se dio en la lista de metodologías ágiles y Scrum , llamada "foro-agiles" (un grupo de yahoogroups). Vamos ahora a ver como encara este tema de como debe ser un líder de un equipo, Gerald Weinberg, autor de entre otros excelentes libros de "The Psychology of Computer Programming.", "Secrets of Consulting: A Guide to Giving and Getting Advice Successfully", etc.
El libro de Weinberg, "Becoming a Technical Leader" es un libro muy interesante adonde el autor aborda el tema del liderazgo desde una óptica poco común. En uno de los capítulos habla de la relación entre el líder y las personas que están a su cargo, para plantearse en síntesis como tiene que ser esta relación, definiendo la conclusión en forma de ciertas "leyes" sobre el liderazgo.

Comienza contando sobre un test que se realizaba en un curso sobre Liderazgo y Management Tradicional. En él se solía plantear una determinada pregunta proponiendo lo que es básicamente:
El dilema por excelencia del liderazgo

Usted esta a cargo de un equipo, y tienen una tarea a terminar. Si el éxito de la tarea se encuentra amenazado, usted probablemente:
a. Pondrá la finalización de la tarea por encima del bienestar de su gente.
b. Pondrá al bienestar de la gente por encima de la finalización de la tarea.
c. Balanceará la importancia entre su gente y la tarea.
d. Escapa de la situación.
e. Ninguna de las anteriores.

Una tarea debe ser completada con un cierto resultado dentro de un tiempo determinado o sino alguna consecuencia negativa sucederá, consecuencia que en principio solo conoce el Líder. Que actitud tomar?, Si uno requiere que todas las personas del equipo trabajen tiempo extra o hagan lo que sea necesario hasta terminarlo están poniendo a la tarea por encima de las personas. Si uno por otro lado comparte con su equipo las consecuencia del no cumplimiento, así como también el motivo por el cual tiene que ser realizada la tarea permitiendo al equipo decidir ellos mismos cuanto trabajar, como, e incluso si van a terminar la tarea entonces están poniendo a la gente por encima de la tarea.

La pregunta, que todos deberíamos hacernos es, Está bien planteado el test? Existe realmente una dicotomía entre tareas y personas? Porque en realidad la tarea que debe hacerse es realizada para conseguir un objetivo para otras personas, es decir que, en realidad el dilema es elegir entre un grupo de personas, diríamos los Interesados (stakeholders) en que se complete la tarea y las personas del equipo que debe realizarla, llamemoslos, Los trabajadores.

El capitulo en cuestión es sumamente interesante, y aquí van algunas de las lecciones más importantes que se destilan de él, que nos ayudan, de alguna manera, a razonar sobre el dilema.
Algunas Leyes sobre Liderazgo

Ley Numero 4: El líder que no le importa la gente no tiene a nadie a quien liderar, a menos que sus seguidores no tengan alternativa.

Ley Número 7: Hay muy pocas tareas que sean realmente tan importantes como para que justifiquen sacrificar las futuras posibilidades de las personas que están realizando el trabajo.

Ley numero 9: Para ser un líder efectivo debemos tener en cuenta y bien presente en todo momento los motivos y sentimientos de todas las personas afectadas por la tarea: los interesados y los trabajadores.
La Solución (como nosotros la vemos)

En mi opinión entonces, un líder efectivo puesto ante el dilema antes mencionado, encontraría la solución eligiendo e. Ninguna de las anteriores:
Primero debe pedir, obtener y entender los motivos, objetivos y sentimientos detrás de los Interesados en la tarea. Luego compartir con el grupo los motivos y consecuencias de la mismas, para que de manera seria y profesional todos tomen la responsabilidad de llevarla a cabo. Y teniendo en cuenta que nunca vale la pena sacrificar algunas personas por otras, conseguir llevar adelante la tarea dentro de tiempos y parámetros razonables para ambos grupos (la única excepción, claro, es que haya riesgo de vida, en este caso obviamente se puede sacrificar el bienestar de un grupo de manera temporal si la tarea salvará vidas).

Deje para terminar este post mi ley favorita:

Ley numero 10: Si tu eres un Líder , La Gente ES tu trabajo. No hay ninguna otra cosa que merezca tu atención.

miércoles, 27 de octubre de 2010

Liderazgo (I)

Hace tiempo, más tiempo del que me gustaría, en uno de mis primeros trabajos, se me acercó mi jefe de ese momento y sin más preambulo que una aclaración de garganta, en un tono seco y muy cortante me informó:

"La empresa necesita destruir unos papeles. Te vas mañana por la mañana a una planta de desechos en Loma-del-Ortis."
Y se dio la vuelta para Irse. Mi respuesta fue casi automática, visceral e inmediata:
"No", le dije.
La espalda se detuvo, y juro que percibí como se contracturaba todo antes de volverse con cara de pocos, poquísimos amigos:
"Como? que no vas a ir?"
"No, porque no me pagan para eso, soy programador."

La discusión que siguió fue bastante fea, con acusaciones de "Sos un principista", "no estas alineado con la empresa", etc.

La discusión fue doblemente fea porque podría haberse evitado totalmente. Que les parece que hubieran contestado si lo planteaba de la siguiente manera:

"La empresa tiene que mandar a destruir unos papeles. El que quiera ir tiene que levantarse un poco mas temprano, lo pasan a buscar en remise, el desayuno lo paga la empresa y a las 15 horas esta libre y se puede tomar el resto del dia libre. Quien quiere ir?" Porque realmente esas eran las condiciones.

Hace poco Martin Alaimo preguntó en la lista de foros-agiles que rol de Scrum era mejor para "reciclar" a un PM de la escuela PMI-stica, si era mejor que se transformara en un Product Owner (PO) o en un Scrum Master (SM).

Mas allá de la parte metodológica de la discusión que siguió: que en general se los asocia mas como Scrum Master, que los Analistas Funcional hacen mejor de PO, incluso mejor que los propios clientes , que depende del PM, que mejor continua fuera de Scrum llenando planillas o projects, etc., mas allá de todo esto, decia, de manera subyacente se estaba discutiendo el tema del Liderazgo y de que características deben tener un buen líder para ser efectivo (tanto si se hablaba del rol como PO, SM u otro).

Pueden ver la discusion original aqui, pero para resumir hubo excelentes aportes de Ingrid Astiz, Jose Manuel Beas, Pablo Rodriguez Facal y varios otros que fueron desgranando características (a veces por la negativa) entre las que rescato:

  • Un líder debe poner de costado su "propio ego"
  • Debe tener humildad y poner lo menos posible de su propio ruido
  • Aportar herramientas practicas y dejar que el equipo descubra su potencial.
  • Renunciar a la ilusión de importancia personal
  • No ser burócrata
  • Sentirse incomodo con forma de Gestionar de "Comando y Control"
  • Ayudar al equipo a triunfar
  • Escuchar a la gente
  • No adjudicarse el merito de los demás
  • No crear conflictos
  • No manipular
  • No caer en la inercia y tratar siempre de mejorar
  • No caer en la ilusión del control
  • No culpar al equipo por los fracasos
  • No tiene que estar encima de todos
  • debe confiar en las personas del equipo

¿Que les parece eh?! Pavada de listita!! Interesante para chequear a nuestro alrededor, verdad?

jueves, 21 de octubre de 2010

El miedo apropiado

Greg Poppovich es el entrador de los San Antonio Spurs (el equipo donde juega Ginóbili). Es un gran entrenador y ganó 4 títulos de la NBA. ¿Por qué lo mencionamos en este blog (además de para que nos lleguen todas esas búsquedas de Google)? Porque tiene una enfoque muy interesante sobre algo con lo que tenemos que tratar a menudo los programadores: el miedo.

A primera vista, no parece que el miedo tenga mucho que ver con lo que los programadores hacemos todos los días. Después de todo es poco probable que nuestras acciones causen daños graves a nadie. Sin embargo, todos los que hemos estado algún tiempo en esta profesión sabemos que es algo que nos acompaña todos los días. En uno de mis primeros trabajos, el miedo había llegado tan lejos que muchas de las personas en el proyecto se habían vuelto superticiosas, y no había manera de que alguien te aceptara que le alcanzaras un salero en la mano (y ni hablar de hacer una implementación un martes 13).

En el desarrollo de software, el miedo suele ser un enemigo, porque funciona como paralizante. Nos lleva a recurrir a parches en vez de realizar cambios que sabemos que son necesarios pero que nos obligarían a tocar partes del programa que nos aterrorizan. O nos hace seguir trabajando con tecnologías obsoletas (el típico "nadie fue despedido por elegir IBM").

Sin embargo, el miedo también es nuestro aliado. Cuando son las 5 de la mañana de una puesta en producción y finalmente parece que lo logramos y hacemos una última prueba antes de irnos a casa, es el miedo el que nos hace sacar fuerzas para no irnos ya a dormir. Cuando escribimos casi tantas líneas de tests de unidad cómo de código de producción también es el miedo a esas sesiones interminables de debugging el que nos ayuda a tomar ese camino, que en apariencia es más largo.

Entonces, ¿Cual es la actitud correcta frente al miedo? En mi opinión, la actitud de Poppovich: cuando un equipo gana seguido, tiende a perder perspectiva y a no tenerle miedo a los rivales. Esta actitud genera autocomplacencia y más tarde o más temprano provoca errores que causa que se pierdan partidos que se podrían haber ganado. Pero tenerle miedo a los rivales hace que uno juegue sin confianza y no se anime a tomar riesgos y que termine también perdiendo partidos que podría haber ganado. Por lo tanto, el objetivo es tener lo que Poppovich llama "Appropiate fear": suficiente miedo como para no hacer macanas por sobrar la situación, pero no suficiente como para que nos paralice.

Llegar a esta actitud lleva años tanto en basket como en desarrollo de software, pero realmente creemos que es la marca del profesional maduro de cualquiera de las dos disciplinas.

martes, 12 de octubre de 2010

Largá el twitter!

Probablemente el consejo de usabilidad más conocido por todos los programadores es el no construir menúes con más de 7 +- 2 opciones. Seguramente nuestros lectores recuerdan el motivo de este criterio: los seres humanos (y generalmente nuestros usuarios lo son) tenemos problemas en mantener en nuestra memoria de corto plazo más de esa cantidad de elementos a la vez.

¿Qué es la memoria de corto plazo? Para explicarlo en términos nerds (y muy simplificados), es una suerte de cache donde nuestro cerebro guarda cosas que podemos acceder en forma extremadamente rápida. Cuando todo lo que necesitamos para realizar una tarea está en esta cache, el desarrollo "fluye" y se producen esos momentos en que todas las ideas que tenemos son fácilmente plasmadas en nuestro código. Es en estos momentos cuando una hora de trabajo nos rinde más que ocho horas de trabajo normal. Este fenómeno es lo que en inglés se conoce como "flow" o estar "en la zona".

Este estado de concentración total es dificil de alcanzar y es muy frágil. Cualquier interrupción hace que nuevas cosas ocupen nuestra cache y cuando queremos volver a nuestra tarea el cerebro empieza a "paginar", buscando los pedazos de información que necesita para continuar. Si estas interrupciones se producen muy a menudo, trabajamos todo el tiempo de una manera muy inferior a nuestro verdadero potencial y todas las tareas nos llevan mucho más tiempo del que deberían.

Entre las interrupciones que sufrimos normalmente, las mas comunes son las interrupciones producidas por nuestros compañeros de trabajo o, peor aún, por nuestros jefes. Estas son interrupciones dificiles de evitar. Una manera es llegar muy temprano o quedarse más tarde en el trabajo, de manera de tener unas horas de productividad por día. Otra manera es ponerse de acuerdo entre compañeros y hacer los pedidos de ayuda de una manera no intrusiva, de forma tal que la persona a la que vamos a interrumpir pueda manejar el momento en que responde a nuestro pedido (por ejemplo por mail). A riesgo de quedar como un antisocial, también es posible enchufarse los auriculares y poner "Cowboys from Hell" a todo volumen.

Otras interrupciones son mucho más fáciles de solucionar, aunque requieren más fuerza de voluntad. Me refiero a las interrupciones causadas por messengers, redes sociales, mails, etc. A menudo he visto trabajar a programadores a la vez que chatean con 3 o 4 personas y generalmente estos programadores producían código de baja calidad, con millones de bugs y mucho más lentamente que los programadores que trabajaban más concentrados. Esto no quiere decir que se deban prohibir estas herramientas (y mucho menos que los programadores deban trabajar sin conexión a internet, como he visto en algunas empresas). Quiere decir que es importante separar el tiempo en que se está programando del tiempo en que se está chateando, y que aunque parezca antiintuitivo, un programador que dedica 6 horas de su tiempo a programar y 2 a chatear va a ser mucho más productivo que si dedicara sus 8 horas a programar a la vez que chatea.

Ultimamente estoy utilizando una forma de trabajo basada en la técnica Pomodoro (aunque no siguiéndola al pie de la letra ya que esta tiene otras cosas interesantes, que espero poner en práctica en algún momento). Básicamente divido mi tiempo de trabajo en mini-sprints de 24 minutos. Durante esos mini-sprints desactivo los messengers, las notificaciones de mails y básicamente todo lo que me puede llegar a interrumpir. Trabajo totalmente concentrado durante esos 24 minutos y cuando termino me tomo unos 5 minutos para descansar. Antes de arrancar el siguiente sprint, verifico si tengo mails que contestar o si alguien intento chatear conmigo. Cada tres o cuatro sprints, me tomo un descanso un poco más largo.

De esta manera, puedo mantener períodos intensos de concentración y a la vez solo estoy incomunicado por a lo sumo 24 minutos por vez. Es interesante que en las primeras épocas en que utilicé está técnica, terminaba el día muy cansado, por la falta de costumbre de trabajar realmente a full tanto tiempo.

Nuevamente, estas ideas no apuntan a que nos comportemos como robots ni a que seamos antisociales, trabajando todo el tiempo totalmente concentrados y sin comunicación con el resto. El ambiente laboral es algo muy importante y las charlas y los chistes alrededor de la cafetera ayudan a formar ese ambiente laboral. También son muy importantes las reuniones de equipo como el Daiyly Meeting, de Scrum. Lo que buscamos es maneras de hacer que el tiempo que dedicamos a programar sea mucho productivo solo dedicándose a ..... Programar!.

miércoles, 6 de octubre de 2010

Code Smell - Codigo Duplicado

Queridos Chimpances entrenados, Recuerdan lo que eran los Code Smells?

Bien, si tuvieramos que entregar el Oscar a los Code Smells, el número uno, el primer premio se lo lleva sin dudarlo el código duplicado.

Codigo duplicado implica tener la lógica del sistema duplicada en dos o mas lados, en la misma o distintas clases, incluso en distintas capas.

Porque esto es malo?

El primer problema es que cuando tengamos que modificar el código duplicado (y SI,antes de que pregunten les digo: Vamos a tener que modificarlo con 100% de seguridad) es muy probable que nos olvidemos de cambiar alguna ocurrencia de la duplicación, introduciendo bugs.
En segundo lugar estamos salteando una relación de ese código con alguna de las clases. Es decir, a alguna clase realmente le corresponde ese comportamiento que está duplicado y en el resto de los lugares de la duplicación no estamos honrando está relación que mas pronto que temprano nos traerá problemas.
Es fundamentalmente en este sentido en que es un Code Smells de nuestro diseño. Algo malo esta pasando, falta un método y ese método debe ir en alguna clase lo cual causará un rediseño de nuestro sistema.
En tercer lugar el código duplicado produce que el código sea más dificil de leer y de entender.

Además, el código duplicado tiende a ser modificado de maneras ligeramente distintas en cada una de las copias, con lo que suele pasar que después de un tiempo ya no es trivial decir si dos fragmentos de código que originalmente eran duplicados siguen haciendo lo mismo o no.

En sintesis, el problema fundamental de tener la lógica duplicada es que hace al sistema más dificil de mantener, y ya sabemos que la mantenibilidad es la propiedad numero #1 que debemos procurar para nuestro codigo.

Ahora bien, la lógica duplicada a menudo se presenta en formas mucho más sutiles que una duplicacion literal de codigo, si bien hemos visto más de un ejemplo de estos.

Podemos encontrar los siguientes tipos (principales) de duplicacion de código:

1 - Duplicacion simple: Es la forma más común de duplicacion. Sucede cuando se tiene la misma expresión (identica o diferentes en variables) en dos métodos de la misma clase. La solución es aplicar el refactoring "Extract Method" extrayendo el código duplicado en un método privado y llamando desde ambos lugares de la duplicación al nuevo método.

2 - Duplicación en clases relacionadas : Es cuando se encuentra la misma expresión en dos o más subclases de una misma jerarquia de Clases. Es una duplicación bastante común también ya que provienen de comportamientos comunes de clases hermanas hijas de una misma Clase padre. La forma de solucionarlo es extraer el codigo duplicado en ambas subclases con "Extract Method" y luego si aplica a todas las subclases subirlo a la clase padre, si no aplica es una indicación de que hay un problema de diseño con la jerarquía de clases. A veces hay parte de una logica duplicada y otra parte no, en ese caso se puede convertir el método en un "Template Method" en la clase padre, abstracto y luego implementar la parte que es diferente en ambas subclases.

3 - Duplicación en clases no relacionadas : Como el titulo lo indica, es tener duplicación en dos métodos de dos clases A y B no relacionadas por herencia ni interfases. En este caso se debe considerar extraer el comportamiento duplicado en la clase A y generar una nueva clase C que contenga este codigo (refactoring "Extract Class") y luego reemplazar el código duplicado en la segunda clase B por una invocación a la nueva C. Otra posibilidad es que la lógica duplicada realmente pertenezca a una de las dos clases, y la otra debe invocar a la clase a la que pertenece el codigo. Una tercera posibilidad es que pertenezca a otra clase ya existente. Aplicando la Ley de Demeter, el Single Responsability Principle y el sentido común tenemos que encontrar el lugar adonde esta lógica pertenece y removerla de todo otro lugar.

4 - Duplicación en distintos lenguajes : Por ejemplo, validaciones que tenemos que hacer tanto en la GUI (por ejemplo en Javascript) y en el backend (por ejemplo en Fortran... :)). Este es un tipo de validación dificil de evitar. Una manera posible es escribir el código para uno de los lenguajes y generar el código del otro automáticamente a partir de este.

Para terminar les dejamos una regla práctica para aplicar cuando estamos ante una duplicación de código.

La regla del tres (Don Roberts)

La primera vez que uno escribe una lógica la escribe y listo. La segunda vez que uno hace algo similar debe fruncir el ceño, tomar nota y dejar la duplicacion de cualquier manera. La tercera vez que aparece la duplicación, bang!, uno debe eliminarla, a través de la refactorización.

Entonces, recuerden, Una de las Buenas Practicas de programación que más recomendamos es buscar todo Code Smell que encuentren en el codigo y removerlo a través de la refactorización.
Y si pensamos que el código duplicado es el origen de muchos males (Duplication is evil) y uno de los Code Smell más comunes, aprender a buscar, detectar y remover duplicaciones de código es una actividad a la que debemos aplicarnos si queremos convertirnos en Programadores (así con "P" mayúscula).

miércoles, 29 de septiembre de 2010

Toda la verdad acerca de los Tests de Unidad

Porque son tan importantes los tests de unidad?

Uno podria preguntarse que hay detrás de taaaanto rollo acerca de una de las prácticas fundamentales tanto de XP como de toda lista de Buenas Prácticas de Programación. Porque es tan importante hacer tests de unidad?. Este posteo intenta justamente responder a esa pregunta, explicando detalladamente los beneficios principales que se obtienen al hacer tests de unidad.

Esta lista no intenta ser extensiva, ni se obtienen solo al hacer Test Driven Development, TDD, ya que algunos de los beneficios se obtienen también haciendo tests de unidad "PostMorten", es decir, luego de escribir el código.

Vamos, primero, a la enciclopedia galactica:

Tests de unidad: son los tests que un programador debe escribir para testear que su código hace lo que él entendió que se le solicitó que haga, a través del documento de especificación funcional, sea una historia de usuario, caso de uso o conversación con usuarios.

Hacemos esta distinción para diferenciarlos de los tests de aceptación que son aquellos tests de más alto nivel que deben verificar que la funcionalidad desarrollada es aceptada de acuerdo a lo definido en el relevamiento con los usuarios.

Por otro lado cuando decimos que se hacen tests de unidad o TDD estamos asumiendo que se realizan correctamente y con un cubrimiento del total de código del modelo (en un framework MVC) escrito de más del 80%.

Para aquellos que quieran hacer el salto más significativo en el desarrollo de software desde la invención de la Programación Orientada a Objetos (y no estamos exagerando), los beneficios son:

El beneficio global primero y quizás más importante es que el conjunto de tests de unidad funcionan como una malla de seguridad que permite hacer cambios al código de una manera segura y órdenes de magnitud más rápida que cuando no tenemos tests. Y esto para un mundo no perfecto como el que vivimos en el cual los usuarios/la realidad/Lo-que-Sea piden cambios de funcionalidad constantemente no es poca cosa.

En detalle, los beneficios que nos proveen los tests de unidad son incontables (como los beneficios de la soja ;) :

  1. Los tests de unidad verifican que el código en realidad funciona (de acuerdo a lo que entendió el programador, vale la pena aclararlo) lo cual significa que vamos a tener menos bugs y errores.
  2. TDD fuerza a pensar en los contratos de clases y métodos antes de escribir el código, lo cual lleva a un diseño mejor y mucho más preciso de la solución al problema planteado.
  3. Los tests de unidad hacen posible mejorar iterativamente el diseño del sistema sin romperlo. Como contamos con un conjunto de tests de unidad que verifican todo lo que se puede romper, podemos aplicar mejoras al diseño de manera incremental a través de pequeños pasos de refactoring y luego verificar si funciona corriendo todos los tests. Ante un error podemos fácilmente determinar que parte del nuevo código rompió el sistema y corregirlo.
  4. No reemplazan pero complementan muy bien a los tests de aceptación y de integración.
  5. En si sirven como un conjunto de tests de regresión de bajo nivel.
  6. Funcionan como documentación y Reduce el tiempo necesario para entender el código escrito. En general nos olvidamos muy rápidamente de lo que hace el código que escribimos hace apenas unos días atrás (mas de una vez ha pasado que miramos el código asombrados pensando en el... espécimen que habrá escrito semejante zafarrancho para terminar dándonos cuenta que fuimos nosotros mismos.... y no, no digan que nunca les paso). Imaginen además cuando tenemos que entender código escrito por otros. Los tests de unidad funcionan como perfectos ejemplos de utilización del código, documentan la utilización correcta del cada método no trivial y de la relación entre las clases. Y a diferencia de la documentación no quedan desactualizados al instante porque en cuanto eso sucede uno o varios del 100% de los tests de unidad comienzan a fallar y debemos arreglarlo (o el test o el código).
  7. Reduce el costo de mantenimiento. En Lean Software Development se define el costo de un bug como el tipo de criticidad del error (bajo, medio, alto), multiplicado por el tiempo en que permanece no detectado. Tener un buen conjunto de tests de unidad permite reducir drásticamente el tiempo que lleva detectar un bug, y corregirlo. A la vez, si uno desarrolla el sistema haciendo TDD se introducirán muchos menos errores y además cuando se sucede se detectan casi inmediatamente, el error esta en lo ultimo que se cambió.
  8. Nos sacan de un viejo círculo vicioso del desarrollo de software: como tenemos miedo de realizar cambios en la estructura de un programa, hacemos las modificaciones imprescindibles mediante parches, lo que causa que el programa sea mas díficil de modificar, lo que causa que nos de miedo realizar cambios estructurales...
  9. TDD nos fuerza a a usar Pasos de Bebé y por lo tanto a pasar menos tiempo en el debugger.

Una de las objeciones principales que se hacen en contra de escribir tests de unidad es que como es más cantidad de código que hay que escribir entonces esto va a hacer que el desarrollo vaya más lento, verdad?. Esto sería verdad si fuera que nosotros, los programadores, somos una especie de taquígrafos que nos pasamos la mayor parte del tiempo tipeando en un teclado, y entonces la cantidad de teclas por minuto se contaría como productividad. Pero esto no es asi, nos pagan por pensar, por diseñar y evolucionar una solución a un dominio de problemas. Esta comprobado que la mayor parte del tiempo un programador la pasa pensando como modelar una solución y, sobre todo, buscando errores y bugs. Escribir tests de unidad sirve justamente para hacer estas dos actividades mucho mas eficientes.

Como conclusión, y aunque sea antiintuitivo, escribir tests de unidad lleva menos tiempo total que no escribirlos.

lunes, 20 de septiembre de 2010

"Pasos de Bebe", El fin del Debugging?

Baby Steps

Mirando a nuestro hijos aprender a caminar es fascinante. En un momento están agarrados de un sillón, una silla o de nuestras piernas y de repente comienzan a dar el primer paso, pequeño, muy cercano, y luego otro, tanteando con un pie hasta estar firme y luego , tambaleantes, llevan el otro pie al lado. Y así. Con el instinto que la madre naturaleza les dio, nunca intentan empezar a correr o dar zancadas.

Alla Lejos y hace tiempo

Hace muchos años, en nuestros primeros trabajos (en esa época teníamos que fabricar nuestros propios bytes :), nuestra forma de trabajo, a grandes rasgos, era algo asi:

1. Escribir un montón de código.
2. Compilar el código escrito y corregir los errores (no, no habia intellisense).
3. Probar y debuguear el código una y otra vez hasta que funcione.

Cada una de estas etapas tomaba días o incluso semanas. Cuando nos preguntaban como venía el proyecto, la respuesta típica era "ya terminé de escribir el código, me falta probarlo". Si tenías suerte, nadie te preguntaba cuanto tiempo de trabajo te faltaba...

El problema justamente es que luego de incluir en el proyecto una cantidad de lineas de código producida durante varios días, no hay forma de predecir cuanto tiempo llevará terminar el punto 3. Y ni siquiera estamos hablando de que este punto implicaba realizar "casos de prueba" exhaustivos, este punto solo significaba que lograbamos hacer que el código funcionara en los escenarios más comunes (con suerte).

Esta forma de encarar el desarrollo es un resultado natural de toda la corriente de Waterfall muy en boga en esos días. Si lo más productivo es primero hacer todo el análisis, después todo el diseño y después toda la codificación, tiene sentido dividir este último paso en etapas también.

Con el tiempo, y luego de muchos golpes, y algunas pesadillas, empezamos a trabajar de una forma bastante distinta:

1. Escribir 3 o 4 líneas de código.
2. Compilarlo.
3. Probarlo.

La gran diferencia es que generalmente los pasos 2 y 3 no llevan nada de trabajo, ya que somos capaces de escribir 3 líneas de código sin equivocarnos o cometiendo sólo errores obvios y luego probar que funcionan esas 3 o 4 lineas nuevas es algo manejable y en general muy sencillo de realizar(de hecho, programando así casi no se usa el debugger, vale la pena remarcarlo: Casi no se usa el Debugger, y ni les cuento si esas 4 lineas de código se escribieron a partir de un test, haciendo TDD).

Esta forma de trabajar fue descrita como una buena práctica de desarrollo por varios referentes de nuestra profesión, la mayoría proveniente de las metodologías ágiles, y se le dio el nombre de "Pasos de Bebe", "Baby Steps", en ingles. Recientemente se la describió con otro nombre mucho más técnico, "Desarrollo Nano Incremental".

Ahora, cuando nos preguntan como va el proyecto, generalmente la respuesta es del tipo "la aplicación ya puede hacer X e Y, falta que haga Z y terminamos". Además el tiempo total que lleva hacer las cosas es mucho menor, ya que los pasos 2 y 3 llevaban semanas (y a veces un tiempo indeterminado) en la forma de trabajo anterior, llamemosla, para ponerle un nombre igual de rimbombante: "Big Bang de Código".

¿Por qué se da esto?

En primer lugar, porque el desarrollo de software es complejo y nosotros los humanos no podemos manejar toda la complejidad de golpe si no la atacamos dividiendola en "trozos" manejables (Divide y Venceras, dice el dicho). Somos capaces de hacerlo bien para cambios pequeños, pero cuanto más grande es el salto que queremos dar, más probabilidades tenemos de cometer errores, que después llevan mucho tiempo corregir.
Esto se nota mucho cuando utilizamos TDD, donde escribir tests demasiado grandes nos lleva a cometer muchos errores e incluso produce que uno no pueda avanzar (esta fue una de las cosas que notamos en el último Code Retreat).

En segundo lugar, tomar pasos pequeños nos permite aprender de nuestros errores. El conocimiento que obtenemos en cada ciclo es utilizado en el siguiente, que tiene lugar unos minutos después. En cambio cuando se utiliza el "Big Bang de Código", las cosas que se aprenden se pueden utilizar recién en el siguiente proyecto.

Además, tener siempre código compilable y que funciona nos permite obtener feedback de la gente para la cual estamos trabajando. Es un hecho que la mayoría de los clientes no sabe exactamente lo que quiere hasta no ver una aplicación funcionando y si desaparecemos durante meses antes de mostrar algo es probable que terminemos programando algo muy distinto a lo que nuestros clientes necesitan.

Por último, este desarrollo nano-incremental permite justamente ir evolucionando muy despacio el diseño, y sólo con lo que se necesita para resolver el problema en cuestión sin agregar funcionalidad extra que no se necesitara. Justamente al diseño así obtenido se lo llama Diseño Incremental.

Pasen la Palabra

Pese a todos estas razones, y evidencia de muchas fuentes, y entre ellas, nuestra propia experiencia, vemos que la forma de trabajo más común entre los programadores sigue siendo el "big bang" de codigo. Y para ser sinceros, hemos tenido hasta ahora relativo éxito en conseguir convencer a nuestros compañeros de utilizar el "Pasos de Bebe".

Intuitivamente, se sigue creyendo que juntar grandes lotes de código para después probarlo es más eficiente y productivo. Es razonable, porque para muchas tareas de la vida real es así: si uno va a lavar los platos conviene primero ponerle detergente a todos los platos, después enjuagarlos y después lavarlos. No tiene sentido tomar un plato, ponerle detergente, enjuagarlo y secarlo.

Sin embargo, el desarrollo de software no se parece al lavado de platos (ni tampoco a la construcción de edificios para el caso).

Así que si se animan a probar un deporte de riesgo, si les gusta luchar con leones hambrientos y no son débiles de corazón, en su próximo proyecto apliquen esta practica de desarrollar en "Pasos de Bebe". Les aseguramos que van a ver una considerable mejora en su productividad.

Y mucho, mucho, menos debugging.

lunes, 13 de septiembre de 2010

2do Code Retreat

El Evento

El viernes 10/09 realizamos el Segundo Code Retreat en Buenos Aires, en las instalaciones del MUG (Microsoft User Group).

Queremos antes que nada agradecer a los que nos ayudaron a organizar este Retreat, particularmente a Juan Gabardini, referente de la comunidad ágil de Argentina (recomendamos su blog softwareagil.blogspot.com), a Martin Salias (de Southworks ), a Carlos Peix y especialmente a Oscar Turquet del MUG.

La experiencia fue muy satisfactoria, y en esta oportunidad tuvimos el aporte de la vision de gente con mucha experiencia como Carlos Peix, Martin Alaimo (de Kleer) o como Juan (Gabardini) que proviene del sector de Testing.

La lista de Asistentes al Retreat fue :

  • Carlos Meschini
  • Carlos Peix
  • Martin Alaimo
  • Matias Blanch
  • Carlos Pantelides
  • Fernando Claverino
  • Nicolas Bases
  • Juan Gabardini
  • Victor Jorge Paredes
  • Gonzalo Amestoy
  • Jose Vidal

Conclusiones del Retreat

En general la mecanica del Retreat funcionó, encarando el problema a resolver cada vez desde cero, borrando el codigo entre iteraciones y cambiando de compañero de Pair Programming. Falto quizás una iteración más para hacer mas aceitada la mecánica pero la hora y el día en particular no daba para mucho mas.

El tema de hacerlo un viernes ayuda y complica a la vez, porque hay gente que no puede salir de sus trabajos y por otro lado esta el cansacio de la semana, pero en general hubo muy buena onda y energia como para completar 3 iteraciones completas, con una retrospectiva final que se extendio por casi 40 minutos.

Uno de los puntos en que coincidieron todos los participantes, tratando de hacer TDD, es la dificultad para incrementar la funcionalidad de los tests de a pequeños pasos. En general los dos o tres primeros tests "triviales" salen mas o menos bien, simples y en pequeños pasos, pero cuando hay que avanzar en un test que permita introducir funcionalidad no-trivial en general se escribe un test con un salto demasiado grande lo cual dificulta luego el desarrollo.

Justamente otro de los temas que salieron fue la relación entre facilidad de testing y buen diseño del código. Es decir, si se dificulta testear algo muchas veces es porque hay problemas con el diseño del modelo de la solución.

A veces cuesta mantener los tests de unidad porque no prestamos la suficiente atención a la calidad del código de los mismos, ya que es código fuente se deben tener todos los cuidados y aplicar todos los principios y buenas prácticas como con el código de la aplicación principal, sino su mantenimiento se convierte en una pesadilla. Por ejemplo, si un tests prueba más o menos lo mismo que otro se deben eliminar porque la duplicación es uno de los Code Smells que más problema trae a la mantenibilidad del código.

Entre las cuestiones "negativas" que de alguna manera son causadas por la dinámica del Retreat se mencionó que la presión de avanzar en la solución del problema muchas veces hacia que uno le prestara poca atención a la etapa de Refactoring.

En TDD, despues de hacer el test, y de hacer lo necesario para pasar, cuando los tests funcionan (La barra esta toda en "verde") se debe evaluar el diseño del código para ver si es necesario refactorizar. Este punto quedaba de lado muchas veces causados por la "presión" de la duración de la iteración.

Otro punto "flojo" es que en general no se hizo Pair Programming respetando tajantemente los roles de "Conductor" y "Navegante". Es decir estaban ambos integrantes muy compenetrados en los detalles más chicos del código y el que no tecleaba no funcionaba como "navegante", mirando todo desde un punto de vista más alejado, previniendo de posibles desviaciones (como fue esta de no evaluar si correspondia aplicar Refactoring).

Ademas de C# y Java, hubo algunos participantes que utilizaron Ruby y RSpec. Invitamos a los que estuvieron trabajando con estas herramientas a que nos cuenten sus impresiones.

Finalmente, queremos volver a agradecer a todos los involucrados, por su buena onda, su energia y sus ganas. Sabemos que es un esfuerzo significativo dedicarse a aprender uno mismo, con el objetivo de mejorar profesionalmente, pero vale la pena. Tambien decirles que ya nos estamos poniendo a pensar en futuros encuentros. Hasta la proxima!

miércoles, 1 de septiembre de 2010

Inscripcion al Segundo Code Retreat!!

Se viene el segundo Code Retreat!! Para todos los que protestaron (con total justicia) porque el primero fue un sábado muy temprano, esta vez va a ser el Viernes 10/09, de 14:30 a 20 horas, en el MUG (Microsoft User Group), que queda en Rivadavia 1479 Piso 1 Of. A.

Estamos muy contentos porque la pasamos muy bien en el primer Code Retreat que hicimos a principio de año.

Aquí, en el sitio de la comunidad ágil de Argentina se puede ver más información sobre el evento y los interesados pueden anotarse en esta página.

Los esperamos!

lunes, 30 de agosto de 2010

Algunas herramientas para usar con Selenium

Como contaba aquí estuve automatizando tests de aceptación con Selenium, utilizando como lenguaje de programación para los tests Ruby. En este post voy a hablar un poco de las herramientas que utilicé para facilitar esta automatización.

La tarea más importante (pero también la más tediosa) en este tipo de automatizaciones es la identificación de los objetos gráficos (botones, cuadros de texto, etc.) con los que queremos interactuar. Si la aplicación fue desarrollada de manera de que todos los objetos tengan identificadores únicos que se puedan predecir con algún tipo de lógica el problema se simplifica bastante, pero en general esto se da solamente si se fueron escribiendo tests de aceptación en paralelo con el desarrollo de la aplicación. En el caso más usual en que escribimos los tests después de que la aplicación está terminada, debemos dedicarle bastante tiempo a buscar maneras de identificar los componentes de la UI (y no solamente debemos identificarlos si no que debemos hacerlo de una manera robusta, que no cause que todos nuestros tests fallen ante pequeños cambios en la estructura)

Existen varios plugins de Firefox que pueden ayudarnos en esta tarea. En primer lugar está Firebug que es un plugin indispensable para cualquiera que desarrolle aplicaciones Web, con muchísimas funcionalidades que exceden el alcance de este artículo. Solo vamos a mencionar que utilizando este plugin podemos identificar cualquier objeto en la pantalla simplemente haciendo click en el despues de seleccionar la herramienta adecuada.

Otros plugins interesantes son XPather y FireFinder. Estos plugins nos permiten probar expresiones CSS y XPath contra la página que queremos testear, para verificar que estén construidas correctamente y que identifiquen a los objetos que necesitamos. Poder hacer esto desde un plugin contra la página viva nos permite darnos cuenta de errores en forma interactiva, sin necesidad de ejecutar todo un test de aceptación para llegar a la parte del código que contiene la expresión que queremos probar.

Otra manera de probar partes de nuestros tests sin necesidad de ejecutar un test de aceptación completo es utilizar la capacidad de Ruby para trabajar en forma interactiva. Para eso es muy útil el shell de Ruby.

AutoIt es una herramienta fundamental para automatización de tests de aceptación en ambiente Windows. Si bien Selenium está perfectamente equipada para interactuar con casi todos los elementos de la interfaz gráfica, tiene problemas con ciertas ventanas, como las confirmaciones de seguridad o los diálogos para el download de archivos. Esto se debe a que esas ventanas no son ventanas HTML si no que son ventanas nativas del sistema operativo. Por lo tanto, cuando necesitamos realizar actividades que incluyan ese tipo de ventana tenemos que recurrir a herramientas más nativas, como AutoIT. Por suerte, se engancha muy bien con Ruby.

Para poder generar datos para los tests, utilicé esta librería Es un port de una antigua libreria de Perl y contiene colecciones de datos para usar en los tests. Por ejemplo, si necesitamos un nombre para un test hacemos Faker::Name.first_name y esto nos devuelve un nombre al azar de la colección de datos interna de la librería.

Por la ausencia de buenos identificadores en la aplicación para la cual estoy escribiendo los tests, tuve que recurrir mucho a expresiones complejas XPath para identificar los objetos. Esto funcionaba perfectamente bien en Firefox, pero cuando probé con Internet Explorer, los tiempos de ejecución crecieron más de 10 veces!!

Esto se debe a que el motor de Javascript de IE es exasperantemente lento. Era un problema, ya que sabemos que los tests deben ser rápidos, así que estuve haciendo algunas pruebas y la solución que encontré fue la siguiente: en vez de pedirle al browser que identifique un objeto en base a una expresión XPath, le pido todo el DOM en formato HTML y realizo la búsqueda XPath en el cliente Ruby que ejecuta los tests. Esta solución es anti-intuitiva, ya que bajarse todo un documento HTML para hacer una búsqueda parece menos eficiente que hacer la búsqueda en el browser, pero el motor XPath de IE es tan lento que conviene hacerlo así. Para realizar las búsquedas en el documento HTML usé la excelente librería Hpricot, del desaparecido _why.

Finalmente, para organizar la corrida de los tests y para tener un output más o menos lindo con el resultado de la ejecución, usé la librería RSPec, que es un framework que normalmente se usa para BDD en Ruby.