lunes, octubre 25, 2010

9 cosas que todo desarrollador debe saber

El libro 97 things every programmer should know contiene 97 pequeños consejos y prácticas que como desarrolladores deberíamos aplicar a diario en el desarrollo de software. En su blog, Brian Du Preez destaca 9 consejos en particular que le resultaron de interés. Veamos cuáles son...

1. La regla del Boy Scout (por Robert C. Martin, Uncle Bob)

"No es necesario hacer que cada módulo sea perfecto antes de subirlo al repositorio de código. Simplemente basta con hacer que sea un poquito mejor que cuando lo bajamos".

Nos resulta fácil decirnos cosas como "Ya estaba así", o "ese código horrible está así desde hace años, no voy a tocarlo", o "nunca tuvo pruebas". Si parte de nuestro proceso fuera hacer las cosas un poquito mejor (como borrar código que no se usa, o escribir una prueba unitaria), año tras año... lograríamos ahorrar mucho tiempo y dinero a muchas personas.

2. La belleza está en la simplicidad (por Jørn Ølmheim)

"Al final, el código hermoso es el código simple"

Con los años esto me resultó muy importante. Cuando empecé esta carrera, y especialmente cuando tenía que comenzar algo nuevo, me embarcaba en crear los mega-diseños. Era algo como "Bienvenido a la escuela de la sobre-ingeniería", todo sería una abstracción al décimo nivel, y habría patrones de patrones, interfaces para las abstracciones y enormes cantidades de código y componentes que se encargaban de cualquier "qué pasaría si" que podría existir, y que sólo yo comprendía. Todo esto llevaba a código muy "atractivo", y aumentaba mi ego, ¿pero a qué costo?

Sólo había un pequeño detalle: mantenerlo era una pesadilla. Desde entonces prefiero la implementación más simple para casi cualquier solución, incluso aunque no parezca la mejor implementación técnica. En el mundo del software, la mantenibilidad siempre debería pesar más que otros temas.

3. Detenete y automatizá, automatizá, automatizá (por Cay Hosrtmann)

Debemos automatizar todo lo posible: construcciones, despliegues, análisis de código, pruebas unitarias, pruebas funcionales, pruebas de integración. Nadie quiere mirar estas cosas todos los días y la automatización es la única forma de alejarnos de esto. No podemos automatizar demasiado. Automatizá, automatizá, automatizá.

4. Aprendizaje continua (por Clink Shank)

Este es un tema muy importante, estamos en una industria de constante crecimiento y cambio, y como programadores necesitamos estar aprendiendo y mejorando siempre que podamos. Es fácil caer en la zona de confort y descansar sobre los laureles. Algunas cosas que recomiendo:

  1. Lean libros.
  2. Usen Google Reader y agreguen blogs populares y feeds RSS de sitios web para temas específicos de su interés, además de agregar algunos otros temas que no sean de su interés particular.
  3. Creen un blog, y traten de publicar algo 1 -2 veces por semana, asegurándose que sea cosas nuevas que aprendieron.
  4. Únanse a alguna comunidad de software libre, en general no tenemos suficiente desarrollo "técnico" en los ambientes corporativos.

5. Antes de culpar a otros verificá tu código (por Allan Kelly)

Como dice el título, tendemos a buscar la culpa en cualquier cosa excepto nuestro código "perfecto". Desde el sistema operativo hasta la red, desde la base de datos hasta la JVM, desde librerías hasta las interfaces de otros equipos. Esto nos lleva a horas y horas de esfuerzo desperdiciado, o ignorar por completo el problema real que eventualmente volverá a molestarnos. La mayoría de nosotros puede recordar momentos en los que hicimos esto... y es tan frecuente que asusta.

6. El trabajo duro no vale la pena (por Olve Maudal)

"La verdad es que trabajando menos podemos lograr más"

"Si tratás de estar enfocado y "productivo" por más de 30 horas a la semana, seguramente estás trabajando demasiado"

Una gran frase de Olve Maudal. Muchos de nosotros ya pasamos por esto, gastamos días, semanas meses de trabajo, pero no solemos ver los efectos negativos que ocurren después de trabajar 50-70 horas por semana. Desde la lógica común hasta la motivación y la dinámica del equipo, todo esto sale por la ventana. Incluso aunque se logren los objetivos a corto plazo, a menudo las repercusiones a largo plazo son mucho peores. Nadie revisa porqué hay que re-escribir después de 4 años debido a que la arquitectura o el código nos sirven. Me encantaría saber cuántas de estas situaciones son por trabajar una cantidad ridícula de horas con tiempos imposibles. Puede haber alguna ocasión donde sea necesario un par de horas extras, pero debemos mantener esto al mínimo.

7. Comentar sólo lo que el código no dice (por Kevin Henney)

Lo que dice. No le contemos a otro programador lo que puede saber leyendo el código. Los comentarios tienen que explicar el motivo de negocio detrás de un algoritmo en particular, lo cual es mucho más útil que un //sumar 1

8. Conocer al IDE (por Heinz Kabutz)

Pasamos varias horas con nuestro IDE. Aprender los atajos, las características que tiene... usar el IDE con todo su potencial nos puede ahorrar incontables horas.

9. Aprender a estimar (por Giaovanni Asproni)

Si bien esto es algo que viene con la experiencia, podemos hacer cosas para mejorar esta habilidad. Algunos puntos para mejorar nuestras estimaciones:

  1. Sean honestos con ustedes mismos, digan lo que saben y admitan abiertamente lo que no.
  2. Tengan presente lo que hacen y cuánto les lleva, no necesariamente para el líder del proyecto sino para ustedes mismos. Sean honestos con ustedes mismos.
  3. No cuenten las estimaciones ni habilidades percibidas de otras personas. Sean honestos con ustedes mismos.

jueves, octubre 21, 2010

TDD y Unit Tests




Benefícios de Test-Driven Development

  • El conjunto de test unitarios proporciona contante retroalimentación de que cada uno de los componentes sigue funcionando.
  • Los test unitarios actuan como documentación que no se queda obsolet, al contrarío que otros tipos de documentación.
  • Cuando el test pasa y el código de producción es refactorizado para eliminar duplicidades, es claro que el código está terminado, y el desarrollador se puede mover a la siguiente tarea.
  • TDD fuerza un análisis y diseño crito porque el desarrollador no puede crear código de producción sin entender realmente cuales deberían ser los resultado deseados y como probarlos.
  • El software tiende a estar mejor diseñado, esto es, menos acoplado y más facilmente mantenible, porque el desarrollador es libre de hacer decisiones de diseño y refactorizar en cualquier momento con la confianza de que el software todavia funciona.
  • El conjunto de tests actua como una red de seguridad contra regresiones en los bugs: Si se encuentra un bug, el desarrollador debe crear un test que ponga de manifiesto el bug y despues modificar el código de producción para eliminar el bug. En sucesivas ejecuciones de los test, todas las correcciones de bugs son verificadas.
  • El tiempo de depuración se reduce.

Características de un buen unit test

  • Se ejecuta rápido, se ejecuta rápido, se ejecuta rápido. Si los test son lentos, no se ejecutaran a menudo.
  • Separa o simula dependencias ambientales como bases de datos, sistemas de archivos, redes, colas y demás. Los test que ejercitan estos no serán rápidos y los fallos no dan información significativa sobre cual es el problema realmente.
  • Es muy limitado en su alcance. Si el test falla, es obvio donde bucar el problema. Realiza pocas llamadas a la clase Assert de manera que el código que falla sea obvio. Es importante probar una única cosa en cada test.
  • Se ejecuta y pasa de manera independiente. Si los tests requieren establecer entorno especial o fallan inexperadamente, no son buenos tests unitarios. Cambialos por simplicidad y fiabilidad. Los teste deben ejecutarse y pasarse en cualquier máquina. La excusa "funciona en mi máquina" no sirve.
  • Usa a menudo stubs y mock objects. Si el código que está siendo probado llama a un base de datos o al sistema de archivos, estas dependencias deben ser simuladas. Esta dependencias habitualmente serán abstraidas usando interfaces.
  • Revela claramente su intención. Otro desarrollador puede ver el test y comprender que se espera que haga el código de producción.

Arquitectura SOA: Los Servicios. Introducción

Definición

En una arquitectura SOA la funcionalidad de la aplicación está expuesta a través de una colección de servicios. Estos servicios son independientes y encapsulan tanto la lógica de negocio como los datos asociados.

Desde una perspectiva empresarial, los servicios son activos independientes que se corresponden con actividades comerciales reconocibles o funciones comerciales del mundo real y que son accesibles de acuerdo con las políticas que se hayan establecido para los mismo.

Desde un punto de vista técnico podemos decir que se trata de componentes autónomos de grano grueso, con interfaces bien definidas (contratos de servicio) y con una clara separación entre su interface pública y su implementación privada interna.

Los servicios interactúan entre sí a través de mensajes, con un esquema que define su formato, un contrato para definir sus intercambios y la definición de una política de cómo deben ser intercambiados.

Aplicaciones como conjunto de Servicios.

El primer paso en cualquier proyecto de SOA es identificar claramente los problemas críticos para el negocio o desafíos.

Los servicios incluirán los procesos de negocio y serán publicados para su consumo por parte de usuarios, sistemas u otros servicios.

Los servicios pueden utilizar otros servicios para cumplir sus funciones, serán en este caso servicios compuestos de otros servicios.

La creación de grandes aplicaciones será un proceso iterativo de incluir nuevos servicios y publicarlos.

En la terminología SOA componer nuevos servicios basándonos en los ya existente se llama Orquestación (Orchestration) al igual que en una orquesta iremos combinando instrumentos para realizar tareas más complejas.

La importancia del contrato

Las aplicaciones SOA publican sus servicios y no saben quien los va a usar ni donde, estando

fuera del control de la aplicación. Publican un contrato (interface) que se mantendrá constante a lo largo del ciclo de vida del servicio. El ciclo de vida de un servicio diferencia entre los servicios en producción y en desarrollo, para los servicios en producción nunca se modificará su interface sino que en su lugar el servicio se marcará como en desuso y se notificará a sus consumidores que hay una nueva versión del servicio disponible que deberán usar.

Es fundamental la separación entre la interface y la implementación. El usuario de un servicio sólo necesita (y debe) conocer la interface. La implementación puede cambiar a lo largo del tiempo sin que para ello deba afectar a sus consumidores .

Servicios Web

Como comentamos antes, un error muy común es confundir servicios, componentes que forman una arquitectura SOA, con servicios web. Los servicios web son una forma de implementar estos servicios, pero no es obligatorio que los servicios estén implementados como servicios web aunque sí es lo más común.

En nuestro próximo artículo vamos a profundizar en los servicios web como forma más habitual de implementar los servicios de una arquitectura SOA, haciendo referencia a las dos formas más habituales de servicios web (SOAP y RESTFUL) y las principales diferencias entre ellas.

Breve Introducción a SOA

Si tu conocimiento sobre SOA se limita a la realización de algunos Web Services, pero te apetece conocer un poco más en profundidad la Arquitectura Orientada a Servicios.

En éste primero voy a enumerar 5 ideas fundamentales que debes conocer sobre SOA.

  1. SOA no son webservices. Los servicios web son una forma de implementar los servicios de SOA, la más conocida e implantada, pero incluso sin webservices podríamos tener SOA siempre que tengamos una forma estándar de comunicar los servicios entre sí. Digamos que los servicios web son los árboles y SOA va sobre el bosque entero.
  2. Los servicios en SOA representan procesos de negocio. Hay una relación directa entre los procesos de negocio de una empresa y los servicios que se van a implementar en SOA, de tal manera que un proceso de negocio estará formado por la llamada a varios servicios.
  3. SOA no tiene porque ser válido para todas las organizaciones, donde realmente tiene sentido es en grandes sistemas distribuidos y heterogéneos donde el bajo acoplamiento entre los distintos componentes es el factor más importante. Si nuestra empresa no tiene componentes distribuidos y además todo está bajo la misma plataforma probablemente SOA no nos aporte nada.
  4. Implantar SOA no significa cambiar todos nuestros sistemas por un nuevo (y carísimo) software basado en SOA, uno de los principios de SOA es aprovechar los sistemas heredados, realizando servicios que se encargarán de actuar como fachada entre estos sistemas y el resto de servicios.
  5. El Gobierno SOA es un factor fundamental en una arquitectura SOA y es el encargado de velar porque se cumplan los principios de la arquitectura.

Por último algunas siglas que deberías conocer:

  • ESB: Enterprise Service Bus o bus de servicio empresarial, es el encargado de facilitar la comunicación entre los servicios y puede ofrecer muchas funcionalidades de valor añadido como alta disponibilidad, enrutamiento inteligente, orquestación de procesos, monitorización, etc.
  • BPM: Business Process Management o gestión de procesos de negocio, es complementario a SOA, como los servicios representan procesos de negocio es factible que se puedan crear nuevos procesos de negocio en base a la combinación de los servicios ya existentes, con lo que dando de alta nuestros servicios en una herramienta BPM los podemos combinar incluyendo condiciones y utilizando para ello un lenguaje específico como BPEL (Business Process Execution Language)

martes, agosto 17, 2010

No escribo pruebas unitarias porque... (manual de excusas)

Siendo alguien que vive los beneficios de hacer TDD, creo profundamente en el desarrollo guiado por pruebas. Esta práctica agrega un nuevo nivel de calidad y madurez al desarrollo de software, y sin embargo todavía no es la técnica más usada en los proyectos de software. Cuando hay que elegir entre características, tiempo y calidad, siempre sufre la calidad. No queremos agregar tiempo extra para hacer pruebas, y tampoco queremos comprometer las características que vamos a entregar. Si no se pusieron como objetivo hacer TDD al iniciar el proeycto, es dificil hacerlo después.

Todos escuchamos excusas para no hacer TDD, pero nadie las juntó mejor que "Pragmatic Unit Testing in Java With JUnit", de la serie Pragmatic Bookshelf. Hace un par de años que leí ese libro, y desde entonces creo que no hay forma que un desarrollador responsable pueda leer este libro sin entender que las pruebas unitarias son uno de los aspectos más importantes del desarrollo de software.

La excusa más preocupante que escucho es que es demasiado dificil probar mi código. Esto puede ser por dos motivos. Uno es que el código sea principalmente de interfaces de usuario (UI), y automatizar las pruebas de UI es muy dificil. Entiendo que la automatización de UI son bastantes complejas (¡y no imposibles!), pero se debería dedicar todo el esfuerzo en automatizar lo más posible: piensen en las pruebas de regresión. Si tienen una suite de pruebas completamente automatizada, incluyendo el comportamiento del UI, podrán hacer cambios al código con total confianza de no romper nada.

El segundo motivo de que el código es demasiado dificil de probar es que hicieron desastre con el diseño. Quizás la lógica y el código de UI están muy acoplados. Es por esto que TDD ayuda a mantener un diseño limpio, siguiendo las mejores prácticas. Usar JUnit es simple, y si puedo ejecutar toda la capa lógica por tener un diseño limpio, entonces podré probar toda la lógica que el UI va a usar. ¿Qué les falta el modelo de datos? Entonces pueden usar objetos mocks - ¡hay muchos frameworks para esto!

Para quienes todavía no leyeron el libro, les dejo un breve resumen de las excusas para no hacer TDD:

Escribir pruebas lleva mucho tiempo

Este es el principal motivo que dan los desarrolladores, y creo que se debe a cómo nos enseñan a desarrollar software. En general, nos hacen creer que la estapa de pruebas ocurre al final del proceso, y no durante todo el desarrollo.

TDD fomenta el modelo "pagar a medida que se avanza", en donde escribimos las pruebas mientras desarrollamos, por lo que no tenemos que meter tiempo al final del proceso para escribir todas las pruebas que podamos.

Y de todas formas, si no estás escribiendo pruebas a medida que avanzás, ¿cómo comprobás que el código se comporte como esperás? ¿Lo ejecutás manualmente? ¿No tiene más sentido invertir algo de este tiempo de pruebas manuales en escribir una prueba JUnit para esto? Quiero decir, en algún momento vas a tener que ejecutar esa porción de código - no va a quedar sin tocar el resto de la vida del producto.

De hecho, ocurren muchas más penalizaciones de tiempo si no se escriben pruebas unitarias. Vas a tener que gastar tiempo haciendo debug del código intentando averiguar porque algo no funciona. O vas a hacer un refactor, y luego darte cuenta que nada funciona como antes del refactor. Si tuvieras las pruebas unitarias, tendrías una base segura.

Lleva mucho tiempo ejecutar las pruebas

Si, puede llevarse bastante tiempo ejecutar pruebas que involucran a entidades externas, o pruebas de la interfaz de usuario. Pero se supone que hay más de un nivel de pruebas. Las pruebas unitarias deberían ejecutarse rápido, y podría haber un nivel de integración que también corra sin mucho impacto de tiempo. Si hay pruebas de integración que toman mucho tiempo, será cuestión de correrlas con menos frecuencia - quizás de manera nocturna. Esto no quiere decir que debemos ignorar las pruebas unitarias. Estas siempre deberían correr lo suficientemente ráipdo como para ser parte natural del proceso de software.

Mi trabajo no es probar el código

Todavía no sé en qué momento un desarrollador de software decide que puede tirar código contra la pared así nomás. Si nuestro trabajo fuera de "Codificador" quizás ahí tendríamos una mejor excusa. Pero nuestro trabajo consiste en desarrollar código que funcione, y por lo tanto necesitamos alguna forma de mostrar que nuestro código es funcional. Si a la gente de QA les cuesta encontrar bugs en nuestro código, va a ser maravilloso para nuestra reputación.

En realidad no sé cómo funciona el código, por lo que no puedo probarlo

Esta es dificil de tomar sin ser incrédulos. Si no entendemos cómo debería funcionar el código, no deberíamos empezar a programar. Primero debemos entender el requerimiento.

El libro tiene un par de excusas más, pero estos son las principales. ¿Qué excusas escucharon ustedes para no escribir pruebas?

Fuente: DosIdeas

viernes, junio 04, 2010

Consejos y sugerencias para tu primer iteración

Empezar a trabajar por iteraciones puede ser un cambio muy grande (¡y que asusta!) cuando llevamos mucho tiempo desarrollando con otros métodos. Scrum dice cómo llevar adelante el proceso, pero a muy alto nivel. En este artículo, Jared Richardson comparte varios consejos para un equipo que recién comienza a formarse en Scrum, y está a punto de empezar su primera iteración.

No sobre-analicen todo. No importa si no saben exactamente cuánto les va a llevar hacer algo, o cómo van a escribir pruebas unitarias perfectas, o cómo van a manejar los datos para las pruebas X, Y, Z. Simplemente, empiecen a hacer. Tomen una serie de tareas pequeñas y empiecen. Lo mejor de tener iteraciones cortas es que tienen la próxima semana van a poder cambiar sus expectativas!

No se vuelvan locos pensando quién será el Scrum Master. De hecho, hagan que este rol rote en todo el equipo. Al principio, cada miembro del equipo tiene que ser Scrum Master por una iteración antes de volver a ser Scrum Master por segunda vez.

Aprendan la votación con cinco dedos. El equipo entero vota cualquier sugerencia que alguien hace. Un dedo significa que odio esa sugerencia y no puedo aceptarla. Cinco dedos significa que me encanta totalmente. Los dedos en medio reflejan distintos niveles de aceptación. Tres dedos muestran que nos resulta indiferente. Buscamos soluciones que junten respuesta de "Me encanta" o "Puedo aceptarlo". Ninguna de las sugerencias son permanentes; en cambio, usaremos experimentos de entre una y tres iteraciones. Siéntanse libres de probar cosas nuevas, y dejar que otros prueben cosas nuevas. No va a durar por siempre, y los buenos equipos eliminan las prácticas que no funcionan.

Tengan reuniones diarias cortas. El Scrum Master las lidera. Usen algún token sencilla (una lapicera, una pelotita) que se pasa entre los miembros. Si lo tienen, pueden hablar. Sino el resto del equipo puede callarnos por no hablar en nuestro turno (¡y hasta puede resultar divertido!). Debemos asegurarnos que cada persona responda las 3 preguntas: ¿Qué hiciste ayer? ¿Qué vas a hacer hoy? ¿Qué problemas tenés?

Usar integración continua para la compilación (¡como mínimo!). Si no tienen builds automáticos, o un servidor de integración continua, usen una "iteración cero" para configurar esta infraestructura. No dejen de hacerlo, los beneficios para el equipo son enormes y es una de los pasos más importantes.

Sólo trabajen en requerimientos estimados rápidamente entre uno y tres días. ¿Tienen una tarea de 6 semanas? Hay que dividirla en piezas más manejables.

Armen un equipo con desarrolladores y testers. Trabajen de a pares cuando escriban pruebas (¡ambos!). Los desarrolladores van a aprender a escribir mejores pruebas, y también los testers.

Tengan una reunión de planificación. El Dueño del Producto, el líder del producto (o quien cumpla con este rol) trae suficiente trabajo para una o dos iteraciones. Rechacen una tarjeta cuando no se pueden poner de acuerdo sobre qué significa la característica, o cómo se prueba que dicha característica. Hagan que el Dueño del Producto tenga la idea más en claro y traiga la tarjeta en una iteración futura.

Todo el trabajo se realiza tiene que realizarse con dos pares de ojos. Pueden lograrlo trabajando de a pares, o con revisiones de compañeros, pero nadie trabaja solo. Esto es tanto para la calidad de código como para compartir el conocimiento (por cierto, si piensan que sus compañeros no son lo suficientemente inteligentes para "entender" nuestro trabajo, el problema es nuestro. Siempre es nuestro. No sean ese tipo de desarrollador).

Agenden una demostración para mostrarle a los demás lo que hicieron durante la iteración. Es una oportunidad para mostrarnos, y dejar que otras partes de la empresa sepan lo que viene.

Por último, relájense. Los miembros del equipo que se viven preocupando con "¿Y qué pasaría si...? ¿Y qué pasa con...? ¿¿Y eso otro?? ¡¡¡Y que vamos a hacer si ocurre aquello!!!"... estos miembros son los que terminan haciendo menos. Simplemente empiecen a trabajar con equipo, y ajusten las iteraciones. Estoy seguro que no sólo lo van a encontrar muy productivo, sino sumamente divertido.

Fuente

lunes, mayo 17, 2010

Cumplir con la retrospectiva

Si alguna vez trataron de cambiar algún hábito personal (como comerse las uñas, por ejemplo) saben que es virtualmente imposible de lograrlo a menos que tengan algo para reemplazar el hábito viejo. Es más fácil adoptar un comportamiento nuevo que extinguir uno viejo. Lo mismo ocurre para los equipos en las organizaciones.

En su retrospectiva, el equipo de Lynn decidió dejar de empezar a codificar sin tener un plan. Pero en la siguiente reunión de planificación de la iteración, dos miembros del equipo abrieron sus notebooks para compartir código en el que habían trabajado durante el fin de semana. Creían que le estaban dando una ventaja al equipo.

Lynn les recordó a todos el acuerdo y compartió varias ideas para planificar que había leído en grupos de discusión Ágiles. El equipo acordó actuar de acuerdo a lo decidido y probar las ideas de Lynn para la planificación. A medida que el equipo empezó a hablar sobre el trabajo que debía hacerse, el equipo se dió cuenta que el código escrito durante el fin de semana no contribuía al objetivo de la iteración - fue un esfuerzo en vano.

Sin un reemplazo (como estas ideas para planificar), el equipo no tuvo más alternativa que caer en su comportamiento anterior.

Todos los comportamientos nuevos resultan extraños al principio. Las personas desarrollan tranquilidad con la práctica - sea tanto al aprender un nuevo saque de tenis como aprender a escribir código en un nuevo lenguaje. Debemos brindar apoyo y recordar que está bien cometer errores mientras se aprenden nuevas habilidades.

Brindar apoyo

El trabajo de provocar un cambio no termina con el cierre de la retrospectiva. Incluso los cambios más pequeños necesitan ser cuidados y apoyados. El apoyo proviene de diferentes formas: refuerzos, empatía, oportunidades de aprendizaje, oportunidades de práctica, y recordatorios. Algunos tipos de apoyo provienen del equipo (como la empatía y los recordatorios). Otros requieren de recursos y presupuesto externos. Los líderes de equipos, coaches y gerentes tienen la responsabilidad de obtener el apoyo que requiera de gastos.

Refuerzos

El cambio es difícil. Debemos apoyar al equipo (y a nosotros mismos) haciendo notar el avance. Demos frases de aliento sobre lo que estamos haciendo bien.

Debemos brindar información sobre lo que va bien para que el equipo pueda ver que están avanzando. Demos feedback que describa el comportamiento y destaque el impacto: "Noté que ayer no nos fuimos de tema en la reunión diaria. Acordamos sólo responder las preguntas del scrum diario, y eso hicimos. Nos ayudó a ver cuáles eran los obstáculos".

Empatía

Es válido que las personas sientan frustración o pérdida por el cambio. Veamos como Fred manejó mal la situación cuando un miembro del equipo le habló sobre los cambios. Fred escuchó a Katie explicar cómo se sentía sobre tener que dejar su cubículo personal cuando el equipo se ubicó en un espacio abierto. "Estuve pensando lo que me contaste", le dijo Fred, "y no hay ningún motivo para que te sientas así". ¡Eso no es empatía! Debemos respetar los puntos de vista de las otras personas, aunque no los compartamos. A veces un simple "Te escucho" es suficiente.

Oportunidades de aprendizaje

Debemos apoyar la exploración y el aprendizaje, y demostrarlo. Es posible que el equipo necesite aprender nuevas habilidades para tener éxito en los experimentos que eligieron para su plan de acción. Se pueden organizar almuerzos y sesiones para que los miembros aprendan entre ellos. Se pueden dar listas de recursos web y artículos para que el equipo investigue ideas nuevas. La programación de a pares ayuda a aprender nuevos lenguajes y técnicas. Y se puede hacer todo esto sin un presupuesto.

También debemos estar dispuestos en gastar dinero para apoyar un cambio. No todas las habilidades se pueden aprender desde un sitio web o leyendo un artículo. Invirtamos en capacitación para construir las bases de nuevas habilidades. Armemos una biblioteca de referencia para que el equipo pueda consultarla.

Oportunidades de práctica

Las personas necesitan practicar para ganar experiencia. Una forma es dejar al equipo con el proyecto para que prueben algo nuevo. Otra opción es crear un espacio formal de práctica usando algún proyecto pequeño, un área de práctica, o un programa tipo Hola Mundo.

Los proyectos cortos -uno que dure dos días, o incluso menos- sirven para explorar posibles soluciones y probar métodos nuevos. El límite de tiempo en los proyectos cortos crea un punto de verificación explícito en donde el equipo puede comprobar su aprendizaje y las decisiones en el experimento.

Las áreas de práctica son un lugar donde el equipo puede cosas nuevas sin afectar al producto real. Un área de práctica puede ser un área especial de desarrollo o prueba que no se utiliza para el desarrollo actual del producto.

Alentemos a que el equipo prueba programas del tipo Hola Mundo. Los programas Hola Mundo son muy simples (en general sólo muestran el mensaje "Hola, Mundo"), pero sirven para probar entornos de desarrollo, configuraciones y encontrar problemas rápido (o confirmar que algún concepto básico funciona).

Recordatorios

Los tableros grandes y visibles y los check-in son recordatorios que ayudan a que el equipo se enfoque en los cambios. Por ejemplo, el equipo de Terry decidió que necesitaban realizar refactors más seguido. Crearon un tablero grande donde cada miembro agregaba un punto verde cuando terminaban una tarea de refactor. Al final de cada día, revisaban el gráfico y discutían los resultados.

Un check-in le permite al equipo informar lo que están haciendo con un cambio en particular. Debemos mantener preguntas y respuestas cortas: "En una o dos palabras, ¿cómo estamos con las estimaciones?". Las respuestas nos pueden ayudar a saber cómo está avanzando el cambio.

Fuente

viernes, mayo 07, 2010

¿Inteligente o Tonto?

¿Cuál es la diferencia entre ser inteligente o ser tonto? Creo que podría resumirse en dos cosas: qué tan lejos en el futuro podés pensar, y qué tan rápido podés generar este pensamiento. Cuando alguien juega ajedrez, o poker, sus habilidades están determinadas por cuántas movidas puede pensar por adelantado. Cuánta historia pueden recordar, y así planificar el siguiente movimiento.

En el desarrollo de software, ¿qué tan lejos podés mirar? ¿Estás usando prácticas destructivas porque estás muy ocupado "terminando el trabajo"? ¿Estás ignorando buenas prácticas que podrían ahorrarte tiempo?

Podemos relacionarlo con armar un camino que atraviese un bosque. Estás trabajando muy, muy duro. Todos en el equipo están transpirando, astillándose las manos, todo el tiempo. No se puede cuestionar la lealtad ni dedicación de nadie.

Pero...

¿Cuándo fue la última vez que detuviste esta tala de árboles metafórica, te subiste a un árbol... o miraste el mapa... o afilaste el hacha? El problema con la mayoría de los equipos de software que talan árboles en el bosque es que no comprueban si el camino que están armando está dirigido hacia la ciudad correspondiente. No comprueban si es un camino recto. No analizan si podrían comprar algunas sierras eléctricas para reemplazar a las hachas obsoletas que vienen usando.

Por supuesto que esto también puede abusarse. No queremos pasar todo el día en el negocio buscando herramientas nuevas, pero de vez en cuando necesitamos mirar los alrededores, ver si seguimos en línea recta. Debemos asegurarnos de estar usando las herramientas correctas para el trabajo. Comprobar si siguen afiladas las hojas.

Les dejo algunas sugerencias como herramientas para asegurarnos que seguimos en el camino correcto.

  • Integración Continua. Hay muchas herramientas de Integración Continua que ayudan muchísimo al equipo. Hace que el equipo siga escribiendo código en vez de arreglar compilaciones, mantiene limpio al producto, y encuentra problemas rápido.
  • Demos frecuentes. Tanto si son internas o para el cliente, estas demostraciones públicas ayudan a entender lo que estamos haciendo, y nos sugiere correciones al curso. Si estamos cortando el camino en la dirección incorrecta, ¿cuánto tiempo queremos seguir perdiendo? Debemos mostrar lo que hacemos, y averiguar lo que piensan lo antes posible.
  • Iteraciones de duración fija. Las iteraciones acotadas brindan una forma más efectiva de enfocar los esfuerzos y asegurarse de estar construyendo el software adecuado.
  • Pruebas automatizadas. Cuando codificamos nuestro conocimiento del producto en una prueba automatizada (que se ejecuta en un servidor de integración continua), se hace imposible que alguien del equipo rompa el código sin que se descubra rápidamente.
  • Pruebas guiadas por los defectos. ¿Encontraste un bug? Agregá una prueba. Siempre. Esta perspectiva extreme a la automatización de pruebas nos brinda cobertura justo en donde era necesaria. También, no agregues una sola prueba... buscá armar escenarios derivados de la situación.
  • Desarrollo guiado por pruebas. Escribir una prueba antes de escribir el código productivo hace que surja un código completamente diferente. Es más pequeño, más enfocado y (¡sorpresa!) está probado. TDD es un camino de ida... ¡probalo!
  • Reuniones diarias de parado. Estas reuniones diarias y breves hacen que todos hablen y se vean la cara, todos los días. Se responden 3 preguntas que ayudan a compartir información. ¿Cuántos equipos conocen que no se hablan a diario?
Fuente