Pular para o conteúdo

Engenharia de dados

O que separa uma análise que roda de um pipeline que se pode confiar — e as três formas de errar em silêncio.

Uma análise erra e alguém percebe: o gráfico fica estranho. Um pipeline erra e ninguém percebe — o número é plausível, o processo termina com código zero, e a conclusão errada vira decisão. Esta seção é sobre as formas de errar que não dão erro.

O erroComo ele apareceA defesa
janela sem partiçãomédia móvel "por loja" atravessa as lojaspor := "loja"
junção que multiplicao total sobe, e as linhas tambémcardinalidade := "muitos_para_um"
deriva de esquemao id chega como texto, e o join para de casarQualidade.exigir_esquema
reprocessar sem idempotênciao mesmo dia contado duas vezesmarca d'água, e partição sobrescrita
ausência virando zeroa soma cai, e a média sobevoid é vão, e não zero

O caminho inteiro, num programa#

dataforge
adopt Arcane.Quadro as Q
adopt Arcane.Qualidade as Qual

// ── 1. o que chegou ────────────────────────────────────────
bruto := [
    {"dia": "2026-01-05", "loja": "sul",   "produto": "cafe",   "valor": 98.7},
    {"dia": "2026-01-05", "loja": "norte", "produto": "cafe",   "valor": 32.9},
    {"dia": "2026-01-06", "loja": "sul",   "produto": "filtro", "valor": 42.5},
    {"dia": "2026-01-06", "loja": "norte", "produto": "cafe",   "valor": 65.8},
    {"dia": "2026-01-07", "loja": "sul",   "produto": "cafe",   "valor": 51.0},
]

// ── 2. o esquema esperado, e a conferência ────────────────
esperado := Qual.esquema_de(bruto)
relato := Qual.exigir_esquema(bruto, esperado)
assert relato["ok"] is yes

// ── 3. o quadro, e a janela POR LOJA ──────────────────────
vendas := Q.de_vaults(bruto).ordenar("dia")
com_media := vendas.janela("valor", 2, "media", "media_2", void, "loja")
assert com_media.altura() is 5

// ── 4. o apoio, com a cardinalidade declarada ─────────────
lojas := Q.de_vaults([
    {"loja": "sul", "regiao": "SE"},
    {"loja": "norte", "regiao": "N"},
])
junto := com_media.juntar(lojas, "loja", "dentro", "muitos_para_um")
assert junto.altura() is 5          // não inflou

// ── 5. a resposta ─────────────────────────────────────────
por_regiao := junto >> agrupar "regiao" >> resumir {"valor": "soma"}
out por_regiao.texto()

Cinco passos, e quatro deles são sobre não errar em silêncio. É a proporção certa: o trabalho de um pipeline é quase todo em garantir que o número final significa o que ele diz significar.