Lección 70 de 170

Un mensaje es un contrato

Curso de desarrollo de videojuegos con IA

Define un contrato de mensaje especificando el emisor, el receptor, la carga útil, el momento de entrega, la identidad de cada suceso, la garantía de entrega y el comportamiento ante fallos.

1019. Identidad de la lección

Módulo
3.3 — Eventos y mensajería
Lección
Un mensaje es un contrato
Tipo académico
Concepto
Tipo de lección
Texto
Orden
1
Tiempo estimado
30–40 minutos, incluida la práctica

Esta lección define el acuerdo entre un emisor y un receptor cuando un sistema se comunica mediante un mensaje.

1020. Objetivo de aprendizaje

Al terminar esta lección, podrás redactar y evaluar un contrato de evento completo que identifique el emisor, el receptor, la carga útil, el momento de entrega, la identidad del suceso, la garantía de entrega y el comportamiento ante fallos.

1021. Por qué importa

Un mensaje crea una dependencia entre sistemas. Si el receptor interpreta la carga útil de forma distinta al emisor, el sistema puede repetir efectos, mostrar información desactualizada o producir cambios de estado difíciles de explicar. Un contrato escrito permite examinar esa dependencia antes de implementarla y proporciona límites precisos a un asistente de programación con IA.

1022. Conocimientos previos

Debes poder:

  • distinguir entre escritores autoritativos y lectores mediante la hoja de propiedad del estado de 3.2 L2 — Build a state-ownership sheet;
  • identificar qué sistema controla una transición de estado;
  • describir un cambio de estado sin confundirlo con su presentación visual.

No necesitas conocer una biblioteca concreta de mensajería. Esta lección trata sobre el acuerdo entre sistemas, no sobre un mecanismo de transporte específico.

1023. Concepto central

Un contrato de evento es el acuerdo explícito mínimo que permite que un sistema comunique a otro que ocurrió algo significativo.

Usa el contrato S-R-P-T-F:

  1. Emisor (sender): ¿Qué sistema emite el mensaje y después de qué decisión autoritativa?
  2. Receptor (receiver): ¿Qué sistemas pueden reaccionar y qué se les permite hacer?
  3. Carga útil (payload): ¿Qué campos se incluyen, qué significa cada uno y cuál identifica este suceso concreto?
  4. Momento y orden de entrega (timing): ¿Cuándo se emite, puede llegar tarde o fuera de orden y qué garantía de entrega existe?
  5. Comportamiento ante fallos (failure behavior): ¿Cómo se tratan los duplicados y los datos inválidos? ¿Qué hace el emisor, el transporte o el proceso de conciliación si el mensaje no llega?

El contrato solo está completo cuando otra persona puede predecir el comportamiento permitido sin leer la implementación del emisor.

1024. Términos en lenguaje sencillo

  • Un identificador estable es un valor que sigue refiriéndose a la misma entidad o al mismo suceso allí donde se procese el mensaje.
  • Un identificador de suceso, como eventId o transitionId, distingue una cosa concreta que ocurrió. No es solo el identificador de la entidad implicada.
  • Una marca temporal de sesión indica cuándo ocurrió algo según el reloj de la sesión actual. Por sí sola no demuestra el orden de entrega.
  • Una entrega tardía ocurre cuando el mensaje llega más tarde de lo esperado.
  • Una entrega fuera de orden ocurre cuando los mensajes llegan en un orden distinto de aquel en que sucedieron los eventos.
  • El tratamiento idempotente hace que procesar varias veces el mismo suceso produzca el mismo resultado protegido que procesarlo una sola vez. El receptor reconoce la repetición mediante un identificador del suceso.
  • Una garantía de entrega indica qué promete el emisor o el transporte: por ejemplo, conservar y reintentar, reintentar hasta un límite de tiempo o realizar una entrega sin garantía y conciliar después con el estado autoritativo.

La identidad de una entidad y la identidad de un suceso no son lo mismo. Una compuerta puede abrirse, cerrarse y volver a abrirse. Las dos aperturas afectan al mismo gateId, pero son sucesos distintos y necesitan identificadores de transición diferentes.

1025. Hecho, reacción y propiedad del estado

Mantén separadas estas ideas:

  • Hecho: lo que el emisor afirma que ocurrió.
  • Reacción: lo que el receptor puede hacer con ese hecho.
  • Propiedad del estado (ownership): qué sistema conserva la responsabilidad sobre el estado relacionado.

Un evento debe comunicar un hecho ya confirmado, como ContractAccepted o ItemDelivered. No debe convertirse silenciosamente en un segundo dueño del estado. El escritor autoritativo valida y confirma el cambio. El receptor solo puede actualizar una vista, programar otra acción o registrar evidencia según lo permita el contrato.

1026. Ejemplo concreto

Imagina que GateSystem controla si una compuerta está abierta. Tras validar una interacción, confirma una transición de cerrada a abierta y emite GateOpened.

Una descripción incompleta sería:

GateSystem envía un evento de apertura a ObjectiveSystem.

Un contrato utilizable sería:

Evento: GateOpened

Emisor:
  GateSystem, después de validar la interacción y confirmar una transición
  concreta de cerrada a abierta.

Receptor:
  ObjectiveSystem puede actualizar la instancia de objetivo correspondiente.
  No puede modificar el estado autoritativo de la compuerta.

Carga útil:
  transitionId: identificador estable de esta apertura concreta;
                string obligatorio.
  gateId: identificador estable de la entidad compuerta; string obligatorio.
  openedBy: identificador estable del actor responsable; string obligatorio.
  openedAt: marca temporal de sesión de la transición; number obligatorio.

Momento y orden de entrega:
  Emitir después de confirmar el estado autoritativo. El mensaje puede llegar
  tarde o fuera de orden. El transporte reintenta hasta recibir confirmación
  o alcanzar el límite de tiempo especificado.

Comportamiento ante fallos:
  ObjectiveSystem elimina duplicados mediante transitionId dentro de la
  instancia de objetivo actual. Repetir el mismo transitionId no concede
  progreso dos veces. Una apertura posterior de la misma compuerta tendrá un
  transitionId nuevo y no se descarta solo porque gateId ya se haya visto.
  Una compuerta desconocida o la ausencia de campos obligatorios se registra
  y no modifica el progreso. Si se agotan los reintentos, el transporte
  informa del fallo y ObjectiveSystem concilia su vista con el estado
  autoritativo de la compuerta y del objetivo.

Eliminar duplicados mediante gateId sería incorrecto porque podría ocultar una apertura válida posterior. La idempotencia protege el efecto de un suceso concreto; no prohíbe todos los sucesos futuros relacionados con la misma entidad.

1027. Un fallo de entrega no corresponde solo al receptor

El receptor puede rechazar datos mal formados o reconocer un duplicado únicamente después de recibir el mensaje. No puede reaccionar ante un mensaje que nunca le llega.

Por eso, una decisión sobre falta de entrega debe indicar qué capa es responsable y qué garantiza. Algunas estrategias válidas son:

  • el emisor reintenta hasta recibir confirmación o alcanzar un límite de tiempo;
  • una cola persistente conserva el mensaje hasta poder entregarlo;
  • el sistema registra el límite de tiempo agotado y lo expone mediante registros o monitorización;
  • el receptor concilia más tarde su vista con el estado autoritativo;
  • el contrato declara explícitamente una entrega sin garantía cuando perder la actualización es aceptable.

Elige una estrategia acorde con las consecuencias de la pérdida. No escribas únicamente “el receptor gestiona la falta de entrega”.

1028. Práctica guiada

Redacta un contrato para esta situación:

InventorySystem acepta una recogida, confirma el cambio de inventario e informa a HUDSystem. La interfaz debe actualizarse, pero no debe añadir el objeto al inventario por su cuenta.

El contrato debe indicar:

  • el emisor y la decisión que ocurre antes de emitir;
  • la reacción permitida al receptor;
  • cada campo obligatorio y su significado;
  • un identificador de este suceso concreto de recogida;
  • cuándo se emite y si puede llegar tarde o fuera de orden;
  • el ámbito usado para detectar duplicados;
  • el tratamiento de mensajes mal formados;
  • la estrategia del emisor, del transporte o de conciliación si no hay entrega.

No elimines duplicados usando solo itemId: una misma entidad o un mismo tipo de objeto puede intervenir en más de un cambio de inventario válido.

1029. Contrato de referencia y comparación

Compara tu borrador con esta referencia compacta:

Evento: InventoryChanged

Emisor:
  InventorySystem, después de confirmar la recogida aceptada.

Receptor:
  HUDSystem puede refrescar la presentación del inventario.
  No puede modificar el inventario.

Carga útil:
  pickupEventId: identificador de este suceso de recogida; obligatorio.
  itemId: identificador del objeto o de su definición; obligatorio.
  inventoryVersion: versión autoritativa posterior al cambio; obligatoria.
  quantityAfter: cantidad que debe mostrarse tras el cambio; obligatoria.

Momento y orden de entrega:
  Emitir después de confirmar. La entrega puede retrasarse o llegar fuera de
  orden. Reintentar hasta recibir confirmación o alcanzar el límite de tiempo.

Comportamiento ante fallos:
  HUDSystem elimina duplicados mediante pickupEventId durante la sesión.
  No elimina duplicados mediante itemId.
  Ignora una inventoryVersion anterior para no hacer retroceder la interfaz.
  Rechaza cargas mal formadas y registra el motivo.
  Si se agota el tiempo de reintento, solicita o recibe una instantánea
  autoritativa del inventario y actualiza la interfaz desde ese estado.

La referencia no es la única carga útil defendible. Un contrato también puede enviar:

  • una instantánea completa del inventario, que ocupa más pero es sencilla de representar; o
  • un cambio compacto acompañado de inventoryVersion, que ocupa menos pero exige reglas de orden y conciliación.

Ambas estrategias son aceptables cuando el contrato explica sus compensaciones y su comportamiento ante fallos.

1030. Evaluación práctica

Completa Reparar un contrato de evento con S-R-P-T-F. Tendrás que corregir un contrato de inventario incompleto incorporando la identidad del suceso, las garantías de momento y entrega, los límites de propiedad del estado y las decisiones ante fallos. La evaluación se puntúa mediante las cinco partes de S-R-P-T-F.

1031. Lista de validación

Antes de entregar un contrato, comprueba cada punto sin depender del formato de una tabla:

  • Emisor: nombra el sistema autoritativo e indica que emite después de confirmar el cambio.
  • Receptor: define la reacción permitida e impide modificaciones no autorizadas del estado.
  • Carga útil: define los campos obligatorios e incluye un identificador del suceso.
  • Momento de entrega: indica cuándo se emite, si puede retrasarse o desordenarse y qué garantía existe.
  • Fallos: define el ámbito de los duplicados, el tratamiento de datos inválidos y la responsabilidad por falta de entrega.

1032. Ideas clave

  • Un mensaje es un contrato, no solo una etiqueta o una llamada.
  • Un contrato completo especifica emisor, receptor, carga útil, momento de entrega y comportamiento ante fallos.
  • Los identificadores de entidad y de suceso cumplen funciones diferentes.
  • La idempotencia impide aplicar dos veces el efecto protegido de un mismo suceso; no debe ocultar sucesos válidos posteriores de la misma entidad.
  • El receptor gestiona los mensajes que llegan. El emisor, el transporte, los límites de tiempo o la conciliación cubren los mensajes que no llegan.
  • El escritor autoritativo conserva la propiedad del estado.

1033. Siguiente lección

Continúa con 3.3 L2 — Evitar el event soup.

1034. Comprobación

Responde estas preguntas por tu cuenta antes de leer las respuestas.

¿Qué conjunto contiene las cinco partes del contrato de evento S-R-P-T-F?

  • A. Estado, regla, presentación, respuesta y reintento
  • B. Emisor, receptor, carga útil, momento de entrega y comportamiento ante fallos
  • C. Autor, componente, escena, entrada y salida
  • D. Disparador, animación, sonido, puntuación y cámara
Mostrar respuesta y explicación

Respuesta: Emisor, receptor, carga útil, momento de entrega y comportamiento ante fallos

Por qué: S-R-P-T-F abarca quién comunica, quién puede reaccionar, qué datos se comunican, cuándo y bajo qué condiciones de entrega, y cómo se gestionan los fallos.

Una compuerta puede abrirse, cerrarse y volver a abrirse. ¿Qué campo debe usar el receptor para reconocer la repetición de un suceso GateOpened concreto?

  • A. Solo gateId
  • B. Un transitionId único para ese suceso de apertura confirmado
  • C. El nombre del componente receptor
  • D. El tipo de mensaje sin ningún identificador
Mostrar respuesta y explicación

Respuesta: Un transitionId único para ese suceso de apertura confirmado

Por qué: gateId identifica la entidad, no una apertura concreta. Un transitionId único permite ignorar una repetición sin descartar una apertura válida posterior de la misma compuerta.

¿Qué cláusula del contrato trata correctamente un mensaje que nunca llega al receptor?

  • A. El receptor rechaza el mensaje antes de recibirlo.
  • B. El receptor supone que la entrega siempre es inmediata.
  • C. El transporte reintenta hasta agotar el tiempo, informa del fallo y la vista se concilia después con el estado autoritativo.
  • D. El receptor elimina todos los mensajes que compartan el mismo identificador de entidad.
Mostrar respuesta y explicación

Respuesta: El transporte reintenta hasta agotar el tiempo, informa del fallo y la vista se concilia después con el estado autoritativo.

Por qué: Un receptor no puede gestionar un mensaje que nunca recibe. La falta de entrega debe asignar responsabilidad al emisor, al transporte, a la supervisión de límites de tiempo, al almacenamiento persistente o a una conciliación posterior.

Apoyar