Modelo Ejecutable con Markdown: Specification by Example aplicada al dominio

Una de las ideas más potentes de Specification by Example es simple: las reglas del negocio no deben quedar en documentos ambiguos, sino en ejemplos concretos que puedan ejecutarse. Si bien este libro se escribio antes que  la IA generativa tuviera la visibilidad que tiene hoy, sigue teniendo mucha vigencia. 

Si combinamos esto con un enfoque model-driven, podemos ir un paso más allá: definir el modelo de datos, las reglas y los escenarios de aceptación en un único Markdown ejecutable.

Ese archivo puede ser:

  • Legible por negocio
  • Procesable por una herramienta
  • Generador de código
  • Generador de tests automáticos
  • Documentación viva

Ejemplo: Sistema de Gestión de Pedidos

1️⃣ Modelo de Datos

model:
  entities:

    - name: Cliente
      attributes:
        - { name: ClienteId, type: int, key: true }
        - { name: Nombre, type: string, required: true }
        - { name: Email, type: string }

    - name: Pedido
      attributes:
        - { name: PedidoId, type: int, key: true }
        - { name: Fecha, type: date }
        - { name: Estado, type: enum[Borrador,Confirmado,Cancelado], default: Borrador }
        - { name: ClienteId, type: int, foreignKey: Cliente }
        - { name: Total, type: decimal, derived: true }

    - name: ItemPedido
      attributes:
        - { name: ItemId, type: int, key: true }
        - { name: PedidoId, type: int, foreignKey: Pedido }
        - { name: ProductoId, type: int }
        - { name: Cantidad, type: decimal, required: true }
        - { name: PrecioUnitario, type: decimal, required: true }
        - { name: Subtotal, type: decimal, derived: true }


2️⃣ Reglas de Negocio

rules:

  - name: SubtotalCalculation
    entity: ItemPedido
    expression: Subtotal = Cantidad * PrecioUnitario

  - name: PedidoTotalCalculation
    entity: Pedido
    expression: Total = sum(ItemPedido.Subtotal where PedidoId = Pedido.PedidoId)

  - name: PedidoDebeTenerItems
    entity: Pedido
    validation: count(ItemPedido where PedidoId = Pedido.PedidoId) > 0
    error: "El pedido debe tener al menos un ítem"

  - name: PedidoNoPuedeConfirmarseConTotalCero
    entity: Pedido
    when: Estado changes to Confirmado
    validation: Total > 0
    error: "El pedido no puede confirmarse con total cero"

3️⃣ Escenarios Ejecutables

Estos ejemplos funcionan como tests de aceptación. Si cambian las reglas y estos escenarios fallan, sabemos que rompimos el contrato del sistema.

Escenario: Pedido sin ítems

scenario: PedidoSinItems
given:
  Pedido:
    PedidoId: 1
    Estado: Borrador

when:
  action: validar

then:
  error: "El pedido debe tener al menos un ítem"
Escenario: Cálculo correcto del total

scenario: CalculoTotalCorrecto
given:
  Pedido:
    PedidoId: 10
    Estado: Borrador

  ItemPedido:
    - { PedidoId: 10, Cantidad: 2, PrecioUnitario: 50 }
    - { PedidoId: 10, Cantidad: 1, PrecioUnitario: 100 }

when:
  action: calcular_total

then:
  Pedido.Total: 200
Escenario: Confirmación inválida
scenario: ConfirmacionTotalCero
given:
  Pedido:
    PedidoId: 20
    Estado: Borrador

  ItemPedido:
    - { PedidoId: 20, Cantidad: 1, PrecioUnitario: 0 }

when:
  action: cambiar_estado
  Estado: Confirmado

then:
  error: "El pedido no puede confirmarse con total cero"


¿Por qué esto es poderoso?

Usando archivos con Markdown:

  • Definimos el modelo conceptual
  • Expresamos reglas formales
  • Documentamos comportamiento esperado
  • Generamos pruebas automáticas

El modelo deja de ser solo diseño y pasa a ser el centro ejecutable del sistema.

En un futuro cercano, herramientas de IA podrán, en forma consistente y correcta

  • Generar/mantener la estructura de la base de datos 
  • Crear APIs automáticamente 
  • Construir UI inicial
  • Generar tests unitarios y de aceptacion
  • Validar inconsistencias

El código será una consecuencia del modelo que podra expresarse de varias maneras. 

Al ser archivos de Markdown tambien se facilita el versionado de los mismos y se deberan contar con algun mecanismo de centralizacion (tipo GIT)  y solucion de colisiones cuando dos personas (o dos IA) modifiquen el mismo archivo o intenten ingresar requerimientos contradicctorios. 

Cada vez es mas importante conocer el problema que queremos resolver con el sistema que estamos desarrollando, para poder expresarlo y definirlo correctamente. 


Conclusión

Specification by Example no es solo una técnica de testing. Es una forma de pensar el desarrollo donde los ejemplos son el contrato.

Si esos ejemplos viven junto al modelo en Markdown ejecutable, tenemos una base sólida para sistemas generados, adaptables y verificables.



Comentarios

Entradas más populares de este blog

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Impresión directa a impresora en el WEB con aplicaciones GeneXus.

Aplicación monolítica o distribuida?