Comunicar con el equipo: acordar el comportamiento antes de programarlo
El diagrama deja de ser una herramienta de ingeniería cuando se convierte en el objeto compartido donde diseño, producto e ingeniería acuerdan qué hace el sistema. La lección propone tratar el statechart como objeto frontera en el sentido de Star y Griesemer, describe un protocolo de sesión de modelado que produce como acta el propio esqueleto de la máquina, cataloga los estados que el diseño de pantallas sistemáticamente omite, y muestra cómo cada camino del modelo se convierte en criterio de aceptación verificable.
El desacuerdo sobre el comportamiento de un producto no desaparece: se aplaza. Se aplaza desde la reunión de definición, donde nadie preguntó qué pasa si el usuario vuelve atrás a mitad del pago, hasta el día en que un ingeniero se topa con la ambigüedad y la resuelve solo, con el criterio que tenga a mano y sin dejar rastro de que ha tomado una decisión de producto. Ese aplazamiento es el impuesto más caro del desarrollo de software, porque el precio de resolver una ambigüedad crece con todo lo que se ha construido sobre ella. Lo que sigue no es una lección sobre diagramas bonitos para presentaciones, sino sobre un uso muy concreto del statechart: como superficie donde el desacuerdo aflora temprano, con coordenadas, delante de las personas que pueden resolverlo.
- Usar el statechart como objeto frontera legible a la vez por diseño, producto e ingeniería.
- Conducir una sesión de modelado cuya acta sea el propio esqueleto de la máquina y no un documento paralelo.
- Detectar sistemáticamente los estados que el diseño de pantallas omite y forzar una decisión sobre cada uno.
- Convertir los caminos del modelo en criterios de aceptación verificables y firmados antes de implementar.
El diagrama como objeto frontera
En 1989 Susan Leigh Star y James Griesemer describieron los objetos frontera: artefactos que habitan varios mundos sociales a la vez, lo bastante plásticos para que cada comunidad los use según sus necesidades y lo bastante robustos para conservar una identidad común. Un mapa de un parque natural es su ejemplo canónico: el biólogo, el cazador y el administrador ven cosas distintas en él y sin embargo hablan del mismo territorio. El statechart funciona exactamente así. Para diseño es la secuencia de pantallas y sus transiciones; para producto son las reglas de negocio y lo que está permitido; para ingeniería es la especificación de implementación. Nadie tiene que aprender el lenguaje del otro porque el artefacto ya habla los tres.
La plasticidad del objeto frontera tiene un límite que conviene respetar: funciona mientras el modelo se mantenga en el plano del comportamiento observable y no descienda al de la implementación. En cuanto en el lienzo aparecen estados que representan pasos internos —esperando la respuesta del segundo microservicio, reintentando la conexión con la caché—, diseño y producto dejan de reconocerse en el artefacto y vuelven a delegarlo en ingeniería, que es exactamente lo que se quería evitar. Si esos estados internos son necesarios, van en una submáquina propia; el modelo compartido conserva un único estado visible que los engloba.
Eso lo distingue de los dos candidatos habituales. Un documento de requisitos en prosa es robusto pero nada plástico: solo lo lee bien quien lo escribió, y su corrección no se puede comprobar. Un prototipo interactivo es plástico pero no robusto: enseña un camino feliz y calla sobre todos los demás, que es donde vive el trabajo. El statechart es el único artefacto de la mesa que muestra a la vez lo que ocurre y lo que no puede ocurrir, y que además es ejecutable, de modo que la discusión se puede zanjar recorriéndolo en lugar de recordándolo.
Hay un efecto secundario que conviene aprovechar deliberadamente: los nombres de los estados se convierten en el vocabulario común del equipo, en el sentido que Eric Evans llamó lenguaje ubicuo. El nombre que se pone a un estado en el lienzo termina en el código, en las trazas de inspección, en los mensajes de error, en los nombres de las pruebas y en la conversación del canal de soporte. Por eso nombrar es un acto de diseño de producto y no una tarea técnica: pendiente_de_verificacion y bloqueado describen la misma situación técnica y comunican promesas distintas al usuario, y esa diferencia debe decidirse en la mesa donde está producto, no tres semanas después en una revisión de código.
La mayoría de los equipos de diseño ya producen diagramas de flujo con cajas y flechas, así que la propuesta no les resulta ajena. La diferencia técnica es una sola y hay que explicitarla en la primera sesión: en un flujo de diseño las flechas suelen etiquetarse con la acción de interfaz que las provoca, mientras que en un statechart se etiquetan con el evento del dominio. La distinción parece menor y no lo es, porque un mismo evento puede provenir de tres botones distintos y un mismo botón puede significar cosas distintas según el estado. Modelar por eventos y no por pulsaciones es lo que hace el modelo estable frente a los rediseños.
El protocolo de la sesión de modelado
Una sesión de modelado bien conducida dura entre sesenta y noventa minutos, reúne a una persona de producto, una de diseño y una o dos de ingeniería, y produce como acta el esqueleto de una máquina, no un documento sobre ella. El orden importa porque cada paso desbloquea el siguiente.
Enumerar los modos
Los estados excluyentes con nombre de dominio, uno solo activo a la vez. Si dos parecen simultáneos, o son regiones paralelas o uno de ellos no era un estado.
Enumerar los eventos
Lo que puede hacer el usuario y también lo que puede hacer el mundo: respuestas, caducidades, pérdidas de conexión, cambios en otra pestaña.
Rellenar la matriz
Para cada par de modo y evento, decidir qué ocurre. Se hace en voz alta y se escribe en el momento, sin dejar celdas para después.
Simular delante de todos
Recorrer el modelo con clics es donde producto descubre que lo que pidió no es lo que quería, y aún es gratis cambiarlo.
flowchart TD A[Enumerar los modos excluyentes] --> B[Enumerar los eventos del usuario y del mundo] B --> C[Rellenar la matriz de modo por evento] C --> D[Decidir cada celda sin dejar ninguna en blanco] D --> E[Nombrar los estados nuevos que han aparecido] E --> F[Simular delante del grupo] F -->|aparece una sorpresa| C F -->|nadie se sorprende| G[El modelo es el acta y entra al repositorio]
El paso uno esconde una criba que vale por sí sola lo que dura la reunión: al intentar enumerar modos excluyentes, el grupo descubre que la mitad de lo que llamaba estados eran datos. Que el carrito tenga tres artículos, que el usuario sea premium o que el formulario esté a medias no son modos, son valores del contexto; el modo es si el carrito está en edición, en pago o cerrado. Separar el modo del dato es la operación conceptual más difícil de la sesión y también la más productiva, porque los productos que acumulan estados fantasma —cargandoConDatosViejosDeUsuarioPremium— sufren exactamente de no haberla hecho.
El paso tres es el que hace el trabajo, y merece una herramienta explícita: la matriz de estado por evento, que es la tabla de transiciones del nivel 1 usada como instrumento de reunión. Su virtud es que hace visible el hueco: una celda vacía es una pregunta que alguien tiene que responder ahora, no una omisión que nadie percibe. La regla de oro es que ninguna celda puede quedar en blanco ni marcada como no aplicable; hay que elegir explícitamente entre ignorar el evento, encolarlo, rechazarlo con un mensaje o transicionar.
| Estado | PAGAR |
CANCELAR |
CADUCA_SESION |
|---|---|---|---|
listo |
va a cobrando |
va a cancelado |
va a expirado |
cobrando |
ignorar, evita el doble cobro | pedir confirmacion primero | encolar | ignorar, hay que decidirlo |
fallido |
va a cobrando, reintento |
va a cancelado |
va a expirado |
hecho |
ignorar, ya es final | ignorar, ya es final | ignorar, el pago ya existe |
Sobre el tamaño del grupo, la experiencia es consistente: cuatro personas funcionan, ocho no. La sesión exige decidir en voz alta y con rapidez, y por encima de cierto número el coste de coordinar la conversación supera al de modelar. Si hay más partes interesadas de las que caben, se modela con el grupo pequeño y se presenta el resultado simulándolo, que ocupa diez minutos y provoca las objeciones importantes igual de bien. Lo que no funciona nunca es enviar el modelo por escrito y pedir comentarios: sin la simulación delante, nadie descubre lo que falta.
Esa celda con dos opciones separadas por una barra es el patrón que más valor produce en la sesión: no es un fallo del modelo, es una decisión de producto que acaba de hacerse visible tres semanas antes de lo habitual. Qué debe pasar si la sesión caduca mientras el cobro está en vuelo es una pregunta con consecuencias legales y de soporte que nadie iba a formular mirando un prototipo, y que la matriz obliga a formular porque hay una casilla vacía en el centro de la pantalla compartida.
Si la sesión termina con un documento que alguien deberá transcribir a código, se ha reintroducido la deriva que todo el nivel intenta eliminar. Conduce la sesión con el lienzo del estudio abierto y proyectado, escribe los estados y las transiciones mientras se hablan, y cierra simulando el flujo delante del grupo. El artefacto que sale de la reunión debe ser el mismo que entrará en el repositorio, y quien conduce debe resistir la tentación de anotar aparte lo que no le da tiempo a modelar: si no cabe en el modelo, no se acordó.
Los estados que el diseño olvida
Un catálogo de pantallas describe el sistema cuando todo va bien, porque la maqueta se dibuja sobre datos que existen y respuestas que llegan. El repertorio de situaciones que faltan es sorprendentemente estable entre productos y entre equipos, hasta el punto de que conviene llevarlo impreso a la sesión y recorrerlo como lista de comprobación antes de dar por cerrado el modelo.
Latencia con matices
No basta con cargando: hay diferencia entre la primera carga, la recarga con datos viejos en pantalla y la espera que se alarga tanto que hay que ofrecer cancelar.
Vacío y parcial
Sin resultados, con resultados incompletos, con una parte del formulario ya guardada. Cada uno pide una pantalla y una salida distintas.
Caducidad y reentrada
La sesión expira a mitad, el usuario vuelve atrás, abre dos pestañas o recupera el flujo al día siguiente. Aquí es donde la historia del nivel 14 se gana su sitio.
Fallo con clases
Un error de red no es un error de validación ni un rechazo del banco. Si los tres caen en el mismo estado, el producto miente al usuario sobre qué debe hacer.
Conviene además introducir en la sesión una pregunta que casi nadie hace y que reordena el modelo entero: qué eventos puede emitir el mundo sin que el usuario haga nada. La respuesta suele incluir la respuesta del servidor, el vencimiento de un plazo, la desconexión, una notificación entrante o el mismo usuario actuando desde otro dispositivo. Los productos que fallan de formas raras suelen fallar exactamente ahí, porque su modelo mental implícito supone que el sistema solo cambia cuando alguien toca la pantalla, y ese supuesto es falso en cualquier aplicación conectada.
Hay una asimetría en el catálogo que conviene explotar: los estados olvidados casi nunca son de camino feliz, y por tanto casi nunca los reclama nadie hasta que un usuario real se topa con ellos. Nadie escribe una petición de soporte diciendo que falta el estado de espera larga con opción de cancelar; escribe que la aplicación se le quedó colgada. Esto significa que la deuda de estados no aparece en el flujo habitual de peticiones de producto, y que la sesión de modelado es prácticamente el único momento en que puede detectarse antes de convertirse en incidencias.
Hay un beneficio adicional para diseño que rara vez se anticipa y que sirve para ganarse a la disciplina más escéptica: la accesibilidad se modela junto al comportamiento. Cada estado tiene un anuncio para el lector de pantalla, una gestión del foco y una decisión sobre si el contenido cambia de forma disruptiva. Cuando los estados están enumerados, esas decisiones son una columna más de la matriz, en lugar de una revisión que llega al final y descubre que faltan cuatro pantallas.
Del acuerdo al criterio de aceptación
El modelo acordado no termina en el acta: se convierte en el criterio con el que se verificará el trabajo. Un camino a través de la máquina —una secuencia de eventos desde el estado inicial hasta uno terminal— es exactamente lo que un criterio de aceptación intenta expresar en prosa, con la diferencia de que el camino es ejecutable y la prosa no. El nivel anterior mostró cómo generar esos caminos desde el modelo; aquí se cobra el uso organizativo de esa capacidad.
// Los caminos del modelo son la lista de criterios de aceptacion.
import { getShortestPaths } from '@xstate/graph'
import { pago } from './pago'
const caminos = getShortestPaths(pago, {
events: [{ type: 'PAGAR' }, { type: 'CANCELAR' }, { type: 'CADUCA_SESION' }],
})
for (const camino of caminos) {
const eventos = camino.steps.map((s) => s.event.type).join(' luego ')
console.log(`${eventos} termina en ${JSON.stringify(camino.state.value)}`)
}
Antes de nada hay que enseñar a leer el diagrama, y lleva menos de lo que la gente teme. Bastan tres convenciones dichas en voz alta al empezar: una caja es una situación en la que el sistema puede estar y solo puede estar en una a la vez, una flecha es algo que ocurre y su etiqueta es el nombre de eso que ocurre, y la ausencia de flecha significa que ese algo no tiene efecto en esa situación. Con esas tres frases cualquier persona de producto o de diseño participa de pleno derecho. Quien introduce el statechart empezando por la jerarquía, las regiones paralelas o la historia pierde a la sala en noventa segundos y concluye erróneamente que el formalismo no es para equipos mixtos.
Conviene generar los caminos con el conjunto de eventos acordado en la sesión y no con todos los posibles, porque el objetivo aquí no es la cobertura exhaustiva —eso pertenece al nivel de pruebas— sino producir una lista que una persona de producto pueda leer entera sin perder la paciencia. Diez o quince caminos nombrados en lenguaje de dominio son revisables; ciento cuarenta no lo son y provocan que nadie los mire, que es peor que no haberlos generado.
La lista que imprime ese fragmento se puede pegar en la tarjeta de trabajo y revisarla con producto en cinco minutos. Su valor no es la automatización, que es modesta, sino el cambio de carga de la prueba: en lugar de que alguien invente los casos que se le ocurren, el modelo enumera los que existen y la conversación pasa a ser cuáles de estos caminos importan y cuáles se aceptan sin cubrir. Es una discusión mucho más honesta que la habitual, porque parte de un inventario completo en lugar de una muestra sesgada por lo que cada cual recuerda.
La primera sesión de modelado en un equipo que no la ha hecho nunca suele durar el doble de lo previsto y dejar a alguien incómodo, porque las preguntas de la matriz revelan que dos personas creían cosas distintas sobre el producto que llevan meses construyendo. Esa incomodidad es el rendimiento de la práctica, no su coste: el conflicto existía ya y se iba a pagar igualmente, con la única diferencia de que se habría pagado más tarde, en forma de reescritura, y sin que nadie supiera identificar la decisión que lo originó. Quien conduce la sesión debe decirlo en voz alta al empezar, para que el descubrimiento se lea como un logro y no como un fracaso.
Durante décadas la especificación de un producto ha sido un texto que alguien escribe y los demás leen, y ese formato arrastra dos vicios que ninguna metodología ha conseguido corregir. El primero es que la prosa no tiene complemento: un documento enumera lo que debe ocurrir y calla infinitamente sobre lo que no, de modo que no existe forma de saber si está terminado ni de demostrar que le falta un caso. El segundo es que la prosa tiene un autor, y por tanto un dueño, y por tanto una asimetría: quien la escribió sabe lo que quiso decir y los demás interpretan, con lo que cada malentendido se descubre cuando ya está construido y su corrección es un cambio de alcance en lugar de una precisión. El statechart derriba las dos cosas a la vez. Al ser finito, tiene complemento: se puede señalar la celda vacía, contar los huecos y afirmar con sentido que el modelo está completo respecto a un conjunto de eventos. Y al ser legible y ejecutable por las tres disciplinas, deja de tener un dueño; nadie interpreta, todos recorren el mismo objeto y observan el mismo resultado. Lo que se está sustituyendo aquí no es una herramienta de documentación por otra mejor, sino un régimen entero de coordinación: el de escribir, repartir y esperar a que se entienda, por el de construir un objeto delante de todos y comprobar juntos qué hace. La consecuencia práctica más notable es que las conversaciones difíciles se adelantan. Un equipo que modela junto discute el día uno lo que otro equipo discutirá el día sesenta, y la diferencia entre ambos no la marca el talento ni la herramienta, sino que uno tenía una superficie donde las omisiones tenían coordenadas y el otro tenía un documento donde no las tenían.
- Elige un flujo en el que ingeniería haya tenido que decidir por su cuenta algo que era una decisión de producto. Ese es el mejor candidato para la primera sesión.
- Prepara la matriz con los modos en filas y los eventos en columnas, incluyendo al menos tres eventos que no origina el usuario sino el mundo.
- Conduce la sesión con el lienzo proyectado y prohíbete anotar fuera del modelo. Marca cada celda con la decisión tomada y deja escritas las que queden a dos opciones.
- Recorre el catálogo de estados olvidados y comprueba cuántos faltaban en el diseño original. Anota el número: es la medida del valor de la sesión.
- Cierra simulando el flujo completo delante del grupo y recoge cada sorpresa que se manifieste en voz alta.
- Genera los caminos del modelo, conviértelos en la lista de criterios de aceptación de la tarjeta y pide a producto que marque cuáles se aceptan sin cubrir y por qué.