~/VibeHandbook
PDF grátis

Capítulo 14 · 03

Fundamentos de Design de Schema

Um schema é a planta baixa dos seus dados: quais tabelas existem, quais colunas elas têm e como se relacionam. Um bom design de schema é principalmente senso comum mais alguns hábitos.

  • Uma tabela por "coisa." Usuários, posts, pedidos — cada um recebe sua própria tabela.
  • Toda linha precisa de um ID único (uma chave primária).
  • Conecte tabelas com chaves estrangeiras, não copiando dados de um lado para o outro.
  • Escolha tipos honestos. Dinheiro é decimal, não float. Datas são timestamps, não texto.
  • Não duplique. Se o email de um usuário mora em cinco tabelas, eventualmente você terá cinco emails diferentes.

Aqui está um schema simples para um blog, do tipo que a IA vai gerar para você:

CREATE TABLE users (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email       TEXT NOT NULL UNIQUE,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE posts (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    author_id   UUID NOT NULL REFERENCES users(id),
    title       TEXT NOT NULL,
    body        TEXT NOT NULL,
    published   BOOLEAN NOT NULL DEFAULT false,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_posts_author ON posts(author_id);

Aquela linha author_id ... REFERENCES users(id) é a chave estrangeira. Ela conecta cada post de volta a exatamente um usuário real, então o próprio banco de dados se recusa a armazenar um post sem um autor válido:

   users                          posts
   ┌─────────────┐                ┌─────────────┐
   │ id  (PK) ◀──┼────────────────┤ author_id   │  (FK → users.id)
   │ email       │   um usuário    │ id  (PK)    │
   │ created_at  │   tem muitos    │ title       │
   └─────────────┘   posts         │ body        │
                                   │ published   │
        1  ────────────────────▶  *└─────────────┘
       (um)                     (muitos)

Repare em REFERENCES (uma chave estrangeira ligando um post a um usuário real) e nas restrições NOT NULL e UNIQUE. Esses são guardrails que o banco de dados aplica por você, para que dados ruins não consigam entrar mesmo quando seu código tem um bug.

Uma restrição que vale a pena adicionar deliberadamente é o que acontece quando o "pai" desaparece. Por padrão, apagar um usuário cujos posts ainda o referenciam vai falhar — o que geralmente é o que você quer. Mas você pode ser explícito: REFERENCES users(id) ON DELETE CASCADE apaga os posts também, enquanto ON DELETE RESTRICT bloqueia a exclusão. Escolher de propósito é melhor do que descobrir o comportamento padrão do jeito difícil em produção. O mesmo instinto de "deixe o banco de dados te proteger" se aplica a uma restrição CHECK (CHECK (price >= 0)) — ela recusa dados sem sentido na origem, em vez de confiar que todo caminho de código vai validar.

Quer offline?

Baixe o livro inteiro em PDF ou EPUB — grátis.