Coloque os dados onde eles pertencem
Também em 28 idiomas
English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

Módulo 4 de 6 do capítulo Modelar dados pelo significado, capítulo 2 do curso Data Architect. Cada módulo vale por si só. Anterior: Construa o modelo lógico · Próximo: Projete até à terceira forma normal, depois recue
A pergunta que este módulo responde: Como a normalização me ajuda a descobrir onde os dados realmente pertencem?
Temos um modelo lógico: entidades, relações, atributos e chaves. Agora quero fazer uma das perguntas mais importantes da modelação de dados: este dado pertence mesmo a este lugar?
Parece simples. Não é. Já vi muitos sistemas em que cada campo fazia sentido quando alguém o criou. O problema não era os campos serem ridículos; era os factos estarem armazenados no lugar errado. Uma entrega guarda informação que na verdade descreve um centro de distribuição. A mesma morada aparece em centenas de registos. Um campo guarda três valores separados por vírgulas. Uma mudança num facto de negócio significa atualizar 10 mil registos. Esse é o problema que a normalização nos ajuda a resolver e, antes de nos enterrarmos em terminologia de bases de dados, eis a ideia inteira: coloque um facto onde ele pertence. Todo o resto deste módulo ajuda-nos a fazê-lo de forma mais sistemática.
O que é normalização?
Seção intitulada “O que é normalização? ”Normalização é organizar os dados para que cada facto seja armazenado uma vez, no lugar a que pertence. Quando uma tabela está a fazer trabalhos a mais, dividimo-la em tabelas que descrevem uma coisa cada, e ligamo-las com chaves.
Porquê dar-se ao trabalho? Porque um facto armazenado uma vez é um facto que mudamos uma vez. A normalização evita a redundância, o mesmo facto copiado em muitos registos, e com ela as inconsistências que aparecem quando uma cópia é atualizada e as outras não. É por isso que combina com sistemas transacionais como o Salesforce, em que os registos são criados e atualizados o dia inteiro.
Normalizamos em passos chamados formas normais, e cada uma faz uma única pergunta:
- Primeira forma normal (1FN): um valor por campo, e algo que identifique de forma única cada linha.
- Segunda forma normal (2FN): cada facto descreve o todo do que identifica a linha, não só uma parte.
- Terceira forma normal (3FN): cada facto descreve esta coisa, não outra coisa com que ela se relaciona.
Há mais formas além da terceira. Vou falar um pouco delas mais adiante, e de porque é que normalmente paramos na terceira. Primeiro, vamos ver os três passos acontecerem.
Porque é que normalizamos?
Seção intitulada “Porque é que normalizamos? ”Quando ensino isto ao vivo, não começo com entregas. Começo com cães. Toda a gente percebe de cães, por isso ninguém se distrai com o negócio, e podemos ver os dados a tentar encontrar a sua casa. Depois levamos os mesmos movimentos para a Steve Trucking.
Senta, fica, modelo
Seção intitulada “Senta, fica, modelo ”Início: a folha de cálculo em bruto. Ponho alguns cães no ecrã, e depois a sala acrescenta os seus. Em poucos minutos temos uma lista grande: o cão, o ano em que nasceu, quem é o dono, onde o dono vive, a raça, quem o criou e os truques que sabe.
| Cão | Nasceu | Dono | Código postal | Cidade | Raça | Criador | Truques |
|---|---|---|---|---|---|---|---|
| Bella | 2017 | Marcus | 80202 | Denver | Labrador | Maple Ridge | Senta, Fica, Dá a pata |
| Milo | 2019 | Marcus | 80202 | Denver | Poodle | Golden Meadow | Senta, Rebola |
| Max | 2022 | Ana | 64105 | Kansas City | Rafeiro | Senta, Finge-se de morto | |
| Luna | 2020 | Kenji | 98101 | Seattle | Husky | Cascade | Senta, Fica, Gira |
| Rocky | 2024 | Priya | 30301 | Atlanta | Beagle | Maple Ridge | Senta |
| Coco | 2014 | Ana | 64105 | Kansas City | Chihuahua | Little Paws | Dá a pata, Gira |
Funciona. Todas as folhas de cálculo funcionam no primeiro dia. Mas veja o que já está errado. Como encontro todos os cães que sabem Dá a pata? O código postal da Ana está em duas linhas, e o do Marcus também: o que acontece se alguém atualizar uma e não a outra? Maple Ridge aparece duas vezes, e Kansas City também. E o Max veio do canil municipal, por isso não há criador nenhum.
Passo 1: primeira forma normal. Duas regras. Cada campo guarda um único valor, por isso a lista de truques separada por vírgulas tem de sair. E cada linha precisa de algo que a identifique de forma única. Não o nome do cão; há muitos cães chamados Max. Um ID: um ID gerado automaticamente ou um GUID. Os truques saem para linhas próprias, uma linha para cada cão e cada truque. E, quando um truque tem a sua própria linha, há espaço para o que nunca conseguiríamos dizer numa lista com vírgulas: quão difícil é o truque, quão bem este cão o faz, e quando o aprendeu.
Cão (identificado pelo ID do cão)
| ID do cão | Nome | Nasceu | Dono | Código postal | Cidade | Raça | Criador |
|---|---|---|---|---|---|---|---|
| D-001 | Bella | 2017 | Marcus | 80202 | Denver | Labrador | Maple Ridge |
| D-002 | Milo | 2019 | Marcus | 80202 | Denver | Poodle | Golden Meadow |
| D-003 | Max | 2022 | Ana | 64105 | Kansas City | Rafeiro | |
| D-004 | Luna | 2020 | Kenji | 98101 | Seattle | Husky | Cascade |
| D-005 | Rocky | 2024 | Priya | 30301 | Atlanta | Beagle | Maple Ridge |
| D-006 | Coco | 2014 | Ana | 64105 | Kansas City | Chihuahua | Little Paws |
Truque do cão (identificado por ID do cão + Truque)
| ID do cão | Truque | Dificuldade | Nível de habilidade | Aprendeu em |
|---|---|---|---|---|
| D-001 | Senta | Fácil | Especialista | 2017-11 |
| D-001 | Fica | Fácil | Especialista | 2018-01 |
| D-001 | Dá a pata | Média | Bom | 2018-06 |
| D-002 | Senta | Fácil | Especialista | 2020-02 |
| D-002 | Rebola | Difícil | A aprender | 2023-05 |
| D-003 | Senta | Fácil | Bom | 2022-06 |
| D-003 | Finge-se de morto | Difícil | A aprender | 2024-03 |
| D-004 | Senta | Fácil | Especialista | 2020-11 |
| D-004 | Fica | Fácil | Bom | 2021-01 |
| D-004 | Gira | Média | Especialista | 2021-06 |
| D-005 | Senta | Fácil | A aprender | 2025-02 |
| D-006 | Dá a pata | Média | Especialista | 2015-06 |
| D-006 | Gira | Média | A aprender | 2025-04 |
Agora «todos os cães que sabem Dá a pata» é uma pergunta simples. Mas repare no que identifica o Truque do cão: não uma coisa, duas coisas juntas, o cão e o truque. Guarde isso.
Passo 2: segunda forma normal. A segunda forma normal só importa quando uma linha é identificada por uma combinação, e o Truque do cão é. Por isso pergunto a cada coluna: descreve a combinação inteira, ou só parte dela? O nível de habilidade descreve este cão a fazer este truque: a Bella é especialista no Senta, o Rocky ainda está a aprendê-lo. A data em que aprendeu, a mesma coisa. Mas a dificuldade? O Senta é fácil, seja qual for o cão que o faça. Descreve o truque, só parte da chave, e é por isso que «Fácil» se repete em todas as linhas do Senta. Por isso, o truque ganha a sua própria tabela, e o que sobra é o par.
Truque
| ID do truque | Truque | Dificuldade |
|---|---|---|
| T-01 | Senta | Fácil |
| T-02 | Fica | Fácil |
| T-03 | Dá a pata | Média |
| T-04 | Rebola | Difícil |
| T-05 | Finge-se de morto | Difícil |
| T-06 | Gira | Média |
Truque do cão (ID do cão + ID do truque)
| ID do cão | ID do truque | Nível de habilidade | Aprendeu em |
|---|---|---|---|
| D-001 | T-01 | Especialista | 2017-11 |
| D-001 | T-02 | Especialista | 2018-01 |
| D-001 | T-03 | Bom | 2018-06 |
| D-002 | T-01 | Especialista | 2020-02 |
| D-002 | T-04 | A aprender | 2023-05 |
| D-003 | T-01 | Bom | 2022-06 |
| D-003 | T-05 | A aprender | 2024-03 |
| D-004 | T-01 | Especialista | 2020-11 |
| D-004 | T-02 | Bom | 2021-01 |
| D-004 | T-06 | Especialista | 2021-06 |
| D-005 | T-01 | A aprender | 2025-02 |
| D-006 | T-03 | Especialista | 2015-06 |
| D-006 | T-06 | A aprender | 2025-04 |
Essa tabela Truque do cão é a mesma que encontrámos no módulo 2, e tem um nome na modelação de dados: uma junção, ou, como eu lhe chamo, um objeto de junção lógico. Um cão sabe muitos truques; um truque é conhecido por muitos cães. A junção fica entre eles, e não é canalização vazia: guarda os factos que pertencem à própria relação, o nível de habilidade e a data. Vamos encontrá-la de novo no módulo 6, e no capítulo 3 veremos que o Salesforce usa «objeto de junção» num sentido mais estreito: um objeto de junção do Salesforce (Salesforce Junction Object) é um objeto personalizado com duas relações mestre-detalhe (capítulo 3, módulo 7).
Passo 3: terceira forma normal. Agora de volta à tabela Cão. Tudo nela é identificado pelo ID do cão, por isso a segunda forma normal não tem nada a dizer. A terceira forma normal faz uma pergunta diferente: este facto descreve o cão, ou outra coisa com que o cão se relaciona? A raça é uma coisa própria: um labrador é um labrador, seja qual for o cão, e os factos sobre ela, como o porte, pertencem à raça, não à Bella. O código postal e a cidade descrevem o dono, não o cão: é onde a Ana vive, seja qual for o cão dela que estamos a ver. Os dados do criador descrevem o criador. Cada um destes é um facto sobre outro facto, por isso cada um vai para a sua própria tabela, e o cão aponta para ela com uma chave estrangeira:
- Cão: ID do cão, Nome, Nasceu, ID do dono, ID da raça, ID do criador
- Dono: ID do dono, Nome, Código postal, Cidade
- Raça: ID da raça, Raça, Porte
- Criador: ID do criador, Nome, Cidade
- Truque e Truque do cão, do passo 2
Agora a Ana é armazenada uma vez, com os seus dois cães a apontar para ela. Maple Ridge é armazenado uma vez, e a tabela Raça dá-nos um lugar para os factos sobre cada raça, como o porte, que a folha de cálculo não tinha onde pôr. Uma chave estrangeira pode ficar em branco: o Max não tem ID do criador, e essa é uma resposta honesta, não uma lacuna. Depois faço uma pergunta rasteira à sala: a data em que o dono ficou com o cão, onde é que vai? No cão. Neste modelo, um cão tem um dono de cada vez, por isso essa data descreve a relação do cão com o dono.
Podia ir-se um passo mais longe e separar a cidade do código postal; os livros fazem-no. Na prática, uma morada fica junta, e Kansas City fica em dois estados, de qualquer forma: um bom lembrete de que o mundo real não lê os nossos livros.
Essa é a progressão: uma folha de cálculo, depois três perguntas, e cada facto acaba num só lugar. Dê um passo atrás e veja o que construímos. Uma lista desarrumada tornou-se seis tabelas, cada uma a descrever uma coisa, ligadas por chaves:
Ninguém precisou de uma única palavra do Salesforce para acompanhar isto. São só os cães, as pessoas à volta deles e o que eles sabem.
Agora vamos aplicar isto à Steve Trucking
Seção intitulada “Agora vamos aplicar isto à Steve Trucking ”Os cães tornam os movimentos fáceis de ver. Um negócio a sério faz com que importem, porque os mesmos erros custam dinheiro a sério em escala. Por isso, vamos levar as mesmas três perguntas à Steve Trucking. Imagine que guarda as suas entregas assim:
| Entrega | Parceiro retalhista | Centro de distribuição | Cidade do CD | Equipa | Camião |
|---|---|---|---|---|---|
| 1001 | Keystone | CD Keystone Phoenix | Phoenix | Equipa 12 | 117 |
| 1002 | Keystone | CD Keystone Phoenix | Phoenix | Equipa 8 | 122 |
| 1003 | Keystone | CD Keystone Phoenix | Phoenix | Equipa 12 | 117 |
À primeira vista, nada aqui é complicado. Mas olhe para o centro de distribuição. Repetimos «CD Keystone Phoenix, Phoenix» em cada entrega que sai dele: a Steve Trucking faz umas 3.300 entregas por dia em nove CD, portanto algumas centenas por dia de cada um. O que acontece se esse CD mudar de sítio? Quantos registos alteramos, e o que acontece se um ficar esquecido? Agora os dados dizem que o CD está em duas cidades ao mesmo tempo. Isso é uma anomalia de atualização. E se quisermos registar um novo CD antes da sua primeira entrega? E se eliminarmos a última entrega de um CD: acabámos de eliminar o único lugar onde guardávamos alguma coisa sobre ele?
Estes são sintomas diferentes do mesmo problema: misturámos factos sobre coisas diferentes. Os factos do centro de distribuição pertencem ao centro de distribuição. Os factos da entrega pertencem à entrega. Os factos da equipa pertencem à equipa. Isso é a normalização em termos práticos.
Primeira forma normal: não esconda estruturas que se repetem
Seção intitulada “Primeira forma normal: não esconda estruturas que se repetem ”Vamos começar pela primeira forma normal, ou 1FN, onde as pessoas às vezes tornam a normalização mais difícil do que precisa de ser.
Suponha que uma entrega tem um campo chamado Artigos: «Frigorífico, kit de máquina de gelo, recolha do antigo.» Pusemos três informações num só campo. Parece conveniente, até alguém perguntar: «Quantas recolhas fizemos no mês passado?» Ou imagine campos chamados Artigo 1, Artigo 2 e Artigo 3. Funciona, até à entrega com quatro artigos. O problema não é termos escolhido o número errado de campos Artigo. O problema é não termos reconhecido a estrutura que se repete. Uma entrega pode ter vários artigos. Isso é um dado que devemos modelar: o Item de entrega que encontrámos no módulo 2.
A lição prática da 1FN: não esconda estruturas que se repetem dentro de campos. Se o negócio lhe diz que algo pode acontecer muitas vezes, escute. Pode haver outra entidade a tentar sair.
Vai ver isto em orgs reais constantemente. Alguém precisa de uma descrição em vários idiomas, por isso cria um campo chamado Description_English, depois Description_French, depois Description_German. Ou uma aprovação precisa de algumas pessoas, e ficamos com Aprovador 1, Aprovador 2, Aprovador 3. Quando encontro isso numa revisão, é uma palmada na mão: corrija o seu modelo de dados. Um ou dois, talvez, se o negócio só tiver mesmo um ou dois. Qualquer coisa além disso deve ser um objeto filho: uma Tradução com um idioma, uma Etapa de aprovação com um aprovador. O idioma seguinte, ou o quarto aprovador, torna-se um novo registo, não um novo campo e um deploy.
Segunda forma normal: descreva a coisa inteira
Seção intitulada “Segunda forma normal: descreva a coisa inteira ”A segunda forma normal, ou 2FN, importa quando um registo é identificado por uma combinação de coisas. Pegue no Item de entrega. Tem o seu próprio ID de registo, mas cada um é único por Entrega + Produto. Suponha que guardamos a entrega, o produto, a quantidade e a descrição do produto.
A quantidade faz sentido aqui: descreve este produto nesta entrega. Mas a descrição do produto não descreve a combinação; descreve o produto. Ponha-a em cada Item de entrega e repetimo-la sempre que aquele modelo de frigorífico sai noutro camião. Essa é a pista de que o facto pertence a outro lugar.
Então a pergunta da 2FN é: este atributo descreve a coisa inteira que estou a identificar, ou só parte dela? Se descreve só o produto, vai com o Produto. Se descreve o lugar do produto nesta entrega específica (a quantidade, se será instalado), pertence ao Item de entrega. Muitos administradores nunca vão dizer conscientemente: «Agora estou a aplicar a segunda forma normal.» Não faz mal. Importa-me muito mais que aprenda a perguntar: o que é que este facto descreve realmente?
Terceira forma normal: não guarde factos sobre outros factos
Seção intitulada “Terceira forma normal: não guarde factos sobre outros factos ”Agora a que mais me importa na modelação do dia a dia: a terceira forma normal, ou 3FN.
Cada centro de distribuição tem um gestor do lado do Parceiro retalhista, alguém que usa o portal do parceiro. Suponha que pomos o nome do gestor do CD diretamente em cada entrega. O que acontece quando o CD tem um novo gestor? Atualizamos cada entrega daquele CD. É o mesmo cheiro outra vez: estamos a repetir um facto que pertence a outro lugar. A entrega sai de um CD; o CD tem um gestor. São duas relações, e o nome do gestor pertence ao CD.
A versão clássica dos livros é a morada: código postal, cidade e estado guardados juntos em cada registo, quando a cidade e o estado normalmente decorrem do código postal. A mesma forma, a mesma pergunta.
A pergunta prática da 3FN é: este facto descreve esta coisa, ou outra coisa com que esta se relaciona? Quero que a faça constantemente.
Agora dê um passo atrás, da mesma maneira que fizemos com os cães. A tabela de entregas com que começámos tornou-se cinco coisas, cada uma a guardar os seus próprios factos: o Item de entrega saiu na primeira forma normal, o Produto na segunda, e a cidade e o gestor do Centro de distribuição foram para o Centro de distribuição na terceira.
As mesmas três perguntas, o mesmo resultado: cada facto num só lugar.
Uma forma simples de pensar em 1FN, 2FN e 3FN
Seção intitulada “Uma forma simples de pensar em 1FN, 2FN e 3FN ”Dá para passar um curso inteiro de bases de dados em normalização. Não o vamos fazer. Para este curso, quero que tenha o entendimento prático de um arquiteto:
- 1FN: estou a esconder vários valores ou estruturas que se repetem dentro de um campo ou de um registo?
- 2FN: este facto descreve a coisa inteira que estou a identificar?
- 3FN: este facto descreve realmente esta entidade, ou algo relacionado com ela?
Estas não são definições para um livro de bases de dados. São perguntas que consigo usar a sério enquanto projeto.
Sim, a normalização vai mais longe: a forma normal de Boyce-Codd (FNBC) aperta as regras em torno da 3FN para modelos com chaves mais complicadas, e há a quarta, a quinta e até a sexta forma normal. Tratam de tipos mais raros de repetição, do tipo que vem de estruturas de chave invulgares mais do que de registos de negócio do dia a dia. Muita teoria e, na minha experiência, não vale a dor de cabeça para o tipo de sistema que construímos no Salesforce. Em sistemas de negócio, a pressão costuma ir no sentido oposto: é muito mais provável recuarmos da terceira forma normal, por causa dos utilizadores, dos relatórios e do desempenho, do que irmos além dela. Esse é o próximo módulo. Saiba que as outras formas existem, mas para a maior parte do que fazemos, da 1FN à 3FN temos as ferramentas de raciocínio de que precisamos.
Projete até à terceira forma normal
Seção intitulada “Projete até à terceira forma normal ”Eis a minha posição. Quando estou a tentar entender um negócio e a projetar o seu modelo lógico, quero começar limpo: os factos da entrega com a entrega, os factos do centro de distribuição com o CD, os factos do camião com o camião, os conceitos que se repetem modelados como conceitos. Não quero um facto de negócio copiado pelo modelo todo só porque isso pode facilitar um ecrã ou um relatório. Ainda não.
Mas a normalização não é uma religião. O objetivo não é o modelo academicamente mais puro possível. Já vi arquitetos tão focados na pureza que o modelo se torna um sofrimento para todos os que têm de o usar. Não estamos a tentar ganhar um concurso de normalização; estamos a construir um sistema, e esse sistema tem utilizadores, relatórios, integrações, necessidades de desempenho, escala e, cada vez mais, IA a ler os dados. Estes podem querer os dados em formatos diferentes.
Por isso, o meu ponto de partida é projetar até à terceira forma normal onde for viável, e depois recuar quando necessário: entender primeiro onde cada facto pertence. Depois, se nos vamos afastar disso, quero saber porquê. Se a resposta é «porque eu não sabia onde mais pôr o campo», não chega. Se a resposta é «copiámos este valor de propósito porque simplifica o scorecard do parceiro, e temos uma forma fiável de o manter sincronizado», agora estamos a ter uma conversa de arquitetura.
O que um arquiteto decide aqui
Seção intitulada “O que um arquiteto decide aqui ”Quando estou a normalizar um modelo lógico, procuro:
- Valores ou estruturas que se repetem e que deveriam ser modelados separadamente.
- Atributos que descrevem uma entidade diferente daquela em que estão armazenados.
- Factos duplicados sem necessidade em muitos registos, e as dependências que os deixam inconsistentes.
- Conceitos de negócio escondidos dentro de campos.
- Um modelo limpo que representa a verdade antes de qualquer concessão da implementação.
Não porque todos os sistemas físicos tenham de continuar perfeitamente normalizados. Muito pelo contrário. No próximo módulo vamos afastar-nos do modelo limpo de propósito, por causa dos utilizadores, dos relatórios, da escala, da análise e da IA, e vamos fazê-lo sabendo exatamente do que estamos a abdicar.
