Las capas semánticas se venden como el sitio donde poner las definiciones de métricas.
Escribe revenue una vez, exponlo en todas partes, deja de discutir en reuniones.
Y entonces dos equipos reportan cifras de ingresos distintas, ambas técnicamente correctas, y la discusión se muda del panel al archivo de definiciones.
Las definiciones nunca fueron la parte difícil.
Las métricas son la capa visible, no la que sostiene el peso
Una métrica es una agregación sobre un conjunto de cosas. Cambia qué cuenta como una de esas cosas y el número cambia, sin que la fórmula se toque.
sum(amount) no es ambiguo. Qué importes es donde vive el desacuerdo:
- ¿Un pedido cancelado sigue siendo un pedido?
- ¿Un cliente que firmó dos contratos es un cliente o dos?
- ¿Un pedido pertenece a la fecha en que se hizo, se pagó o se envió?
- ¿Una devolución es un pedido negativo, o es otra cosa distinta?
Ninguna de estas es una pregunta sobre métricas. Son preguntas sobre qué es un pedido y qué es un cliente, y sobre si dos registros se refieren a la misma cosa real. Una capa semántica que solo responde la pregunta de la métrica hereda todos estos desacuerdos y no les da ningún sitio donde vivir.
Esa parte que falta es la ontología: no las fórmulas, sino las entidades sobre las que las fórmulas cuantifican.
A qué se compromete una ontología
A tres cosas, y cada una es una decisión que alguien tiene que tomar de forma explícita.
Identidad. Qué hace que dos registros sean la misma cosa. Es la que más se omite, y la que provoca dobles conteos durante años.
Granularidad. Qué significa una fila. “Una fila por pedido” y “una fila por línea de pedido” son mundos distintos, y las métricas se rompen en silencio cuando un modelo pasa de uno a otro.
Relaciones. Cómo se conectan las entidades y, sobre todo, con qué cardinalidad. Un join que abre en abanico sin que nadie lo declarara es la causa más común de un total inflado.
erDiagram
CLIENTE ||--o{ PEDIDO : realiza
PEDIDO ||--|{ LINEA_PEDIDO : contiene
PEDIDO ||--o{ DEVOLUCION : "puede devolverse en"
PRODUCTO ||--o{ LINEA_PEDIDO : "aparece en"
CLIENTE {
string cliente_id PK
string cuenta_id "identidad: una por entidad legal"
}
PEDIDO {
string pedido_id PK
string cliente_id FK
date fecha_pedido
date fecha_reconocimiento "grano: fecha de ingreso"
string estado
}
LINEA_PEDIDO {
string linea_id PK
string pedido_id FK
numeric importe
}
theory of small decisionsLee el diagrama como un conjunto de compromisos, no como un dibujo. Dice que un pedido
tiene muchas líneas, así que cualquier métrica que sume importe al grano de pedido está
mal. Dice que un cliente se mapea a una cuenta, así que “número de clientes” necesita
declarar a cuál de las dos se refiere. Dice que el ingreso tiene su propia fecha,
distinta de cuándo se hizo el pedido.
Cada una de esas es una frase que alguien pudo discutir en una reunión. Escritas, dejan de relitigarse cada trimestre.
Hacerla ejecutable
Una ontología que vive en un diagrama se pudre. La versión que sobrevive es la que lee el motor de consultas, porque entonces no puede desviarse de lo que los números hacen de verdad.
entities:
- name: pedido
primary_key: pedido_id
grain: "una fila por pedido"
# La identidad es una decisión, no un tecnicismo: dos filas con el mismo
# id de origen desde sistemas distintos son el mismo pedido solo después
# de que esta regla lo diga.
identity:
resolve_by: [sistema_origen, id_origen]
relationships:
- to: cliente
type: many_to_one
via: cliente_id
- to: linea_pedido
type: one_to_many
via: pedido_id
- name: linea_pedido
primary_key: linea_id
grain: "una fila por línea dentro de un pedido"
metrics:
- name: ingresos
description: >-
Neto de devoluciones, reconocido en fecha_reconocimiento y no en
fecha_pedido, excluyendo pedidos cancelados.
entity: linea_pedido
agg: sum
expr: importe
filters:
- "pedido.estado != 'cancelado'"
time_dimension: pedido.fecha_reconocimiento
La línea entity: linea_pedido hace un trabajo silencioso e importante. Declara el grano
al que corre la suma, que es lo que impide al motor abrir en abanico un join a nivel de
pedido y contar el mismo dinero dos veces.
Cómo se resuelve una pregunta
El valor de escribir esto es que una pregunta deja de responderla quien componga el SQL, y pasa a responderla el modelo.
flowchart LR
Q["ingresos por cliente,<br/>último trimestre"] --> M[métrica: ingresos]
M --> G[grano: linea_pedido]
M --> F["filtro: estado != cancelado"]
M --> T[tiempo: fecha_reconocimiento]
G --> J{ruta de join}
J --> O[pedido]
O --> C[cliente]
C --> ID["identidad: cuenta_id"]
ID --> R[una fila por cuenta]
theory of small decisionsDos analistas que hagan la misma pregunta recorren ahora el mismo camino. No porque se hayan puesto de acuerdo, sino porque el desacuerdo se zanjó una vez, aguas arriba, y se codificó.
Dónde debe vivir la ontología
La parte difícil no es modelar. Es la propiedad: una ontología mantenida por un equipo central se desvía de los dominios que describe, porque la gente que sabe qué es un contrato no trabaja ahí.
Este es el argumento para empujar las definiciones hacia los dominios dueños del dato, y dejar la capa semántica como el contrato entre ellos en lugar del sitio donde se inventa el significado.
No hace falta adoptar el modelo organizativo entero para quedarse con la parte útil: la definición pertenece a donde está el conocimiento, y el trabajo de la capa es hacerla legible en todas partes.
Modos de fallo que conviene nombrar
| Síntoma | Suele significar |
|---|---|
| Dos equipos, dos cifras de ingresos, ambas defendibles | Sin identidad acordada para la entidad |
| Los totales se inflan tras un join nuevo | Cardinalidad no declarada, abanico silencioso |
| Una métrica se rompe al refactorizar un modelo | El grano nunca se declaró, solo se supuso |
| “¿Qué fecha?” preguntado cada trimestre | Semántica temporal dejada a quien escribe la consulta |
| Definiciones correctas pero sin usar | Ontología gobernada lejos del dominio |
El patrón en los cinco: la fórmula estaba bien, y lo que había debajo nunca se escribió.
Por dónde empezar
No por un catálogo de métricas. Empieza por las cinco o seis entidades sobre las que el negocio más discute, y por cada una escribe las tres frases: qué hace que dos sean la misma, qué significa una fila, y cómo se conecta con las demás.
Es poco lucido, y lleva una tarde por entidad. Pero esas frases son de lo que depende en silencio cada métrica, y dejarlas sin escribir es como una capa semántica acaba siendo un sitio más donde se almacena el mismo desacuerdo.