martes, 25 de enero de 2011

Vida de Programador I - Como explicar agiles a los Gerentes

El problema es justamente ese: Como explicamos lo que hacemos al Gran-Jefe-Quiero-Que-Cumplan-con-La-Fecha?.

Estas un día tranquilo en tu cubículo, esperando mientras la máquina cachaza que te dieron arranque y levante el IDE superperfomante gratuito que te bajaste por izquierda, cuando recibís la siguiente llamada:

"Juancito, te llama el Gran-Jefe-Quiero-Que-Cumplan-con-La-Fecha, que quiere hablar con vos, pasa a su oficina."

Con una cierta inquietud en tus entrañas te vas para la oficina como quien camina sobre piedras descalzo. Te vas pensando de que vendrá el tema, si tu cv está actualizado en Linkedin o si te sera posible pagar la siguiente cuota del televisor LCD sin trabajo. En síntesis, vida del programador que le dicen.

"Pero Si, hombre, como andas?, pasa pasa, siéntate en esa silla", dice, señalandote una sillita de juguete, bajita, mientras se apoya en el Gran-sillón-De-Cuero-2-metros-de-Alto, para preguntarte:

"Hombre, que te he llamao porque un Gerente amigo, cuando estaba jugando al Golf, me ha hablado de no se que rollo de unas metodologías ágiles, escram(sic) o cosillas por el estilo, no se bien. Creo que hablaba de algo así como focalizarse en la entrega al usuario, en lo que quiere, que el cambio es un rollo normal y no recuerdo pero algo sobre la importancia de las personas por sobre no se que coño."

"Punto numero 1:", pensas, "Este cabron no sabe ni como me llamo". "Punto numero 2: Dios no existe, mierda."

"En sintesis, joder, que me gustaría que me explicaras este follón, porque me ha picao el bichito de la curiosidad, no sea que puedo salir en la gran magasine "MANAGEMENTO" y me estoy perdiendo una oportunidad de la Ostia!!."

"Es definitivo", seguis pensando mientras lo miras con cara de sesudo, "Si, Dios existe pero es un sádico o bien, en la reencarnación anterior debo haber sido muy mala persona....".

Pero bueno... repitiendote pavadas como "en la cancha se ven los pingos" (hmm pero no soy caballo ni galgo)... o "los cobardes no hacen historia" (pero todos murieron de viejo)... te pones a pensar como explicarle al Gran-Jefe-plin plin plin, lo que te pide....

Como explicar que la calidad si importa. Que no hacerlo bien es justamente no llegar a tiempo porque los intereses de la deuda tecnica te comerán vivo como si tu acreedor fuera la mafia misma (bah o algún banco...) .

Piensa piensa piensa...

Del PMI y Waterfall a Scrum

La diferencia fundamental que uno ve al pasar de trabajar de la manera tradicional PMI-Waterfallistica a Scrum es que uno se va chequeando durante el proyecto que esta construyendo lo que el usuario quiere.

El gran problema con la manera "tradicional" es que la forma en que plantea encarar los proyectos es, engañosamente, muy razonable y atractiva: Hagamos un proyecto dividiéndolo en etapas bien marcadas adonde en cada etapa nos aseguramos de hacer bien una y solo una tarea. Hagamoslo en cascada de manera que la actividad de la etapa siguiente se apoye en lo que se hizo en la etapa anterior, como construir un puente, que joder, relevamos, armamos una maqueta, los planos y a construir, todo muy ingenieril, si, si. Pero si hasta parece una receta, un poquito de harina por acá, levadura por allá, 10 minutitos de horno y Voila! la Torta del proyecto esta cocinada, no? No.

Comienzo de un proyecto a-la-tradicional

Es la primera etapa, Gran Relevamiento, el primer paso de la Receta Torta-A-la-Waterfall: Tomémonos todito TOODO el tiempo necesario para entender lo que quiere el usuario, hagamos casos de usos, diagramas de realización, armamos minutas de reunion de todo lo que se hablo en infinidad de reuniones con los usuarios, hagamos prototipos, maquetas, y documentemos en un gran Documento de documentación (valga la redundancia) hasta el más mínimo detalle de lo que el usuario quiere, no sea cosa que después nos pida algo que no mencionó antes. Y si se olvidó de algo...., jah! al banquillo de los acusados!

Tipica reunion de Relevamiento

El funcional, canchero, pregunta:
"Che, A ver, es esta pantalla, en el menu 48, item 256, fijate en el caso de USO de UML2, en Rational: Agregando informacion a la solicitud XRF-3456, te parece que si queres especificar la lista de boxitracios te pongamos un listbox sincronizado con este checkbox o lo hacemos igual que la lista de parafernoles que te mostramos en la maqueta del caso de Uso UJ323 hace 8 días? ".

El usuario nos mira con una sonrisa tímida y balbucea alguna respuesta al azar mientras piensa:
"Merda!, que catzo estará diciendo este tipo por dios?! porque no pueden hablar en castellano?. No voy a decir que "si" ni en pedo, no se a que me estoy comprometiendo."

Despues de eso deberias explicarle al Gran-Jefe-Quiero-Que-Cumplan-con-La-Fecha:

Que ventaja tenemos si usamos Scrum o alguna otra metodología ágil?

El beneficio mas importante de aplicar una metodología ágil en un proyecto es que nos permite instalar dentro del grupo una forma de trabajar en la cual es mucho mas probable que logremos entender y desarrollar el sistema que el usuario realmente necesita. El secreto es simple: Feedback Feedback y mas Feedback.
Feedback constante durante muchas iteraciones para mostrarle una y otra vez lo que entendimos que el usuario pidió y corregir una y otra vez el rumbo en base a su revisión.

Agiles es más que feedback constante y un proceso de mejora iterativa

Claro, el tema es que vamos a pemitir que el usuario en cada iteración nos diga en que difiere lo que hicimos de lo que ahora ve que El necesita. Notar el "ahora", porque es justamente cuando lo ve funcionando que se da cuenta que lo que pidio no es exactamente lo que necesita. O bien, se da cuenta que puede accederlo de alguna manera distinta o entiende lo que le dijimos cuando le deciamos que probablemente la pantalla se vea un poco...saturada de informacion, es decir, confusa.

Y, como vamos a permitir eso; perdón, no solo a permitirlo, como vamos a alentar para que lo hagan, TENEMOS QUE poder cambiar el software, cambiarlo a veces de una manera radical, rapida . Cambiarlo, generalmente, de una forma no prevista en el momento de hacerlo.

Por eso, para que esto sea posible, en un tiempo razonable y que no genere un código fuente inmantenible es que se necesita desarrollar código de calidad.Y para ello se necesitan buenas prácticas de desarrollo.

Cuales? y bueno, por lo menos una malla de seguridad de tests de unidad con un cubrimiento alto del código del proyecto, si es posible hacer TDD, aplicar refactoring constantemente para mantener la calidad y no generar deuda técnica, integración continua, aplicar diseño incremental y evolutivo, técnicas de programación de a pares, Tests de aceptación....etc...

Con tu metabolismo acelerado pensastes todo esto en una fracción de un segundo. Tu jefe, el Gran-Jefe-plin plin plin esta esperando la respuesta, repechado en su Gran-Sillon, te mira desde las alturas y ya se impacienta.

Pensas todo lo que tenes que decirle, pensas en lo difícil que es que lo entienda porque no sabe del tema ni por lejos, de como inventar metáforas simples y futboleras, de lo peligroso que lo malinterprete, sopesas pros y contras, hasta que llegas a la única conclusión lógica posible...

"Pues entonces Juancito? "

"Entonces nada Gran Jefe, son unas metodologias de desarrollo poco serias, chorradas no importantes para un gran Jefe como usted, el camino mas serio e importante es seguir el pinbuk del Gran Libro del Management, PMI, el curso que hizo usted durante 2 años, jefe, ese que le salio lo que yo gano en 5 años. "

"Pero, estas seguro ? mi amigo parecía al tanto de que esto era poco menos que un filón de oro."

"Seguro, Jefe, fijese que tiene nombres raros como Scrum, Extreme Programming, tests de unidad, diseño emergente, metaforas, People over Process" y cosas así, suenan poco serio, no?

En lontananza se escucha el canto de un gallo...

martes, 11 de enero de 2011

Como y porqué de las excepciones

Las excepciones fueron uno de los grandes avances de los lenguajes de programación modernos (y somos concientes de que al llamar modernos a lenguajes como Java o C++ se nos están cayendo varias sotas...).

Antes, cuando programábamos en C, nuestro código tenía esta pinta (ejemplo tomado del brillante "The Pragmatic Programmer" ).


    retcode = OK;
    if (socket.read(name) != OK) {
      retcode = BAD_READ;
    }
    else {
      processName(name);
      if (socket.read(address) != OK) {
        retcode = BAD_READ;
      }
      else {
        processAddress(address);
        if (socket.read(telNo) != OK) {
          retcode = BAD_READ;
        }
        else {
          // etc, etc...
        }
      }
    }
    return retcode;

Mientras que con excepciones podemos hacer


    retcode = OK;
    try {
      socket.read(name);
      process(name);
      socket.read(address);
      processAddress(address);
      socket.read(telNo);
      // etc, etc...
    }
    catch (IOException e) {
      retcode = BAD_READ;
      Logger.log("Error reading individual: " + e.getMessage());
    }
    return retcode;

Con lo cual es claro que las excepciones nos ayudan a escribir mucho mejor código. Sin embargo hay muchas situaciones donde no son la mejor solución y deben ser evitadas. Veamos el siguiente ejemplo

 try {
  f = Float.parse(userInput);
 } catch(MalformedFloat e) {
  f = defaultValue;
 }

En este caso, estamos aprovechando que el metodo parse dispara una excepción cuando le pasamos valores incorrectos para continuar con el procesamiento en el handler de esta excepción. Y estamos usando excepciones para manejar un caso no excepcional: los usuarios suelen equivocarse en el input. El problema es que las excepciones disparan un salto de control bastante parecido a un goto (cuando se produce una excepción se salta del contexto actual hacia otro contexto, probablemente en otra clase y con varias ejecuciones de bloques finally entre medio). El código que depende de excepciones para el manejo de situaciones normales suele tener el mismo tipo de problemas que el código que usa gotos.

Una alternativa sería escribir el mismo código de la siguiente manera:

 if(Float.canParse(userInput)) {
  f = Float.parse(userInput);
 } catch(MalformedFloat e) {
  f = defaultValue;
 }

Para hacer esto dependemos de que la clase Float nos brinde la posibilidad de chequear el input antes de usarlo, lo que nos da un buen consejo para cuando diseñamos nuestras propias clases: siempre ofrecer maneras de verificar que no se deberían producir excepciones.

Por supuesto, si la operación que dispara la excepción es muy costosa o es destructiva, nos veremos forzados a usar la primera alternativa.