Taller: Explorando heurísticas para TDD

Este es el taller que estaré facilitando la semana próxima en el contexto de Agile Brazil. Pero dado que es un taller nuevo (nunca antes lo hice) y que en el contexto de la conferencia lo realizaré en inglés, tengo intenciones hacer una corrida previa, a modo de prueba, en castellano y sin co$to, el martes próximo (5/10) a las 19.00 (GMT-3).

Les comparto aquí una breve descripción del taller.

Test-Driven Development es una de las prácticas más populares de Agile pero es al mismo tiempo una de las prácticas más difíciles. Incluso cuando la idea central TDD es fácil de entender, puede resultar verdaderamente duro de aplicar en escenarios no triviales. Entre los factores determinantes para un exitosa y cálida experiencia de TDD está la secuencia de tests que vamos eligiendo para guiar nuestro desarrollo. En este taller con modalidad «hands-on» exploraremos diversas heurísticas para un uso efectivo de TDD.

Personalmente he visto muchos programadores tratando de aplicar TDD y fallando una y otra vez. Yo mismo fallé la primera vez que intenté aplicarlo en un proyecto de industria allá por 2005. Aprendí de esa experiencia fallida, estudié, leí mucho y volví a intentarlo. Hoy en día llevo más de 10 años practicando y enseñando TDD. Estas experiencias y descubrimientos son las compartiré en este taller.

Durante el taller yo trabajaré con Java, Git e Intellij pero los participantes pueden trabajar con el stack de herramientas que gusten.

Los interesados en participar pueden contactarme aquí.

Importante: este taller está dirigido a gente que ya conoce TDD y que tiene experiencia práctica en el uso de TDD.

El riesgoso mensaje de los afortunados de sistemas

De vez en cuando veo en redes mensajes de gente que trabaja en sistemas con una onda:

No hace falta estudiar para trabajar en sistemas, yo soy Senior Lead Developer y nunca pisé la universidad.

Es cierto que hay mucha gente trabajando en sistemas sin haber estudiado formalmente una carrera de sistemas, pero de ahí a que cualquiera puede llegar a trabajar en toda/cualquier posición creo que hay una diferencia diferencia. Personalmente creo que una de las cuestiones que da un estudio formal es que habilita más oportunidades por el simple hecho de que hay empresas que valoran la educación formal a punto tal que para acceder a ciertas posición ponen como condición necesaria tener un título universitario.

Por otro lado creo que poner casos particulares como ejemplos puede ser contraproducente. El hecho de que «Pepito» haya logrado llegar a tal o cual posición sin tener un estudio formal no implica que el individuo promedio pueda hacer lo mismo. Tal vez «Pepito» tuvo un contexto, una suma de situaciones personales que derivaron en su éxito. Ojo, no estoy diciendo que sea todo simple consecuencia del destino, sino que tal vez «Pepita» aprendió a programar en la secundaria y tal vez tenia facilidad con el inglés y tal vez un tio le regaló una computadora. En fin, nada de otro mundo, pero son pequeñas cuestiones que en la suma pueden marcar la diferencia.

Conclusión:

Me parece excelente motivar a la gente para que trabaje en sistemas, «desmistificando» algunas cuestiones que muchos ven como una traba, pero creo que es fundamental hacerlo cuidando mucho el mensaje para no generar falsas expectativas y frustración.

Sobre la definición del Trabajo final de carrera

En las últimas semanas he recibido varias consultas sobre trabajos finales de carrera en FIUBA. Más allá de siempre recomendar dejar en claro el objetivo personal del trabajo, en estas ocasiones me encontré recurrentemente explicando una cuestión sobre la definición del trabajo y la presentación del proyecto. Lo escribo aquí para futuras referencias.

El primer paso formal del trabajo final de carrera es la presentación del plan de proyecto a la comisión curricular para su aprobación. Este un paso clave, y que a mi entender, en ocasiones subestimado. Si nos quedamos cortos en el nivel de detalle del plan de proyecto, corremos el riesgos que la comisión curricular no apruebe el proyecto. Al mismo tiempo si ponemos mucho nivel detalle sin tener suficiente conocimiento del dominio, la tecnología y el contexto, corremos el riesgos de estar embarcándonos en un trabajo mucho más extenso de lo esperado.

Entonces he aquí la clave: la formulación del plan de proyecto debe proveer el suficiente nivel detalle para que la comisión lo apruebe, pero para proveer ese nivel de detalle es necesario que tengamos suficiente conocimiento del dominio del proyecto, la tecnología que utilizaremos para la solución y el contexto del proyecto. Esta situación tiene distinto grado de «gravedad» en cada carrera/institución. En algunos casos no se pide tanto nivel de detalle en el plan de proyecto porque se espera que el proyecto incluya el esfuerzo de descubrimiento/análisis/requerimientos. Del mismo modo, en los casos en los que se pide mayor nivel de detalle se está, en cierto modo, forzando que al menos una parte importante del descubrimiento/análisis se realice previo/durante a la formulación del proyecto.

Si quisiéramos poner esto en términos formales (o de industria) podríamos pensar estas dos situaciones: en un extremo en una planificación adaptativa y en el otro en una planificación «up-front». Al mismo tiempo si analizamos los trabajos finales desde una perspectiva de gestión de proyectos tenemos que generalmente los reglamentos establecen de forma fija los recursos/esfuerzo/presupuesto del proyecto (cada alumno debe trabajar X cantidad de horas como mínimo). También se establece un tiempo calendario máximo para completar el proyecto una vez aprobada la propuesta (por ejemplo 1 año calendario). De esta forma la dimensión variable del proyecto termina siendo el alcance y ahí la paradoja: en un planificación «up-front» muchas veces los alumnos (y también las empresas) intentan fijar un alcance, teniendo así las tres dimensiones del proyecto fijas de entrada: alcance, tiempo y recursos. Típico proyecto «llave en mano» con las ¿pocas? chances de que el proyecto llegue a buen puerto. Es así que nos encontramos con alumnos haciendo interminables trabajos finales y algunos otros que nunca siquiera lo empiezan.

La clave entonces podría estar en plantear un alcance variable, lo cual a mi parecer va mucho mejor con una planificación adaptativa que con una planificación «up-front».

En términos formales, y dependiendo de las particularidades de la comisión curricular (o el organismo que sea que deba aprobar el plan de proyecto), puede que la mayor parte descubrimiento/análisis debamos hacerla antes o después de la aprobación del plan de proyecto. En base a lo que he hablado informalmente con miembros de las comisiones curriculares de FIUBA me queda la sensación de que en el caso de la Ingeniería el descubrimiento/análisis hay que hacerlo en su mayor parte antes de la presentación del plan de proyecto. En el caso de la Licenciatura el descubrimiento/análisis es en su mayor parte realizado una vez aprobado el plan de proyecto.

En este sentido, mi recomendación para los alumnos de Ingeniería en Informática es:

  • Conseguir un director y comenzar a trabajar
  • Presentar la propuesta formal una vez avanzando un porcentaje de ~30% del proyecto
  • Obviamente esta estrategia tiene el riesgo de avanzar en el trabajo y que luego la comisión no apruebe el plan de proyecto. Justamente es aquí donde resulta clave el rol del director para minimizar la chances de que el proyecto sea rechazado.

Continuous Delivery: Scripting para balanceador F5

F5 es una empresa que provee un conjunto de productos relacionados a networking: firewall, balanceador, etc. Es común encontrarse con balanceador F5 en ambientes productivos de alta carga para repartir carga entre varios nodos.

Al mismo tiempo, en aplicaciones de cierta criticidad, es común que las actualizaciones se hagan siguiendo alguna estrategia tipo «canary», esto es:

  • «Se saca» un nodo del balanceador
  • Se le instala la nueva versión de la aplicación
  • Se verifica que la aplicación funcione correctamente
  • «Se restaura» el nodo en el balanceador
  • Se repite el proceso con cada uno de los restantes nodos

Cuando pretendemos trabajar en un esquema de continuous delivery es imprescindible que este proceso se haga de forma automatizada y para ello es necesario poder interactuar con balanceador programáticamente.

Dicho esto, he aquí un fragmento de código Python para interactuar un F5 Big-IP:

# este script depende de varias variables:
# * f5_login_url (url del balanceador para obtener el token)
# * f5_user (usuario de f5 para obtener el api token)
# * f5_pass (password de f5 para obtener el api token)
# * f5_self_service_url (url de la api del balanceador)
# * node_name (nombre del nodo sobre el que queremos operar)
# * node_id (id del nodo sobre el que queremos operar)
# * pool_id (id del pool del balanceador en el que está el nodo)


import requests
import json
import sys

# primero hay que loguearse y obtener un token
login_request = '{ "username":' + f5_user + ', "password":' + f5_pass }'
response = requests.post(f5_login_url, login_request)
if response.status_code == 200:
  response_json = json.loads(response.text)
  token = response_json["token"]["token"]
else:
  token = {}
  print('No pudo obtener token', file=sys.stderr)
  exit(1)

# sacamos el nodo
headers = { 'X-F5-Auth-Token': token }
disable_request = '{"name":"Self-Service_' + node_name + '", "resourceReference":{' \
  + '"link":"https://localhost/mgmt/cm/adc-core/working-config/ltm/pool/' + pool_id \
  + '/members/' + node_id + '"},"operation":"force-offline"}'
response = requests.post(f5_self_service_url, data=disable_request, headers=headers)

# restauramos el nodo
enable_request = '{"name":"Self-Service_' + node_name + '", "resourceReference":{' \
  + '"link":"https://localhost/mgmt/cm/adc-core/working-config/ltm/pool/' + pool_id \
  + '/members/' + node_id + '"},"operation":"enable"}'
response = requests.post(f5_self_service_url, data=disable_request, headers=headers)

Espero les resulte útil.

Situaciones de Diseño #1

Hace tiempo venia con la idea de publicar una serie de videos sobre diversas técnicas/patrones/recomendaciones para lidiar con situaciones de diseño habituales. Finalmente ayer decidí poner manos a la obra y publiqué el primer video de esta serie.

La situación que aborda este primer video es cómo lidiar con lógica que depende de fechas de una forma testeable. Muchas veces cuando tenemos lógica que depende de la fecha actual, estamos tentados de utilizar directamente una llamada al componente nativo de fecha. El problema con este camino es que no resulta testeable. La clave está en encapsular el acceso a la fecha del sistema de manera tal de poner utilizar un doble de prueba (mock) en el momento de hacer nuestra pruebas automatizadas.

Les dejo aquí el video y los invito a que me dejen en los comentarios alguna otra situación que les gustaría que aborde en próximos videos.

RubyMine con Docker

En la actualidad es cada vez más habitual utilizar Docker como ambiente de desarrollo, o sea: en lugar de instalar el runtime de desarrollo en nuestro host, armamos una imagen Docker con el runtime del proyecto conteniendo también todas dependencias/libs y en nuestro host instalamos tanto solo Docker Desktop y el IDE de nuestra elección.

Esta estrategia resulta especialmente útil en stacks como Ruby donde es habitual tener que utilizar distintas versiones Ruby. Sin embargo cuando pretendemos utilizar IDEs más potentes como RubyMine, que proveen algunas funcionalidades que dependen del runtime (como es el caso de algunos refactorings), es necesario hacer algunos ajustes de configuración en el IDE. Es por ello que grabe un video explicando estos ajustes. Espero les resulte útil.