Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 4: Escuchando a los tests.

En esta cuarta parte del libro Nat y Steve nos cuentan que el código de los tests debe ser cuidado tanto como el código de producción. A lo largo de este post voy a resumir solo la parte de «Escuchando a los tests» ya que creo que se merece dedicarle un post entero.

Normalmente, cuando encontramos una nueva funcionalidad que es difícil de testear existe una razón detrás de ello. Si aprendemos a escuchar a los tests conseguiremos simplificarlos y a su vez mejorar el diseño de nuestra aplicación.

Sigue leyendo «Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 4: Escuchando a los tests.»

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 3: Desarrollando un ejemplo.

En la tercera parte del GOOS los amigos Nat Pryce y Steve Freeman nos cuentan como construyen una aplicación que permite automáticamente pujar online en subastas. Ellos empiezan a escribir la aplicación partiendo desde la iteración 0, mediante pequeños incrementos de funcionalidad y TDD van dando forma al software que quieren conseguir.

En este post voy a citar algunos puntos y consejos que ellos destacan durante el proceso de la construcción de la aplicación. Para profundizar en el proceso es imprescindible leer todos los capítulos que comprenden esta parte.

Divide y vencerás.

Es importante separar en pequeñas porciones las funcionalidades que se quieren implementar e ir añadiendo esas porciones incrementalmente y solo una cada vez. A la hora de refactorizar se debería seguir el mismo principio, pequeños refactorings que no comprometan el estado de la aplicación.

Iteración 0.

La «iteración 0» sirve para crear el esqueleto de la aplicación junto con el primer test de aceptación. Esto ayuda a entender desde el principio la automatización de la construcción, empaquetado y despliegue de la aplicación. Puede suponer un importante esfuerzo al principio pero es una de las tareas más importantes ya que si se deja para más tarde podrían surgir problemas inesperados.

Tests de aceptación.

Cada vez que se implemente una nueva porción de funcionalidad se debería añadir un test de aceptación simulando un evento de entrada a la aplicación para lograr un efecto en ella. Una característica de los test de aceptación es que permiten explorar el espacio que hay en medio desde que el mensaje entra a la aplicación y el resultado que produce ese mensaje.

Código mantenible.

Los equipos deberían invertir tiempo en escribir código mantenible a la vez que van añadiendo nuevas funcionalidades, ya que si no se hace, el coste de mantenimiento a largo plazo será cada vez mayor. Algunos consejos a tener en cuenta:

  • Principio de responsabilidad única, ayuda a separar la complejidad.
  • Métodos pequeños para expresar intención.
  • No tener miedo de crear nuevos tipos, por ejemplo, encapsular tipos primitivos ayuda a expresar el dominio de una mejor forma.
  • Encapsular colecciones. Utilizando el lenguaje del problema en lugar del lenguaje del lenguaje de programación ayuda a describir mejor un concepto de dominio.

Tests.

Algunos consejos útiles que los autores recomiendan a la hora de escribir tests:

  • Utilizar null cuando el argumento en el test no importe.
    Chat UNUSED_CHAT = null;
  • A veces puede ser beneficioso calcular el valor esperado en un test ya que hace el test más legible. Algunos puntos negativos de esta técnica pueden ser que haya que escribir el mismo código en el test que en la implementación y el cálculo puede ser demasiado complicado.
  • Pair programming es beneficioso durante todo el proceso de desarrollo, puede serlo incluso más durante la fase de refactoring en el ciclo de TDD, ya que aporta varios puntos de vista a la hora de realizar el diseño.

Decisiones.

Decidir si realizar o postponer un refactoring o el cambio de diseño de la aplicación es una difícil decisión. Es fundamental tener en cuenta los trade offs que hay detrás de ese cambio y no hay una regla común para decidirlo, requiere experiencia y madurez técnica.

No tener miedo a cambiar el nombre de los objetos es una parte esencial del proceso de desarrollo de software. Cada vez que conocemos más la aplicación y el dominio irán surgiendo mejores nombres y abstracciones las cuales facilitarán la lectura del código.

 

 

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 1: Introducción

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 2: TDD.

 

Pair programming

Hace unos días di una charla sobre pair programming para el equipo, no es que yo sea un experto en la materia, pero lo que estaba claro es que no lo estábamos haciendo de forma adecuada.

¿Por qué no lo hacíamos bien? Creo que fallábamos cuando un miembro de la pareja, sin darse cuenta, monopolizaba el teclado. Otro aspecto que debíamos mejorar es que los programadores con más experiencia intentábamos imponer nuestras ideas en lugar de llegar a un acuerdo con la pareja.

Basándome en algunos recursos¹ que encontré en internet y en el libro Pair Programming Illuminated, hice una pequeña presentación y discutimos sobre como estábamos haciendo pair programming y como podríamos mejorar nuestra técnica.

Uno de los aspectos que acordamos mejorar es el rol del navegador. Es fundamental que la persona que está navegando ayude basándose en abstracciones al que tiene el teclado en ese momento. Por ejemplo, es mejor comunicar «vamos a crear un componente que sirva para la selección de usuarios», que decir «ahora extendemos una clase de react que contenga un select al cual le vamos a pasar un array con los usuarios».

Otro aspecto a mejorar por los desarrolladores más experimentados es limpiar la mente de prejuicios y experiencia pasada, ya que de esta manera podemos aprender nuevas técnicas de la persona con la que estamos programando.

Una de las conversaciones que surgieron es que programar por parejas nos está ayudando a mejorar la comunicación entre los miembros del equipo. Además, en mi caso, me está ayudando mucho a practicar inglés y a conocer mejor el business de los productos.

Happy coding and pair programming!

1. Recursos:
Effective Navigation in Pair Programming
Pragmatic Pair Programming Introduction
Pair Programming Explained
Pair Programming course

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 2: TDD.

En este segundo capítulo del GOOS, Nat Pryce y Steve Freeman nos explican lo que puede aportar el ciclo de TDD y cómo sería para ellos un buen diseño orientado a objetos.

TDD.

Incertidumbre y fuente de feedback.

Los riesgos de dejar el despliegue de la aplicación para el final son demasiado altos. Nada mejor que automatizar el despliegue desde el principio para entender el proceso y que el equipo entienda como encaja.

Tener un sistema desplegable es útil para poder lanzar los tests contra él. Esto aportará fuente de feedback en el proceso de desarrollo, sobre la calidad del sistema y del código.

Todo este trabajo previo de automatización puede parecer excesivo pero ayuda a exponer la incertidumbre lo más pronto posible.

Mantener el ciclo de TDD.

Empezar escribiendo un test de aceptación en el lenguaje del negocio/dominio ayuda a entender lo que el sistema debe de hacer, sin hacer presunciones de como tiene que ser la implementación.

Los tests unitarios nos ayudan a diseñar los objetos necesarios para cumplir con el objetivo.

Una de las mejores cosas que se puede conseguir con TDD es la confianza de cambiar el código sin miedo a romperlo. El miedo paraliza el progreso.

Consejos:

  • Es preferible empezar escribiendo los tests con el caso más sencillo posible e ir añadiendo tests para validar nuestras ideas e ir haciendo más robusta la nueva feature.
  • Deberíamos escribir el test que nos gustaría leer, sin tener en cuenta si el código compila, centrándonos solo en cómo está escrito.
  • Es fundamental ver fallar el test para comprobar si falla de la forma que esperamos.
  • Los tests unitarios deberían comprobar el comportamiento de una unidad, no todos los posibles caminos del código.
  • Escuchar a los tests. Cuando el código es difícil de testear, probablemente el diseño de la aplicación necesita ser mejorado.

Orientación a objetos.

Para diseñar una aplicación mantenible hay que centrarse principalmente en dos objetivos. El primero es la separación de responsabilidades que ayuda a cambiar menos código cuando hay que implementar una nueva funcionalidad. El segundo es elevar el nivel de abstracción, ya que se consigue bajar la complejidad.

Consejos:

  • Exponer solo lo necesario en la interfaz pública de nuestros objetos.
  • Encapsular el comportamiento de un objeto para que pueda solo ser modificado a través de su API.
  • Ocultar como un objeto implementa la funcionalidad para la que existe.
  • Un objeto solo debe tener una responsabilidad.
  • Nombrar objetos sin utilizar ningún tipo de conjunción («y», «o», «con»).
  • Construir un objeto válido desde el constructor.

Relaciones entre los objetos.

Se puede categorizar la relación entre los objetos en tres tipos. Un objeto puede tener  relaciones con objetos que son dependencias, objetos a los que notificar y objetos que ajustan el propio comportamiento del objeto.

Al componer un objeto con otros objetos se espera que la API del nuevo objeto oculte los componentes del nuevo objeto y sus interacciones, exponiendo una abstracción más simple.

Logrando un diseño orientado a objetos.

Empezar primero escribiendo los tests ayuda con el diseño y a describir lo que se quiere conseguir y no cómo conseguirlo. Para construir el objeto que se quiere testear es necesario conocer las dependencias del objeto, esto ayuda a mantener la independencia del objeto sobre la aplicación y a conocer como se relaciona el objeto en el sistema.

Value types.

Los conceptos de dominio deberían de estar definidos como tipos aunque no tengan demasiada implementación.

Tres técnicas básicas para introducir value types son:

  • Extraer nuevos tipos que ayuden a eliminar la complejidad de un objeto que tiene múltiples responsabilidades.
  • Introducir un nuevo concepto de dominio.
  • Agrupar grupos de valores que son usados siempre conjuntamente.

Identificar relaciones con interfaces.

Usar interfaces para identificar los roles que un objeto cumple en el sistema ayuda a describir los mensajes que el objeto acepta.

Cuantos menos métodos tenga la interfaz más claro será el rol que define, además será más fácil escribir adaptadores y decoradores para ella.

Clases.

Son un detalle de implementación, una forma de implementar los tipos.

Construir sobre código de terceros.

Uno de los principales problemas cuando se utiliza código de terceros es que no tenemos el control sobre él y no podemos usar nuestro proceso para guiar el diseño. Es aconsejable centrarse en el proceso que integra nuestro diseño y el código de terceros.

Consejos:

  • Mockear tipos que te pertenecen.
  • Escribir adaptadores para comunicarse con el código de terceros.

Enlaces relacionados:

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 1: Introducción

 

Saliendo de mi zona de confort

Estoy escribiendo este post camino a Irlanda, embarcado en un ferry que probablemente me cambiará la vida. Saliendo de la zona de confort, aquella en la que tan cómodo y a gusto estaba, un buen trabajo, casa, familia, amigos, rutina, todo aquello con lo que muchas personas soñarían.

Hace unos años ví este video y algo cambió en mi interior. Desde ese momento decidí que quería salir de la zona donde más cómodo me sentía y así poder experimentar qué se siente al salir de ella.

Siendo programador, lo más factible para mí era buscar un trabajo en el extranjero, lo cual me permitiría aprender de otra cultura, forma de trabajar e idioma. Lo que ocurría era que mi nivel de inglés no era lo suficientemente bueno para conseguirlo. Para mejorarlo me propuse asistir a clases y empezar a ver en versión original las series de televisión que me gustaban. En el transcurso de unos años poco a poco mi inglés fue mejorando y conseguí aprobar un par de exámenes oficiales.

Ahora solo faltaba empezar a buscar trabajo. La búsqueda empezó en agosto de éste año y la verdad es que las primeras entrevistas fueron de pena, pero me sirvieron para ir mejorando el oído y pronunciación. De todo se aprende.

En noviembre, después de cuatro meses de búsqueda, pasé una serie de entrevistas con una empresa de Dublín y me han dado la oportunidad de trabajar allí. Y aquí estamos mi mujer y yo emprendiendo una aventura emocionante.

En este momento mis sentimientos están encontrados, por una parte tristeza por dejar a la familia y amigos, por otro lado alegría y ganas por empezar una nueva etapa y conocer qué cosas hay fuera de mi zona de confort en la que he estado toda mi vida.

Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 1: Introducción

Empecé a leer el GOOS hace unos días y me di cuenta que para profundizar en el libro tenía que hacer algo más que leerlo. Por eso voy a empezar a escribir en el blog algunos posts  con notas del libro que me parezcan interesantes. Por supuesto solo serán unas notas, para profundizar con el libro y sacarle todo el jugo posible habrá que leerlo y releerlo varias veces.

Parte 1: Introducción

Es necesario contar con procesos / herramientas que proporcionen feedback lo más rápido posible para solucionar la incertidumbre que existe cuando se empieza a desarrollar un proyecto de software.

El desarrollo iterativo refina progresivamente la implementación de las nuevas funcionalidades hasta que son suficientemente buenas.

Sigue leyendo «Notas sobre Growing Object-Oriented Software, Guided By Tests – Parte 1: Introducción»

RPG Combat Kata

En la Software Craftsmanship de Pamplona, Daniel Ojeda (@SuuiGD) propuso hacer la kata RPG Combat Kata, en ese mismo momento no la hice pero me quedé con ganas de hacerla.

En estos días de vacaciones la he hecho y me ha parecido muy enriquecedora ya que tienes que cuidar mucho el diseño en la fase de refactorización, ya que si no lo haces de esta manera en la próxima iteración tendrás muchos problemas para poder añadir las nuevas features propuestas.

A mi me ha pasado factura el no refactorizar lo suficiente en la iteración 4, ya que he tenido que hacer alguna «chapuza» para poder implementar la iteración 5.

 

Os dejo el enlace con el código con el código.

RPGCombatKata.

 

Cultura de la automatización

Recientemente, he tenido el placer de asistir a un curso de Continuous Delivery impartido por Néstor Salceda y la gente de GeeksHubs Academy y de leer un par de libros, Building Microservices, de Sam Newman y Continuous Delivery with Windows and .NET de Chris O’Dell y Matthew Skelton. Todo esto me ha ayudado a descubrir una serie de prácticas y herramientas con las que conseguir automatizar los procesos rutinarios que hacemos todos los días.

Para entregar valor de forma continuada, sin estrés y a un ritmo sostenible en un proyecto de software es fundamental no gastar tiempo haciendo tareas repetitivas que no aportan valor. En mi opinión, una de las claves para conseguir el objetivo es automatizar procesos y crear una cultura de la automatización dónde nos tendríamos que preguntar si merece la pena automatizar una tarea y si el retorno de la inversión pagará el coste de la automatización.

Sigue leyendo «Cultura de la automatización»

Impresiones sobre la CAS 2015

Hace unos días asistí a la Conferencia Agile Spain 2015 que se celebraba en Madrid en el Círculo de Bellas Artes. Un lugar estupendo en el centro de la ciudad. Ésta ha sido la tercera edición a la que asisto, después de Bilbao 2013 y Barcelona 2014.

La mayoría de las charlas a las que asistí en la conferencia fueron del track «Mejorando software» y me gustaría compartir algunas impresiones sobre ello.

Sigue leyendo «Impresiones sobre la CAS 2015»