Vertical Slicing (V) — Ejemplo práctico (Bot en Slack para traducir mensajes)

Abraham Vallez
8 min readDec 8, 2021

Vamos con un segundo ejercicio, más realista, donde pondremos en práctica los conceptos de anteriores posts.

Disclaimer: Los ejercicios son ejemplos, más o menos reales, pero ni son ejercicios deterministas, ya que dependen del contexto, la tecnología, el código que tengamos, ni es la solución única de implementación. Es una aplicación práctica de los pasos del proceso a varios ejemplos. Si lo hacéis vosotros mismos, es muy posible que os puedan salir otros incrementos, otras actividades necesarias y otro tipo de implementación.

Bot Slack

Queremos que cuando alguien escribe un mensaje en un canal, se envíe además otro mensaje con una traducción en castellano e inglés para que podamos hablar con varias personas en inglés de forma más natural, dado que no tenemos aún fluidez con el idioma.

Básicamente, el journey es: alguien chatea a un canal de Slack → el mensaje se envía a traducir a un servicio de traducción (elegimos DeepL como ejemplo) → este mensaje ya traducido se vuelve a enviar al mismo canal.

1. Preparar un primer problema grande

Este paso lo vamos a obviar para facilitar el ejemplo, asumimos que entendemos y tenemos claro el porqué, para quien es y el para qué lo necesita.

2. Encontrar las actividades necesarias (funcionalidades, capacidades o comportamientos)

¿Cuáles son las actividades o comportamientos que necesitamos para solucionar el problema?, las tres actividades o capacidades que identificamos serían:

  • Detectar el mensaje que se escribe en el chat
  • Traducir el mensaje
  • Escribir la respuesta traducida en el canal

3. Encontrar los conceptos de cada actividad que añadan complejidad

¿Qué conceptos son los que añaden complejidad a cada actividad?

Para detectar el mensaje, seguramente la dificultad esté en ¿Qué tipo de mensaje?, si es un mensaje normal, uno editado, uno en un hilo…

Para la actividad de traducir

  • Que tipo de contenido tiene el mensaje: si tiene solo texto, imágenes, links, gifs…
  • Detectar el idioma del mensaje original
  • A que idiomas tengo que traducir

Al tratar de Escribir la respuesta traducida

  • Tipo de mensaje a responder: si será un nuevo mensaje, o añadirlo como hilo…
  • El contenido del mensaje al responder

4. Identificar todas las posibles variaciones

Una vez identificados los conceptos que añaden complejidad, descubriremos y refinaremos las variaciones o cómo ir desarrollando poco a poco esa complejidad.

Variaciones en que tipo de mensaje detectamos, podría ser un mensaje enviado normal, un mensaje enviado que alguien lo ha acabado de editar o un mensaje que se ha enviado en un hilo.

Con el contenido del mensaje podremos diferenciar entre mensajes con únicamente texto, mensajes con links, con imágenes…

Respecto a que idioma detectar empezamos no detectando, asumiendo que todo es envío en ESP y aumentando la complejidad llegaremos a detectar de forma automática el idioma.

Con los idiomas, las variaciones son obvias. ESP-ENG, ENG-ESP

Al enviar la respuesta podremos encontrar variantes al decidir si queremos enviar un nuevo mensaje o un mensaje en un hilo y podremos usar las mismas variaciones que anteriormente respecto al contenido del mensaje.

5. Reducir todas las posibles variaciones a una — Vertical slicing

¿Cuál es el primero pequeño incremento? ¿Cuál es la primera versión básica de nuestro sistema al completo?
El primer incremento de cada actividad que nos dará feedback de si vamos por buen camino respecto a la solución del problema.

Una opción sería tener un sistema que al detectar un mensaje enviado normal, de solo texto y en ESP — podríamos obligar en un canal de prueba a solo escribir texto en ESP — traducirlo al inglés y reenviarlo al mismo canal como un mensaje nuevo.

El objetivo es tener una versión básica del sistema, con funcionalidades básicas — no las funcionalidades finales — que nos pueden dar feedback de la complejidad a la que nos vamos a enfrentar y que podamos ir haciendo crecer incremento a incremento.

6. Desarrollar en baby steps iterativos e incrementales

Ahora que tenemos un primer slice vertical, tendremos que implementarlo. Volveremos al paso 2, ahora con la primera versión básica del sistema, para encontrar de nuevo pequeños incrementos o baby steps con los que desarrollar la solución.

En este 6º paso, debemos adentrarnos en la parte más cercana a la complejidad de la propia solución y empezar a pensar en posibles diseños para implementar de forma iterativa e incremental.

En este ejemplo, podemos idear algo así:

Usando la API propia de Slack y un Lambda en AWS que gestione el mensaje. Enviar al servicio DeepL y gestionar también la propia devolución del mensaje traducido.

Encontrar las actividades o tareas del sistema.

Buscamos ahora funcionalidades o comportamientos que mi sistema va a necesitar implementar para realizar lo que necesita. No tareas de desarrollador, no va a ser nada como “implementar el endpoint del servicio”, sino algo funcional o un cambio de comportamiento en el sistema.

Recordad que ya no necesitamos plantear la solución final, sino solo el primer slice que hemos seleccionado anteriormente.

Encontrar los conceptos de cada actividad que añadan complejidad y sus variaciones.

En este punto, al entrar en la parte más cercana a la solución, podremos encontrarnos algunos casos como descubrir que Slack ya tiene capacidad de detectar automáticamente el mensaje que se escribe en un canal y lo envía, a través de su API, donde nosotros configuremos. Por lo tanto, esta primera actividad es “gratis”.

Este tipo de conceptos aparecerán durante el propio refinamiento de la solución, por eso es importante ir encontrando poco a poco y desde el principio las actividades, las complejidades y las variaciones posibles.

Para el resto de actividades podremos seguir los patrones de splitting más comunes.

Reducir todas las variaciones a una — Vertical Slicing y baby steps

Llegamos a la parte donde decidimos, con toda la información obtenida hasta ahora, como vamos a hacer posible el desarrollo iterativo e incremental en baby steps. Tendremos que buscar cuál es el primer slice vertical de entre todas las variaciones que nos pueda dar feedback rápido sobre la incertidumbre de nuestra solución.

Podría ser que no hayamos trabajado nunca con la API de DeepL, por lo tanto, un primer baby step básico podría ser tener un lambda que envíe y reciba un mensaje a traducir a DeepL. Un mensaje hardcodeado y sin gestionar errores, podría incluso escribir la salida en algún tipo de consola. Esto nos dará feedback temprano del uso de DeepL

Puede ocurrir también que la mayor incertidumbre sea acerca de cómo chatear en Slack a través de su API, por lo que el sistema básico que implementaremos en primer lugar sería enviar un mensaje a Slack desde nuestro lambda.

O tal vez para nosotros sea algo muy simple — ojo con el optimismo — y decidamos que nuestro primer paso sea un trocito más completo.

Una vez que tengamos este primer slice — nuestro primer step básico con funcionalidades básicas — podremos ir incrementando. Para completar el slice más vertical, haremos que Slack sea quien lance la acción en el momento que alguien escriba un mensaje, aunque la traducción devuelta siga siendo del mensaje hardcodeado en el lambda. Con esto ya tendremos conectado todo el sistema de forma vertical.

Es buena idea no ir incrementando una actividad de manera aislada, ya que lo que nos interesa es recibir feedback cuanto antes de cómo funciona o “liga” el sistema al completo — Cómo ligan y saben juntos los ingredientes de la tarta.

Seguimos añadiendo baby steps hasta completar el incremento al completo o hayamos desarrollado suficiente como para tomar alguna decisión con el feedback obtenido.

Una opción para el siguiente paso es sustituir el envío de un texto hardcodeado por el texto recibido del propio Slack. Pero aún no gestionaremos caracteres extraños por lo que no consideraremos limpiar el mensaje, con lo que esto mismo podría ser un siguiente baby step. Otro ejemplo de baby step sería pensar en cómo empezar a gestionar los posibles errores.

No tiene que ser otro baby step totalmente vertical, sino un baby step dirigido por la intención de resolver una complejidad de la solución, por recibir feedback rápido de si vamos por buen camino o no.

La intención de los baby steps es desarrollar de forma iterativa e incremental haciendo crecer la solución poco a poco. No intentamos desarrollar la solución final desde el inicio, ni tampoco desarrollar todos los incrementos de una vez.

Una vez hayamos ido completando baby step a baby step, tendremos una versión básica del sistema al completo. Ahora es momento de seguir con siguientes incrementos con la misma idea: ir haciendo crecer la solución, buscando feedback rápido de si vamos por buen camino en resolver el problema.

Algo que es común que ocurra — y es justamente por lo que desarrollamos de forma iterativa e incremental — es descubrir nuevas complejidades o resolver algunas con el propio desarrollo de los incrementos.

En este caso, aunque hayamos decidido que el primer incremento sea solo la traducción ESP-ENG y así no tener que detectar el idioma, al empezar a desarrollar, nos daríamos cuenta de que DeepL detecta automáticamente el idioma, por lo que podríamos obtener varios incrementos de “gratis”.

--

--