Monday, July 01, 2024

Decidir lo más tarde Posible: Limites de Producto

Como mencionamos en el artículo anterior de la serie sobre Lean Software Development, continuaremos explorando técnicas que nos permiten tomar decisiones lo más tarde posible.

Empezamos por definir sistemáticamente Limites de Producto.

Al desarrollar un incremento de la solución que estamos implementando, es fundamental establecer límites concretos en todos los parámetros que puedan introducir complejidad. Esto nos permite centrarnos en lo que aporta valor ahora y posponer soluciones más sofisticadas, evitando el coste y la complejidad añadida. Con el tiempo, esos límites irán cambiando y nos obligarán a modificar la solución, pero con esta aproximación podremos decidir cada solución lo más tarde posible y evitar hasta ese momento el coste de desarrollo y evolución de esa solución más compleja.


Es crucial que al definir un límite, este se incluya en el código o solución para que, si se supera, la aplicación se comporte de manera controlada, avisando al equipo y, posiblemente, al usuario.


Ejemplos de límites que he usado:

  • Número de clientes/usuarios totales.
  • Número de clientes/usuarios concurrentes.
  • Tamaño máximo de ficheros que se pueden subir al sistema.
  • Cuotas por usuario (almacenamiento, requests, número de entidades, etc.).
  • Valores numéricos por cualquier concepto de negocio (del problema).
  • Tiempos de respuesta a las distintas peticiones.
  • Resoluciones/Dispositivos para la IU

Si no definimos claramente estos límites de manera numérica, estamos abriendo la puerta al diseño especulativo para resolver situaciones que aún no enfrentamos.


Ejemplos de uso de límites para "decidir lo más tarde posible"

Conocer y definir el número total de clientes en varias ocasiones me ha permitido ofrecer soluciones muy sencillas para la persistencia, que nos han sido útiles durante meses antes de necesitar cambios. Por ejemplo, si el número de usuarios es pequeño, usar persistencia en fichero y cargar la información a memoria es factible. También nos permite usar soluciones tipo SQLite y posponer la decisión de meter un motor de BD independiente.



Al limitar el tamaño de las solicitudes (en cuanto a volumen) y definir los escenarios de conexión, podemos ofrecer soluciones robustas y simples, procesando las solicitudes de forma síncrona. Esto permite posponer la necesidad de tener una solución asíncrona. Como ejemplo, en una ocasión teníamos que aceptar que el usuario subiese ficheros al sistema; la primera implementación solo permitía ficheros muy pequeños, esto nos permitió hacer una implementación sencilla y tener feedback muy rápido (menos de 2 días). Pasadas unas semanas, una vez que vimos que tenía sentido la funcionalidad, mejoramos la implementación para soportar ficheros más grandes.


En varias ocasiones hemos enfrentado situaciones donde cada usuario acumulaba almacenamiento (archivos/objetos). En estos casos, el definir un límite de producto para el total de almacenamiento para todos los usuarios, otro límite para cada usuario y otro límite para definir cuándo teníamos que empezar a preocuparnos por este problema, nos ayudó a posponer la implementación de cualquier medida de control y gestión de este almacenamiento hasta que se llegase a cualquiera de los límites definidos.



Para ilustrar el uso sistemático de estos límites con un ejemplo concreto, en Alea Soluciones lanzamos un nuevo producto de gestión/control de una red de fibra y los routers de los clientes finales en menos de 3 meses. Sabíamos que nuestros clientes en ese momento no tenían más de 1000-2000 usuarios. Sabíamos que los operadores del sistema de gestión no eran más de 2-3 personas concurrentes. Sabíamos que para tener más usuarios nuestros clientes tenían en muchos casos que desplegar fibra hasta la casa o al menos ir a la casa del usuario a instalar el router; esto implicaba que no era posible que creciesen a más de 2-5 usuarios por semana. Con este contexto, la primera versión del sistema inicial de gestión era un servidor web que procesaba todo de forma síncrona y con la información de usuarios en memoria y que simplemente persistía los cambios a un fichero cuando se necesitaba. Esto permitió que dedicásemos mucho tiempo adicional al resto de componentes del sistema (integración con cabeceras de fibra, sistema de configuración remota de los routers, sistema de monitorización de los routers, etc.). Evidentemente, el sistema fue evolucionando y fuimos mejorando ese sistema, pero siempre esperando al último momento responsable para cada decisión de introducir nueva tecnología.


Otro ejemplo sencillo es en ClarityAI, donde para crear un chat ops en Slack que ofreciera algunas capacidades internas de la plataforma, se definieron ciertos límites, tanto en tiempos de respuesta máximos como en volumen de información tratada. Al definir un tiempo de respuesta máximo alto (2s) pero menor del soportado por slack para la respuesta sincrona a comandos de slack (3s), pudimos posponer bastante tiempo la implementación de una solución asincrona. Esa aplicación trabaja con información de inventario de componentes técnicos (repositorios de código, repositorios docker, etc) y de equipos y personas. Vimos que nos era fácil definir unos maximos para cada uno de los elementos y vimos que en todos los casos el máximo estaba por debajo de 1000 elementos. Estos limites nos permitieron evitar bastante complejidad, simplemente apoyandonos en un backend NoCode (Airtable) como BD, que además nos proporcionaba un frontal de administración básico. Sabemos perfectamente que cuando superemos esos limites, tendremos que pensar en una solución más sofisticada y escalable, pero posponer esa decisión nos ha permitido desarrollar muy rápido en esa aplicación durante más de dos años y medio.


Recursos Relacionados:

No comments: