Design de software

Single Source of Truth: duplicar dados sempre causa divergências

Entre os bugs descobertos pouco antes da publicação, alguns seguem padrões conhecidos. O front-end calcula o desconto em 10%, enquanto o back-end usa 15%; ou a documentação marca um campo como obrigatório, mas ele desapareceu da API real. O código em si está correto nos dois lados. O problema é que a mesma informação existe em dois lugares…

6 min de leitura
Imagem de capa de Single Source of Truth: duplicar dados sempre causa divergências

Entre os bugs descobertos pouco antes da publicação, alguns seguem padrões conhecidos. O front-end calcula o desconto em 10%, enquanto o back-end usa 15%; ou a documentação marca um campo como obrigatório, mas ele desapareceu da API real. O código em si está correto nos dois lados. O problema é apenas que a mesma informação existia em dois lugares e só um deles foi alterado.

O princípio que impede estruturalmente esse tipo de incidente é o Single Source of Truth, ou SSOT. O nome parece grandioso, mas o conceito cabe em uma frase: cada informação deve ter exatamente uma única fonte autoritativa.

Resumo.

  1. SSOT é o princípio de que existe uma única fonte original da informação. Isso não significa que deva haver um único armazenamento.
  2. Informações duplicadas inevitavelmente divergem. O problema não é o momento da divergência, mas quando ninguém mais sabe qual versão está correta.
  3. Quando precisar copiar, crie uma versão derivada. Em vez de escrever duas vezes à mão, gere-a automaticamente a partir da fonte original.
  4. Cache e réplicas não violam SSOT. Basta deixar claro onde está a fonte original e em que direção ocorre a atualização.

Por que duplicações inevitavelmente divergem

Assim que você coloca uma informação em dois lugares, a responsabilidade de mantê-los iguais passa a ser das pessoas. Ferramentas e compiladores não conhecem esse acordo. A cada alteração, é preciso lembrar: “onde mais esse valor está?”. Basta esquecer uma vez para que os dois valores sigam caminhos diferentes.

Pior ainda é o que acontece depois da divergência. Quando uma constante aparece com valores diferentes em dois pontos do código, não dá para saber qual está correta apenas olhando o código. Começa a arqueologia: vasculhar o histórico do git, localizar a pessoa responsável na época e conferir o documento de requisitos. O verdadeiro custo de perder o SSOT não é corrigir o bug, mas gastar tempo decidindo “qual é a verdade”.

Vamos passar por alguns casos comuns.

  • Duplicação de constantes: o tamanho máximo de upload, 10 MB, é codificado separadamente na validação do front-end, na validação do back-end e na mensagem de erro.
  • Duplicação da lógica de validação: cliente e servidor validam o formato de e-mail usando expressões regulares diferentes.
  • Documentação e código: a especificação da API fica separada da implementação real. Alguns meses depois, a documentação vira ficção.
  • Banco de dados e cache: a invalidação do cache é esquecida após atualizar a fonte, e dados antigos continuam sendo servidos.
  • Design e código: os valores de cor do mockup de design e os valores codificados no app diferem sutilmente.

As formas variam, mas a estrutura é a mesma: existem duas fontes originais, e a sincronização depende do trabalho manual.

Diagrama comparando uma estrutura em que os valores divergem por sincronização manual sem SSOT e outra em que são derivados de uma fonte compartilhada
A diferença entre confiar a sincronização à memória humana e derivar tudo da fonte original

O princípio não é “proibir cópias”, mas criar versões derivadas

É comum interpretar SSOT como “armazene a informação em apenas um lugar”. Nesse caso, cache, réplicas de leitura e artefatos de build parecem violações. O princípio real é outro: a informação pode existir em vários lugares; porém, há uma única fonte original, e todo o restante deve ser derivado dela.

Uma das principais formas de criar versões derivadas é a geração de código.

  • Geração de tipos a partir do schema: ao gerar tipos de cliente e stubs de servidor a partir da especificação OpenAPI, a especificação se torna a fonte original, eliminando as chances de divergência entre documentação e código.
  • Tokens de design: defina cores e tipografia em um único arquivo de tokens e gere versões para os códigos de iOS, Android e web.
  • Módulo de constantes compartilhadas: se front-end e back-end importarem constantes do mesmo pacote, a duplicação por hardcode será bloqueada na origem.
  • Extrair documentação do código: ao gerar a documentação da API a partir de comentários e tipos, ela acompanha o código permanentemente.

O ponto em comum é transformar o lugar em que uma pessoa escreve duas vezes no lugar em que uma máquina gera uma vez. A responsabilidade pela sincronização sai da memória humana e vai para o pipeline de build; quando algo diverge, o CI detecta primeiro.

Cache e réplicas também se encaixam nesse modelo. Se a fonte original estiver declarada, as atualizações fluírem em uma única direção, da fonte para a cópia, e estiver definido por quanto tempo a cópia pode ficar desatualizada (TTL e estratégia de invalidação), o SSOT está sendo respeitado. A violação não ocorre quando existe uma cópia, mas quando alguém começa a modificá-la diretamente.

O mesmo princípio se aplica à organização

SSOT não diz respeito apenas ao código. Definir, no design de microsserviços, “qual serviço é dono destes dados” e designar a “versão oficial” entre documentos de políticas espalhados pela wiki interna, Notion e Slack são problemas da mesma natureza.

Documentos, em especial, divergem com mais facilidade que código, porque não têm compilador nem testes. Por isso, o SSOT organizacional começa pelo consenso, não pelas ferramentas. Por exemplo: “a fonte original do procedimento de onboarding é esta única página da wiki; nos outros lugares, mantemos apenas um link”. Usar links em vez de cópias é a derivação no mundo da documentação.

Ilustração de um pipeline de geração de código que cria automaticamente tipos, documentação e tokens de design a partir do schema original
Transformamos o ponto em que uma pessoa escreve duas vezes no ponto em que uma máquina gera uma vez

Checklist prático

Em resumo, estes são critérios de decisão que você já pode aplicar a partir de amanhã.

  1. Digitar o mesmo valor pela segunda vez é um sinal: se você está copiando constantes, regras de validação ou configurações, avalie primeiro se pode movê-las para um módulo compartilhado ou substituí-las por geração automática.
  2. Declare a fonte original: cache, réplicas e resumos não são problemas por si só. Verifique se “a fonte original é esta” está explícito no código e na documentação, e se as atualizações fluem em uma única direção.
  3. Faça as ferramentas detectarem divergências, não as pessoas: incluir validação de schema, testes de contrato e verificações de diff do código gerado no CI revela falhas de sincronização antes do merge.
  4. Cuidado com o perfeccionismo: criar abstrações excessivas para eliminar toda duplicação também tem um custo. A ordem é estabelecer SSOT primeiro para informações que mudam com frequência e para as quais uma divergência seria cara.

O princípio SSOT tem a mesma raiz do DRY (Don’t Repeat Yourself), usado em refatoração. Enquanto DRY combate a duplicação da lógica de código, SSOT amplia essa ideia para a duplicação de dados e conhecimento. Quando surgir a pergunta “esse valor também existe naquele lugar; preciso alterar os dois?”, esse é exatamente o ponto em que você deve estabelecer um SSOT.