A lo largo de mi carrera me he encontrado con muchos proyectos, en los cuales ha habido problemas, pero me costaba imaginarme que a estas alturas de mi carrera me iba a encontrar con una situación en un proyecto en el cual me vuelvo a sentir sobrepasado. Hace unos meses, cuando volví de mi baja por paternidad, me movieron a un nuevo proyecto como backend lead. Necesitaban reemplazar al antiguo tech lead, el cual abandonaba la empresa unas tres semanas antes de que el proyecto saliese a producción. Aunque en el fondo sabía que me estaban asignando un marrón, me lo tome como un reto y ademas queria aprovechar la motivación con la que venía tras meses sin trabajar para tratar de ayudar al equipo y poner orden. Qué ingenuo fui.
Un proyecto caótico
El proyecto venía de tener un retraso de más de dos meses con varios intentos de salida a producción. Estos intentos fallidos ocurrian porque el cliente no se sentía seguro con el estado del producto. La frustración en el equipo era bastante alta, pero tarde unos dias en darme cuenta de ello. En particular, de repente me vi envuelto en una reunion super tensa, donde la QA empezo a pelear literalmente contra otra persona del equipo, echando en cara de forma abierta que no estaba haciendo bien su trabajo, ect. A esto habia que sumarle cierto grado de incompetencia por parte de la project manager. La pobre trataba de solucionar todos los problemas poniendo más y más reuniones, las cuales impedían que al equipo concentrarse en el trabajo real. Por otro lado, el cliente, frustrado por los constantes retrasos y dejándose llevar completamente por las presion, se dedicaba una y otra vez a contactar directamente con el equipo técnico para solicitar cambios con la excusa de que era bloqueante y urgente para el lanzamiento del producto, saltándose por completo todo el flujo de trabajo. Por ultimo, parecía que nadie le importaba que el cliente se saltara estos flujos de trabajo. Me sorprendia que la proyect manager no hiciera nada. De alguna forma, existía la expectativa oculta de que trabajáramos ad hoc, sin tickets, sin especificaciones, simplemente en base a la tipica y comoda postura de enviar emails quejandote de esto lo otro, y esperar que el equipo técnico lo solucione lo antes posible. Sin importar que la gente tiene también tiene vida personal y tiene otros problemas aparte del trabajo a los que también tiene que prestar atención.
El handover y la preparación
Siendo totalmente honesto, no estaba preparado para ser lanzado de golpe a un entorno tan caotico. El primer gran escollo fue que el handover que hicimos para traspasarme el conocimiento del antiguo tech lead no fue el más adecuado. He de decir que tampoco ayudan nada los managers que en lugar de tratar de poner claridad, simplemente se decian a hacer preguntas como, “oye, ¿has podido hacer bien el handover?” De alguna manera, tienen la expectativa de que contestes a esas preguntas de forma rotundamente afirmativa, y si siembras ciertas dudas, solamente obtienes como feedback su nerviosismo y mas presiones pidiendo que tienes que revisar mejor la documentación. Algo así como ese entrenador de fútbol que le dice al portero, “oye, tu función es que no te marquen goles, intenta que no te marquen goles”. Pasé bastantes horas con el antiguo Tech Lead en videollamadas, explicaciones, revisiones de código, etcétera. Pero, como todos sabemos, nunca es suficiente. Siempre se queda algo sin cerrar del todo. Era bastante significativo el ver la cara de alivio que tenía el antiguo tech lead conforme se iba acercando su fecha de dejar la empresa. A día de hoy tengo cada vez más claro que se fue porque estaba totalmente agobiado con este proyecto.
Salida a producción
Sorprendentemente la salida a producción fue bastante limpia. No hubo errores significativos, salvo el típico CORS suele ocurrir apuntar el dominio del produccion al nuevo site. La gente estaba eufórica, y todo parecía ir bien. Pero la semana de después se iniciaba la fase 2 del proyecto, y muchos problemas de base siguiern presentes, con la diferencia de que ahora no teniamos la excusa de poder hacer las cosas mal bajo la excusa de la urgencia de sacar el producto a produccion.
La fase 2 — Mas presión y prioridades equivocadas
Los problemas no se hicieron esperar, ya que la presión ya estaba sobre la mesa. En primera conversación con la project manager me indica que para fase 2, backend tiene que entregar 2 nuevas funcionalidades lo antes posible porque está bloqueando muchísimo trabajo para el equipo de apps y para el equipo de frontend.
¿Cuál fue mi primer error aquí? Simplemente dejarme llevar por esa presion, en lugar de haberla cuestionad y haber hablado con los leads de front end y de apps. En su lugar, me reuní con el arquitecto de soluciones, y juntos intentamos ver cómo podíamos avanzar el trabajo lo antes posible. Caso error. Creo que no diré nada en mi defensa, Salvo que lo fácil es dejarse llevar por la presión y tratar de sacar cualquier tipo de trabajo como pollo sin cabeza, con tal de satisfacer expectativas lo antes posible.
Construyendo sin requisitos
¿Tenemos requisitos? No. Solamente un par de páginas con un analisis previo hecho por el arquitecto de soluciones, el cual ha analizado lo que ha podido, en base a un par de reuniones con el cliente. Ademas de eso, tenemos el título de la nueva funcionalidad, sin ningun tipo de contenido. Y eso que lo que hacemos a nivel de backend no es difícil, es que no es difícil. Nuestra función, por lo general, simplemente es proveer de una API con diferentes endpoints que van a ser consumidos tanto por front-end como por apps y un par de integraciones con sistemas del cliente.
Pero, ¿y los requisitos?
Bajo estas circunstancias, ¿cuál seria la forma de proceder? Seguramente debi de cerrarme en banda y decir que no puedo avanzar con el trabajo hasta que no tenga documentados correctamente todos los requisitos que se esperan analizar. Pero al estar bajo presión, es difícil pensar con claridad, y tanto yo como el arquitecto de soluciones, comenzamos una ronda de reuniones con el equipo técnico del cliente para tratar de diseñar la solución de Backend. Teníamos una fuerte dependencia con ellos, ya que ellos actúan como proveedor de datos. Estos datos son enviados a nuestro lado via peticiones POST. Es decir, ellos son la fuente de datos. Por tanto, necesitábamos confirmar el modelo de datos y estructuras que nos iban a enviar, para así nosotros poder diseñar correctamente nuestras APIs. Tras un más de una semana y media sin terminar de cerrar un diseño concreto, finalmente, el manager de producto publicó la documentación referente a los requisitos. El haber tenido dicha documentación por adelantado, nos hubera ahorrado gran parte del trabajo. De hecho, el diseño de backend no se ha podido concretar hasta que hemos podido estudiar correctamente dichos requisitos.
¿Y cuál es la urgencia?
Una vez teníamos claro el modelo de datos, estructuras, etcétera, y los requisitos, ya era más o menos posible poder empezar a diseñar los contratos de las APIs. Pero ¿dónde está la prioridad? ¿donde está la urgencia? la project manager indicó que dicha nueva funcionalidad era urgente y nos indico que backend era el cuello de botella. Pero esa funcionalidad está compuesta por varios casos de uso. ¿Son todos igual de urgentes? ¿Hay uno o dos casos de uso que sean los que desbloqueen la mayor parte del trabajo, al menos a corto plazo? Son preguntas que debía haber hecho. Y aunque la presión no es buena compañera, tampoco voy a eximir mi parte de responsabilidad. No lo hice bien.
Tratando de desbloquear a otros equipos, sin conocer las prioridades
El arquitecto de soluciones y yo como tech lead, tomamos la decisión de empezar a entregar endpoints sin tener datos reales, esto es, moqueando dichas respuestas para poder desbloquear, al menos parcialmente, al equipo de frontend y de apps, para despues de una semana entregando dichos endpoints moqueados, ver como ni el equipo de Frontend ni el equipo de Apps los está utilizando. ¿Dónde estaba la urgencia, entonces? Hemos gastado recursos, en concreto dos personas, trabajando en endpoints que no tienen datos reales, para algo que en realidad podia haber esperado.
Registrando las tareas de backend
Una vez que el arquitecto y yo teníamos definido, más o menos, todo lo que había que hacer para dicha nueva funcionalidad, básicamente creamos una épica en Jira. Hicimos un breakdown de todas las tareas, donde la mayor parte de ellas se correspondía con crear un nuevo endpoint. Una vez teníamos hecho el breakdown, procedimos a crear los tickets tipo historia debajo de dicha épica. Un ticket por cada endpoint. En este punto, pusimos estimaciones y ya teníamos una valoración global en términos de esfuerzo y un listado de tareas más o menos decidido.
Y es en este punto donde procedí a contactar con el equipo de frontend. Mi idea era que ellos cogieran sus tickets y los bloquearan con los tickets de backend, que ya había creado, para poder reflejar perfectamente la dependencia. De esta manera, si ellos establecían las prioridades en sus tickets, yo podria deducir las mías. o incluso ellos poder fijar la prioridad de mis tickets de backend. Se comunicó vía Slack en hasta tres ocasiones, pero no obtenía respuesta alguna a pesar de insistir de forma reiterada durante toda una semana. Finalmente me respondio diciendo que necesitaba hacer la división de tareas de la parte de Frontend, y que después podíamos intentar hacer una reunión para casar unos tickets con otros.
Es decir, nosotros como equipo de backend no éramos el cuello de botella para nada. El primer error aquí fue del project manager por levantar esa presión señalando al equipo de backend como el cuello de botella. Cuando realmente ni siquiera el equipo de frontend sabía qué es lo que tenía que hacer. El segundo error fue mío. por haberle hecho caso y haberme dejado llevar por la presión. En lugar de esto, tendría que haberme reunido con el frontend lead. Establecido prioridades juntos.
La habitación del Backend
En mi opinión, un proyecto es como un largo pasillo, donde hay diferentes habitaciones a ambos lados. Una de las habitaciones es la habitación de Backend, y como el resto de habitaciones, hay una serie de artefactos que entran y otros que salen hacia otras habitaciones. La labor del project manager es coordinar que los artefactos que viajan desde una habitación hacia otra son los correctos, mientras que se asegura de que haya el menor número de bloqueos.
En la habitacion de backend, lo que hacemos desde el punto de vista conceptual no es tan complicado. La función del ingeniero de backend, por lo general, suele ser proveer de las APIs necesarias que serán consumidas posteriormente como fuente de datos o como controllador para ejecutar acciones, bien por una aplicación final tipo frontend u otro sistema a modo de integracion. Usamos APIs, porque es el estándar en la industria. Pero esto es simplemente una manera de definir un contrato donde un cliente final puede hacer una petición que normalmente se corresponde con un caso de uso y que devuelve una respuesta de datos estructurada. Por tanto, lo que proveemos son soluciones a nivel de capa de datos que sirven a nivel último a una aplicación final, implementando toda la lógica de negocio interna que hay detrás de dichas APIs, lo cual en numerosas ocasiones también incluye integraciones con sistemas que están fuera de nuestro ambito y de los cuales dependemos fuertemente.
¿La solución para todos los problemas?
El punto de entrada para cualquier nueva funcionalidad debe ser siempre los requisitos funcionales. Estos requisitos funcionales deben estar estructurados. Esto quiere decir, que deberían evitar la prosa excesiva y centrarse en estructurar la información. Se pueden utilizar historias de usuario para definir tanto el funcionamiento principal como los casos de borde, pero también debería quedar claro cuáles son los casos de uso, así como las funcionalidades. Siempre es bueno, por tanto, tener una página índice o diagrama de casos de uso donde se explique la estructura de dicha funcionalidad. A mí particularmente me da igual un diagrama que una tabla. Lo importante es que pueda responder preguntas como, ¿cuántos casos de uso hay? ¿Cuál es el nombre de cada caso de uso? ¿Cuál es la secuencia principal de acciones que involucra a cada caso? Todo esto abstrayendo, por supuesto, cualquier tipo de alusión a una solución técnica.
Estos requisitos deben ser especificados y validados por el equipo de negocio. En nuestro caso, la única persona con responsabilidad de negocio es el product manager. Este además debe ser también responsable de crear la épica principal, y de crear, al menos, tareas historia de alto nivel para cubrir todos y cada uno de los casos de uso. Desde mi punto de vista, este debe ser siempre el punto de partida, de manera que no solo tenemos la documentación estructurada en una Wiki tipo Confluence, sino que tenemos también cubiertos todos los casos de uso vía tickets en Jira.
Una vez ese artefacto de salida está definido, puede ser enviado a las diferentes habitaciones: frontend, backend, apps y otros. En este escenario, tanto frontend como backend están en disposición de proponer un contrato de APIs que sirva como interfaz entre ambos. Dependiendo de cómo de bien estén definidos los requisitos, en la habitación de backend podría empezar a elaborarse el artefacto correspondiente al contrato de dicha API. Pero como acabamos de indicar anteriormente, construimos APIs para satisfacer las necesidades de los clientes consumidores. Por tanto, este contrato es más un acuerdo entre ambas partes, donde frontend, o el cliente final, debe especificar qué es lo que necesita, y backend debe especificar si puede o no satisfacer esa necesidad de la manera más cómoda para dicho cliente.
Desde la perspectiva de backend, por lo general, crearemos un ticket historia por cada API, o bien subtarea, si se pueden agrupar en alguna subfuncionalidad y dependiendo de los tickets historia semilla creados por el manager de producto. Este es uno de los artefactos de salida principales de la habitación de backend. Además, al haber especificado todos estos tickets, es casi trivial poder hacer estimaciones de esfuerzo final. Por su parte, tanto el equipo de apps como de frontend también deberían de estar en disposición de crear sus propios tickets dependientes de las historias semilla de requisitos, y de bloquearse en dependencia de los tickets de backend generados previamente.
Una vez entendido desde la perspectiva de backend cuáles son las dependencias con el resto de equipos y las necesidades, ya es posible establecer prioridades correctas en dichos tickets. En este punto deberíamos de ser capaces de responder preguntas tales como, ¿cuáles de todos los tickets de backend desbloquean más trabajo para el equipo de frontend y de apps? ¿Cuál es la prioridad en las tareas de frontend y de apps, de manera que podamos identificar las dependencias correctas y las prioridades correctas de los tickets de backend?
Tomando esto como punto de partida, podemos entender qué fuente de datos y qué estructuras mínimas necesitamos, y, a partir de aquí, podemos diseñar las diferentes integraciones y modelos de datos. Por lo general, se suele hacer lo inverso. Es decir, preguntamos al proveedor de datos qué datos puede ofrecer, y en base a eso, hablamos con el equipo de frontend para ver si eso cumple sus expectativas. Es cierto que podemos atacar este problema tanto bottom up como top down, pero no deberíamos de olvidar ninguno de los dos extremos, y, por lo general, se suele olvidar que el client side es el cliente y el que necesita a backend.
Desde el punto de vista de backend, las preguntas que el tech lead debería realizarse cuando se le presenta una nueva funcionalidad a analizar son:
- ¿están todos los requisitos perfectamente definidos y estructurados en funcionalidades, subfuncionalidades y casos de uso?
- ¿Ha comenzado el equipo de apps y de frontend su análisis?
- ¿Han identificado qué endpoints son necesarios desde el punto de vista del contrato de APIs?
- ¿Tenemos identificadas cuáles son las prioridades desde el punto de vista de frontend y de apps?
- ¿Tenemos identificado cuáles son los endpoints prioritarios a desarrollar y cuánto trabajo desbloquean?
- ¿Hay tickets creados, tanto a nivel de frontend y de apps, de manera que podamos relacionar la dependencia en Jira o en sea cual sea la herramienta que utilicemos?
Bajo estas circunstancias, es posible comenzar a elaborar una propuesta de contrato de API para, posteriormente, validarla con el equipo de frontend y de apps. Una vez analizado esto, debemos encontrar cuáles son las fuentes de datos y las integraciones con otros sistemas, y entender las diferentes opciones de soluciones de diseño. Esto ya sí que recae únicamente en el equipo de backend, y la única dependencia sería con respecto al cliente que provee los datos.
Notas para el futuro
- Nunca debimos haber empezado ningún análisis sin haber tenido previamente requisitos funcionales detallados.
- Nunca debimos haber empezado el análisis sin haber tenido los requisitos funcionales estructurados en forma de casos de uso.
- Debimos habernos hecho una propuesta de contrato de API y haberla presentado a Frontend y a Apps para obtener algún tipo de aprobación.
- Debimos haber establecido prioridades con el equipo de Apps y Frontend con respecto a qué endpoints son los más importantes y cuánto trabajo desbloqueaban.
- Hay equipos donde el project manager tiene más conocimiento técnico. Otros donde parece más un mero coaching que otra cosa.
- Es tambien responsabilidad del tech lead entender el contexto de cada proyecto y asegurarse de que los artefactos que entran y salen de la habitación de Backend son los adecuados y los necesarios.
- Por lo general, el project manager debería de ayudar en esta función, pero si detectamos que no es capaz de gestionar esto, tendremos que hacerlo nosotros o la calidad del trabajo de nuestra habitación se verá degradada.