Métricas para equipos de desarrollo de software

Como parte de mi trabajo en el último año, he intentado empujar la cultura de mejora continua en los diferentes equipos con los que he ido trabajando. Tanto en cuestiones de herramientas y habilidades técnicas, como en las de comunicación y coordinación, con ciertas restricciones y dependencias que caen fuera de nuestro margen de influencia.

Partimos del supuesto de que cuanto mejores sean las prácticas del equipo, mejor capacidad de entrega tendrá. Eso se traduce en una mayor adaptabilidad a los cambios, una mejor mantenibilidad del software con el paso del tiempo y posiblemente una mayor motivación del equipo con su trabajo.

Además de las típicas sensaciones subjetivas de efecto de mejora, teníamos que pensar en indicadores que nos permitieran ir observándolo realmente. En algún momento, también se empezaría a querer tener visibilidad desde fuera de los equipos, así que tocaba darle una vuelta y ordenar ideas.

Estuve preparando una presentación para explicar internamente cómo estábamos trabajando, hacia dónde creía que debíamos ir a través de una mejora continua, las distintas métricas que podríamos observar y las necesidades que se cubrirían con una buena capacidad de entrega.

Diapositiva de una presentación con la visión de lo que, como equipo deberíamos cubrir: adaptabilidad respecto a negocio, entregar pronto, evitar retrabajo, una buena UX y evitar bugs en lo posible

“Dime cómo me mides y te diré cómo me comporto”

Desconozco el origen, pero con estas cosas siempre me acuerdo de este dicho. Hay que andar con ojo con qué indicadores (que no objetivos) vamos a medir. Además, tendremos que usar varios para compensar el fomento de comportamientos extraños que falsean esas métricas.

Con el uso normal de las herramientas, sólo acordando algunas convenciones, se puede facilitar la explotación de datos posterior para extraer métricas. Los orígenes de datos para los indicadores son:

  • El código
  • El repositorio y servidor de automatización
  • Las herramientas de gestión
  • El propio producto

Indicadores del código

Las herramientas de análisis estático de código nos dan números sobre deuda técnica que existe. No debemos perder de vista estos indicadores y dedicar tiempo en analizar y hacer limpieza específica de vez en cuando. Unas veces se resuelven con soluciones simples y otras esconden problemas de diseño que no resultan tan evidentes.

La cobertura de test es uno de los indicadores más habituales, lo más interesante en este caso es ver qué NO está cubierto. Y como se suele comentar, hay que andar con cuidado porque es un indicador fácil de falsear si se busca como objetivo.

En un momento dado, además, se podría utilizar mutation testing (comprobar que se rompe algún test al modificar código de producción) para tener un indicador de la calidad de los tests unitarios.

Indicadores del repositorio y servidor de automatización

Hay bastantes indicadores interesantes que se pueden sacar de los repositorios y servidores de automatización, aunque en su mayoría son dependientes de las convenciones de uso.

Sin embargo, un indicador siempre válido y que pienso que debería observarse es la frecuencia de integración.

La integración continua es una práctica (que no herramienta) tan popular como malinterpretada, ya que hasta que no se une el trabajo que ha hecho o está haciendo una persona con la rama principal de desarrollo y se completa una build, no la estamos realizando.

Hasta que no ha terminado correctamente la construcción de un artefacto de software, no sabemos si todo está correcto. A mayor frecuencia, feedback más temprano y menor incertidumbre.

En caso de usar ramas, también es interesante ver la duración de vida de las ramas. A más tiempo, mayor riesgo de conflictos u otros problemas al integrar.

Y si se utilizan pull/merge requests, también hay un puñado de indicadores que en un momento dado puedan sacarnos olores relacionados con la capacidad de entrega: cantidad de comentarios, tiempo que quedan abiertas, cantidad de rechazos…

Indicadores de las herramientas de gestión

Las herramientas de gestión, además de servir como radiador de información para saber la situación actual de la construcción del producto y ayudar a coordinar el trabajo, son una buena fuente de información de indicadores del proceso de trabajo.

Para observar la capacidad de todo el equipo en conjunto de hacer vertical slicing es muy útil conocer el tiempo de ciclo. A menor tiempo de ciclo, mayor es nuestra capacidad de entrega. Es el tiempo que se tarda desde que se empieza a trabajar en algo que aporte valor (por ejemplo, una historia de usuario) hasta que pasa a estar hecho.

Es habitual que en algún punto de las herramientas de gestión se pueden observar los distintos despliegues que se han realizado, donde podamos obtener la frecuencia de despliegue. Evidentemente a mayor frecuencia, mejor.

Aunque nuestro tiempo de ciclo fuera corto y la frecuencia de despliegue alta, sería posible que nuestro producto fuera frágil debido a bugs. Por eso el indicador de bugs detectados y resueltos por versión/despliegue es otra métrica a tener siempre en cuenta.

Dependiendo del momento y escenario en el que se encuentre un producto, también me parece muy interesante el indicador del lead time, el tiempo que pasa desde que se pide algo nuevo hasta que está desplegado en producción. Que vendría a ser consecuencia de los 3 anteriores indicadores y del tamaño de la pila de producto.

Como supongo que haya quien pueda echarlo de menos, omito intencionadamente los indicadores al respecto de las estimaciones, tipo story points por iteración. En mi opinión, tienen un componente muy subjetivo y variable para ser utilizado como indicador de cambio en la capacidad de entrega de un equipo.

Indicadores del propio producto

Además de otro tipo de instrumentación mucho más minuciosa que necesitan los miembros del equipo de gestión de producto o diseño, el equipo de desarrollo debería poder observar el número y porcentaje de uso por funcionalidad, que al final define el éxito o no del trabajo de todos.

Lo más interesante de este indicador es que combinado con otras métricas puede ayudar a tomar decisiones sobre la evolución del producto. Como por ejemplo, este escenario:

  1. Detectamos problemas muy graves de rendimiento en una parte del producto.
  2. Observamos que el porcentaje de uso de la funcionalidad afectada por esos problemas es residual.
  3. Decidimos no resolverlo de momento, pero lo reflejamos en la pila del producto como algo poco prioritario.
  4. Configuramos una alerta para detectar cierto aumento en el porcentaje de uso de esa funcionalidad.

Otro indicador importante es el crash rate del producto, cuántas veces se detecta un fallo o error por cantidad de uso, que nos permite saber lo estable que es un producto. Y mezclado con el indicador de números de uso por funcionalidad, nos permite detectar los puntos problemáticos.

Dependiendo del contexto del producto y del negocio, posiblemente podamos sacar también otros indicadores relevantes de operaciones y soporte que sean consecuencia del uso del producto.

Medir sin perder el foco

Estos son muchas métricas distintas. Es interesante observarlos porque nos pueden servir para detectar olores sobre problemas y oportunidades de mejora, pero son demasiados para tratar de mejorar todo a la vez.

Para evitar diluirnos y no terminar mejorando en nada, deberíamos elegir y enfocarnos en un par de esos indicadores cada vez, dependiendo de la situación de cada equipo.

Y aunque sea tentador hacerlo, evitaría usar alegremente estos indicadores para marcar objetivos, así como para evaluar a equipos distintos.

No olvidemos que el propósito de medir estos indicadores es observar la evolución en el tiempo de un equipo trabajando en un producto y contexto determinado.

Diseño incremental de software a partir de las interacciones (parte 1)

Este post viene a cuento de que me quedé sin hacer la charla de la Bilbostack 2019 por andar pachucho durante varias semanas, teniendo que cancelar el compromiso al no haberme recuperado a los pocos días del evento. Me quedó el contenido a medio preparar y tenía la espinita clavada de compartir mis ideas sobre el tema.

Dibujo representando la autosimilaridad de Lean Startup, ATDD y TDD

¿Qué narices es eso del diseño incremental?

Ahora que “agile” (nótese el entrecomillado ;)) es mainstream, parece que se va asumiendo en muchos sitios que hacer software de forma iterativa ayuda a hacer mejor software. Cada cierto tiempo hay entregas que permiten validar si se va por un camino correcto o no, comprobar malos entendidos, ver problemas que han surgido, adaptabilidad a cambios…

Lo que bajo mi percepción no es tan mainstream es la parte de incremental, cuesta más hacer vertical slicing. En mi opinión esto suele ocurrir por falta de habilidades o conocimiento de prácticas relacionadas con Extreme Programming, como son test first o el propio diseño incremental.

Aunque siempre hay que hacer un esfuerzo inicial para poder sentar algunas bases respecto a la visión del producto, qué problemas o necesidades se quiere resolver, la arquitectura de alto nivel, etc.; muchas veces se peca de querer bajarlo demasiado en detalle desde el inicio, pretendiendo tener una foto de cómo va a ser la solución y adivinar el futuro.

No olvidemos que, cuando desarrollamos un software, hoy sabemos menos que mañana. En cada iteración que pasa, más aprendemos sobre el negocio, conocemos mejor las herramientas y la tecnología, intentamos mejorar como equipo, etc.

Así que una cosa que debemos tener clara es que, si queremos que nuestro software dure, tenemos que enfocarnos en diseñar software que acepte cambios. Aceptar la incertidumbre frente a tratar de adivinar problemas futuros.

¿Y lo de diseñar a partir de las interacciones?

Pues básicamente enfocar el diseño de software desde cómo se va a utilizar, ya sean personas que interactúan a través de una UI u otros sistemas que lo hacen usando algún tipo de API.

Seguramente resulta familiar el término API first, que es una aproximación similar. Empezar definiendo cómo se expone el software partir de un contrato e ir haciendo Outside-In hacia la implementación y modelado más interno.

En el caso del diseño a partir de las interacciones nos abstraemos de los detalles de un API. Anteponemos la definición de la interacción a la del API ya que esta no es nada más que un detalle técnico de cómo se expone la interacción al mundo.

Y cuidado: No podemos caer en la trampa de definir pobremente esas interacciones, sin descubrir el negocio que hay debajo y acabar pensando que sólo son CRUDs. Nunca es un CRUD: reglas de negocio, efectos colaterales, integraciones con terceros…

Descubrimiento de producto

Antes de identificar las interacciones, un trabajo importante es lo que se suele llamar descubrimiento de producto. Algunas cosas que necesitamos saber: objetivos de negocio del producto, quiénes son los usuarios y sus motivaciones, dependencias técnicas u organizativas, posibles restricciones, identificar a los stakeholders…

Es un tiempo dedicado a analizar y entender los problemas para poder enfocar mejor la solución, ya que no hay nada peor que descubrir que hemos contruido algo que nadie quiere.

Hay multitud de actividades que se pueden usar dependiendo del contexto (producto, equipo, negocio…): business model canvas, value proposition canvas, entrevistas, user personas, mapa de stakeholders, mapa de empatía, benchmarking de producto, customer journey map… o usar un paquete de este tipo de actividades como design sprint, agile inception deck o lean inception.

Estas actividades, muy estilo design thinking, se han quedado relegadas habitualmente a la gente de UX, negocio o gestión de producto, ya que a los técnicos típicamente no nos ha preocupado demasiado o no se nos ha incluido.

Participar en estas actividades nos ayuda a entender infinitamente mejor las necesidades durante la evolución del desarrollo del producto, además de facilitarnos el planteamiento inicial de la arquitectura de software a alto nivel. Y es que hacer diseño incremental no quiere decir que no hagamos un trabajo previo.

Formalización del backlog

Para poder organizarnos y priorizar debidamente necesitamos tener disponible algún tipo de backlog de producto, de modo que lo oportuno es hacer un volcado de product backlog items (sin preocuparnos demasiado del tamaño) como complemento a las diferentes actividades de descubrimiento que se hayan podido realizar.

A mi personalmente me gusta el terminar visibilizándolo en un formato estilo user story map. Aunque siempre he omitido la parte de journey, simplemente me gusta verlo organizado en dos dimensiones: funcionalidad/tema y prioridad agrupada en swimlanes.

Me parece muy interesante organizar las swimlanes como must, could y nice to have, al menos como organización incial o de cara a implementar un MVP. Otras veces, teniendo razonablemente claro el alcance final, las he utilizado directamente para definir releases o entregas parciales tentativas.

Refinamiento de historias de usuario

Ya con la prioridad, sabemos por donde hay que ponernos a aterrizar esos product backlog items y formalizarlo en una o varias historias de usuario. Recordemos que una historia de usuario no es sólo completar una plantilla, debería ser siempre un artefacto que sirve como recordatorio de (o excusa para) una conversación sobre ella y que además debería tener unos criterios de aceptación específicos.

Además de en las dailies o conversaciones más informales entre los miembros del equipo, habitualmente estas conversaciones deberían ocurrir más intensamente en algún tipo de sesión de planning, de la que deberíamos extraer los criterios de aceptación de las historias de usuario en las que vayamos a trabajar próximamente. Esas sesiones pueden contener ejercicios de estimación como planning poker o de refinamiento como example mapping.

Personalmente me gusta bastante el example mapping porque ayuda a estructurar las conversaciones, desgranando las historias de usuario en forma de reglas, dudas y ejemplos que ilustran las reglas.

Specification by Example

Las reglas forman parte de los criterios de aceptación de una historia, mientras que los ejemplos nos marcan la especificación y nos sirven como primer paso para hacer Specification by Example (prefiero ese nombre que Behaviour-Driven Development) con el que dirigir el diseño incremental de las iteraciones.

Como herramienta para hacer Specification by Example suelo utilizar cucumber, de modo que las especificaciones terminan en el típico formato gherkin Given/When/Then.

Evidentemente se pueden utilizar otras herramientas para esto, pero ¿por qué cucumber?:

  • Al separar las especificaciones como texto plano, permite colaborar fácilmente con perfiles no técnicos para elaborarlo o validarlo.
  • Ayuda forzarse a utilizar lenguaje ubicuo que deberíamos haber ido desarrollando (quizá incluso mantengamos un glosario de términos).
  • Queda como fuente de verdad y sirve como documentación viva. Si una funcionalidad cambia, quedará reflejado el cambio.
  • Facilita hacer ATDD separando claramente el ciclo de especificación del de desarrollo.
  • Permite implementar tests automáticos a distintos niveles. Pudiendo hacer tests sólo de la lógica de negocio, desde la UI, a través de un API…

A partir de las historias de usuario y de las especificaciones con ejemplos tendremos identificados los casos de uso o interacciones, el alcance bien definido y habremos trabajado el lenguaje ubicuo.

Este tipo de prácticas hacen más eficiente el proceso de desarrollo, aumentando la calidad del producto y evitando retrabajo a causa de malosentendidos.

Próximamente

Espero escribir al menos un post más, tratando la parte más técnica a través de un ejemplo práctico sobre:

  • Implementar tests automáticos desde especificaciones gherkin con cucumber.
  • Artefactos tácticos de Domain Driven Desing.
  • TDD Outside-In, empezando desde las interacciones o use cases.
  • Arquitectura hexagonal/clean, escapando de frameworks.

Otros recursos

En forma de cursos, posts y videos relacionados que tengo repartidos por ahí:

Maven multimodule y attached tests

En mi vuelta al mundo java, una de las cosas que he retomado es el utilizar de forma habitual proyectos maven multimodule, lo que facilita controlar mejor las dependencias y segregar el empaquetado.

Así podemos hacer separación de responsabilidades dependiendo de nuestros intereses. Por ejemplo, algunos escenarios por los que podríamos querer usarlos serían:

  • Partir en vertical una aplicación por temas funcionales.
  • Publicar de forma independiente una librería que sale de nuestro proyecto para reutilización de terceros.
  • Partición horizontal de una aplicación o servicio: core, diferentes APIs, persistencia…

El último escenario es el que he empezado a utilizar de forma habitual, separando el modelo de dominio de los detalles de implementación de infraestructura y mecanismo de entrega. Así evitamos en lo posible tener dependencias en los módulos core a través aproximaciones de arquitectura hexagonal.

El problema que surge frente a tenerlo en un sólo módulo maven es lo respectivo a la duplicidad en cuanto código de test.

Un ejemplo es reutilizar algunos helpers de tests. En nuestro caso, implementaciones de patrones que nos facilitan la mantenibilidad como el builder o el object mother. Tener objetos fake (puede que incluso algún dummy) para usarlos como colaboradores y desacoplarnos de las implementaciones reales. O tener especificaciones en lenguaje gherkin desde el módulo core, para que sean compartidos con los módulos responsables de tener implementados los tests de cucumber.

Gracias a Maven JAR Plugin podemos evitar estas duplicidades, ya que nos permite empaquetar los tests de un módulo en un JAR sin tener que mezclarlo en los paquetes de código de producción.

Por ejemplo, para compartir los tests del módulo core deberíamos configurar la construcción del JAR de test de este modo:

<project>
  ...
  <build>
   <plugins>
     ...
     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-jar-plugin</artifactId>
       <version>3.1.1</version>
       <executions>
         <execution>
           <goals>
             <goal>test-jar</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
   </plugins>
  </build>
</project>

Mientras que en los módulos que queramos usar el JAR de los tests deberemos incluir la dependencia así:

<project>
  <dependencies>
  ...
    <dependency>
      <groupId>com.danilat.killerapp</groupId>
      <artifactId>core</artifactId>
      <version>X.Y.Z</version>
      <type>test-jar</type>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Con esto ya podemos reutilizar los helpers de test o especificaciones de cucumber en diferentes módulos de maven.

Un repaso a mi 2018

Este año tuve un cambio vital importante que vino dado por una combinación de circunstancias y tras un par de meses de conversaciones, terminé mudándome en Junio a A Coruña para trabajar en Zara.com. Así que cuando estuve repasando hace unos días los objetivos del año anterior, pasó lo que era de esperar, que fue bastante fiasco:

En Coding Stones como muchas otras empresas (aunque jamás nos constituyéramos como una), no conseguimos llegar y superar el tercer año de vida. Con las reglas de juego que nos marcamos sabíamos que era un modelo difícil, exige a los socios estar muy alineados y cuesta horrores vender a los clientes. Para mí haber formado parte de esta banda-cooperativa fue una experiencia que me hizo crecer en muchos aspectos, resulta imposible no tener morriña de mis exsocios de vez en cuando.

Respecto a Outreach Tool una de cal y otra de arena. El software tras la reescritura es mucho más extensible y pude ir implementando cambios y mejoras más fácilmente, aunque con mi cambio profesional se quedaron bastantes cosas en el tintero, principalmente relacionadas con temas del rediseño de UI. Ahora mismo la evolución (y explotación) del software está un poco en el limbo, quizás puedan seguir haciéndolo otras personas.

A pesar del parón en febrero por la lesión de una costilla flotante durante una sesión de guanteo, los primeros meses del año tuve una muy buena rutina de entrenamiento y empecé a sentir que (además de mantenerme bien físicamente) técnicamente mejoré bastante. Pena que con el lío del cambio de ciudad no reservé apenas tiempo para buscar un gimnasio en el que seguir aprendiendo, finalmente en noviembre encontré uno que pintaba muy bien, aunque aún he ido muy poco.

En 2018 no hice charlas como tal, sólo la que preparé con la excusa del lanzamiento del curso de Codely de BDD con Cucumber. Facilité coding dojos en el trabajo y en la CommitConf, además del Global day of Code Retreat en Coruña. Experimenté con el formato screencast y me moló bastante. Pero apenas escribí 2 posts en el medium de Coding Stones, este me gustaría escribir más. De nuevo formé parte de la organización del Startup Open Space Zaragoza.

Lo de sacar un DNDzgz como PWA quedó en un fail total. Tengo una versión funcional desplegada que les pasé a un puñado de amigos pero le faltan afinar muchas cosas, así que por el momento se queda como otro petproject que iré tocando cuando me de el puntazo de mejorar algo.

Y bueno, ni mucho menos fue un objetivo, pero algo tendré que contar de Zara.com. Llegué con la idea de dedicar la mayor parte de mi tiempo a hacer producto e involucrarme hasta la cocina en todo lo que me dejaran y fuera capaz respecto a ello. Esto es que no quiero sólo desarrollarlo, sino estar desde las fases de conceptualización y aterrizaje hasta el aprendizaje de tenerlo en producción, y acompañar en hacerlo crecer y evolucionarlo. En el camino estoy haciendo variedad de trabajo, yendo desde cuestiones puramente técnicas hasta temas más relacionados con producto o gestión, así que no me aburro ;)

Como de costumbre, más cosas del año y sin ningún orden en particular:

  • Leí mucho este año, pero casi todo fueron libros técnicos.
  • Estuve unos días en Roma.
  • Repetí participación en Movember.
  • No fui a tantos conciertos como en los últimos años, pero fui a un buen puñado.
  • Fui a algún partido a la Romareda y a Riazor (aunque no pudo ser al Depor-Zaragoza).
  • Pude asistir a BilboStack, From The Trenches en Donosti, NOS Day y XantarJ en Santiago, Software Crafters Madrid y Monitoring Day en Zaragoza.
  • Vi un par de veladas de boxeo y me quedé con ganas de ir a alguna grande.
  • Por avisado que fuera, me sorprendió lo masificada de la noche de San Juan en Coruña.
  • Volví a tener vértigos.
  • Colaboré (poco) con la fundación canem.
  • En verano hice unas vacaciones típicas aragonesas: costa daurada y fiestas del pueblo.
  • Al fin vi el Guernica de Picasso.
  • Montamos un eventito con Cachirulo Valley.
  • Hice un curso de product owning con las buenas gentes de Makoto.
  • Sobreviví a 3 bodas.
  • Vanessa también se vino a vivir a Coruña.
  • Me hicieron una fiesta de despedida sorpresa que lo moló todo.

Objetivos 2019

  • Patear la zona noroeste de la península. Tanto zonas costeras atlántica y cantábrica como visitar ciudades y pueblos más hacia el interior; son zonas que apenas he tenido oportunidad de conocer.
  • Colaborar con grupos locales a través de talleres, coding dojos… Ya tengo algunas cosillas medio apalabradas con varias personas que organizan iniciativas por aquí.
  • Conseguir tener una rutina de entrenamiento similar a la que tuve los primeros meses de 2018 para al menos recuperar técnica y aprender trucos nuevos.
  • Escribir una media de un post al mes. Llevo un tiempo en el que me apetece escribir sobre varios temas sobre los que voy trabajando, pero aunque no sean temas muy sesudos sé que me cuesta horrores y termino no dedicándole tiempo.

Respecto a mi actual trabajo, más que marcarme objetivos lo que tengo son retos. Retos que me resultan muy interesantes para este 2019, junto a varios que se avecinan en el horizonte y otros que seguro que irán surgiendo.

¡Feliz an nou!

El juego de la vida en la Commit Conf

En Junio se acababa la fecha límite para enviar propuestas a la Commit Conf, el viñarock del software (evento organizado por las mismas personas que Codemotion hasta 2018). No me apetecía proponer una charla, más a tanto tiempo vista celebrándose en Noviembre; pero finalmente me animé a enviar una propuesta de coding dojo para practicar TDD y pair programming a través del juego de la vida de Conway.

Tuve bastantes dudas en hacerlo: Lo propuse en una ocasión en un evento de agile y no cuadró, así que no tenía claro como encajaría en un evento más técnico pero un tanto generalista. Sólo había participado/facilitado coding dojos en eventos pequeños. La kata da más juego con más tiempo, a partir de 4 iteraciones o así suele haber más mezcla y se va observando mucha evolución en las soluciones. Y que podía ser un fail tanto por soledad como por superpoblación ;).

Así que procuré poner una descripción para todos los públicos y finalmente la aceptaron.

Aunque es una kata que había practicado bastante y la había facilitado en un par de code retreats la prefería rodar. Tuve la oportunidad de hacerlo en un coding dojo interno con compañeros de Zara.com, y me tomé como cierto rodaje las 2 primeras iteraciones en el Global day of Code Retrat de A Coruña.

De modo que pude acortar y refinar un poco la pequeña presentación para ayudarme a contextualizar, ya que suponía que habría gente que nunca habría participado en un coding dojo o hubiera utilizado katas como ejercicios de práctica deliberada.

Y mientras que en los code retreats prefiero ir improvisando constraints dependiendo de lo que se va viendo en cada iteración. En este caso como no había mucho tiempo ni margen de maniobra, preferí llevarlo preparado en la presentación.

Siendo el segundo día del evento y a primera hora de la mañana había alrededor de una treintena de personas. Y que en general vi a la gente muy concentrada en el ejercicio, mucha comunicación entre pares y tríos, personas desconocidas relacionándose entre ellas, gente descubriendo el testing automático o haciendo sus pinitos con TDD, programando en distintos lenguajes…

Como anécdotas os diré que yo tenía que gritar para dar instrucciones y a veces me sentía ignorado (eso que no tengo mal volumen de voz), y que uno de los fotógrafos de la organización me preguntó si era algún tipo de concurso al ver a todo el mundo tan engorilado.

Así que, aún más acordándome de mis dudas en Junio, al acabar me quedé con un buen sabor de boca :).