✦ Plataforma de Aprendizado

Aprenda a
pensar como
dev.

Doze módulos interativos para dominar os fundamentos de programação — do zero, com exemplos reais e práticas ao vivo.

12
Módulos
48
Conceitos
Playgrounds
— Escolha um módulo para começar —
🧩
Módulo 01
Orientação a Objetos
Entenda como modelar o mundo real em código usando Classes, Objetos e os 4 pilares do OOP.
Classes Objetos Herança Encapsulamento Polimorfismo
🐍 Python · 3 seções
Iniciar →
Módulo 02
Lógica de Programação
Construa a base de qualquer linguagem: variáveis, condicionais, laços e funções com JavaScript.
Variáveis Tipos if/else for/while Funções
⚡ JavaScript · 4 seções
Iniciar →
🗄️
Módulo 03
Estruturas de Dados
Domine Arrays e Objetos — as estruturas mais usadas em qualquer projeto real, com visualizações animadas e playground ao vivo.
Arrays Objetos map/filter reduce Spread
⚡ JavaScript · 4 seções
Iniciar →
Módulo 04
Async & Promises
Entenda como o JS lida com operações que levam tempo — APIs, bancos de dados e muito mais. O conceito que separa iniciantes de devs prontos para o mercado.
Callbacks Promises async/await fetch API try/catch
⚡ JavaScript · 4 seções
Iniciar →
🌐
Módulo 05
DOM — Manipulação
Aprenda a fazer o JavaScript controlar páginas HTML ao vivo: selecionar elementos, mudar estilos, criar conteúdo e reagir a eventos do usuário.
querySelector innerHTML Events classList createElement
⚡ JavaScript · 4 seções
Iniciar →
🌿
Módulo 06
Git & Controle de Versão
Nunca mais perca código. Git é a ferramenta usada por 100% das equipes de dev no mundo — aprenda a salvar, ramificar e colaborar com segurança.
commit branch merge GitHub pull/push
🔧 Terminal · 4 seções
Iniciar →
🔍
Módulo 07 · Novo ✦
Algoritmos de Busca & Ordenação
Entenda como computadores organizam e encontram dados. A base de entrevistas técnicas e de escrever código eficiente.
Linear Search Binary Search Bubble Sort Merge Sort Big O
⚡ JavaScript · 4 seções
Iniciar →
🔄
Módulo 08 · Novo ✦
Recursividade
Funções que chamam a si mesmas — um conceito poderoso para resolver problemas complexos de forma elegante.
Base Case Call Stack Fatorial Fibonacci Tree Walk
⚡ JavaScript · 4 seções
Iniciar →
🏗️
Módulo 09 · Novo ✦
Padrões de Projeto
Soluções testadas para problemas comuns. O vocabulário que todo dev sênior usa — aprenda os padrões mais importantes com exemplos práticos.
Singleton Observer Factory Strategy MVC
⚡ JavaScript · 4 seções
Iniciar →
🔌
Módulo 10 · Novo ✦
APIs REST & JSON
Aprenda como aplicações se comunicam na internet. APIs são o coração de todo app moderno — entenda REST, HTTP e JSON de uma vez por todas.
HTTP Methods JSON Status Codes Headers fetch/axios
🌐 Web · 4 seções
Iniciar →
💻
Módulo 11 · Novo ✦
Terminal & Linux
A ferramenta que todo dev usa todos os dias. Aprenda a navegar pelo sistema, manipular arquivos e automatizar tarefas direto da linha de comando.
Shell Comandos Permissões Pipes Scripts
🔧 Terminal · 4 seções
Iniciar →
🗃️
Módulo 12 · Novo ✦
SQL & Banco de Dados
A linguagem que faz o mundo dos dados funcionar. Aprenda a consultar, inserir, atualizar e relacionar dados como um profissional.
SELECT JOIN WHERE INSERT Modelagem
🗃️ SQL · 4 seções
Iniciar →
💡

O que é OOP?

Organizar código pensando no mundo real

Orientação a Objetos

OOP é uma forma de organizar código modelando o mundo real. Em vez de uma lista de instruções, você cria objetos — entidades com características e comportamentos próprios.

🌎 Analogia: Um cachorro tem atributos (nome, raça) e comportamentos (latir, correr). Em OOP você modela o mundo assim: dados e ações juntos num único lugar.

Por que usar OOP?

Torna código mais organizado, reutilizável e fácil de manter. Você cria um molde uma vez e usa quantas vezes quiser.

🏭 Analogia: Uma fábrica de carros. Você cria o molde uma vez e usa para fabricar milhares de carros — cada um com cor e modelo próprios.
💡 Usado em: Python, Java, C++, JavaScript, C# e quase todas as linguagens modernas. É uma das habilidades mais importantes para qualquer dev.
📐

Classe & Objeto

Molde vs. instância real

Classe = Molde / Planta

Uma classe é a definição — descreve quais atributos (dados) e métodos (ações) os objetos terão. A classe em si não é um objeto; é só a ideia.

📐 Classe: Cachorro

Atributos
nome : texto
raça : texto
idade : número
Métodos
latir() → faz som
correr() → move o cão
apresentar() → mostra info

Objeto = Instância Real

Um objeto é criado a partir de uma classe. Pode ter infinitos objetos da mesma classe — cada um com seus próprios valores.

🐶 rex = nome:"Rex", raça:"Labrador", idade:3
🐶 bolinha = nome:"Bolinha", raça:"Poodle", idade:7

Ambos são Cachorros, mas são objetos diferentes com dados próprios.
cachorro.py
# Definindo a CLASSE (o molde)
class Cachorro:
    def __init__(self, nome, raca, idade):
        self.nome  = nome
        self.raca  = raca
        self.idade = idade

    def latir(self):
        return f"{self.nome} diz: Au au!"

# Criando OBJETOS (instâncias)
rex     = Cachorro("Rex", "Labrador", 3)
bolinha = Cachorro("Bolinha", "Poodle", 7)

print(rex.latir())  # → Rex diz: Au au!
🏛️

4 Pilares do OOP

Clique em cada pilar para expandir

Dica: Clique em cada pilar abaixo para ver a explicação e a analogia.
📦

Encapsulamento

Esconder dados internos

Agrupa dados e métodos juntos e protege dados de acesso direto — expõe só o necessário.

🔒 Como uma cápsula de remédio — você toma, mas não precisa saber a fórmula.
🧬

Herança

Reutilizar de outra classe

Uma classe pode herdar atributos e métodos de outra e adicionar coisas novas.

👨‍👧 Como filhos herdam características dos pais — mas têm personalidade própria.
🎭

Polimorfismo

Mesma ação, resultado diferente

O mesmo método se comporta de formas diferentes em classes distintas.

🎵 Como o botão "play" — funciona diferente no Spotify e no Netflix, mas você usa igual.
🎨

Abstração

Simplificar a complexidade

Esconde a complexidade e mostra só o que importa.

🚗 Como dirigir — você usa volante e pedal sem entender o motor por dentro.
heranca.py
# HERANÇA + POLIMORFISMO
class Animal:
    def __init__(self, nome):
        self.nome = nome
    def falar(self):
        return "..."

class Cachorro(Animal):   # herda de Animal
    def falar(self):       # polimorfismo
        return "Au au!"

class Gato(Animal):
    def falar(self):
        return "Miau!"

animais = [Cachorro("Rex"), Gato("Mimi")]
for a in animais:
    print(a.nome, ":", a.falar())
# Rex : Au au!   /   Mimi : Miau!
🎮

Playground

Crie objetos da classe Carro ao vivo

Experimente! Preencha os campos e clique em "Instanciar" — você está criando objetos a partir de uma classe, assim como o Python faz.
 Criar Objetos — Classe Carro
ao vivo
class Carro:
    def __init__(self, nome, cor, ano, tipo):
        self.nome = nome
        self.cor  = cor
        self.ano  = ano
        self.tipo = tipo

# Seus objetos aparecerão aqui ↓
📦

Variáveis & Tipos

Caixas que guardam informação na memória

Dica: Em JS moderno use const quando o valor não muda e let quando pode mudar.

O que é uma variável?

Uma caixa com etiqueta. A etiqueta é o nome, dentro fica o valor. O programa pode ler ou trocar o que está dentro.

📮 Analogia: Uma caixa de correio. O número é o nome da variável. O que está dentro é o valor. Você pode trocar a carta a qualquer momento.
variaveis.js
const nome     = "Ana"      // String
const idade    = 25        // Number
const aprovado = true     // Boolean

let pontos = 0
pontos = 10  // ✅ let permite reatribuir

// const nome = "Outro"  ❌ erro!
🧪 Clique num tipo para ver exemplo
📝
String
"Olá"
🔢
Number
42 / 3.14
Boolean
true/false
📋
Array
[1,2,3]
🗂️
Object
{chave:val}
← Selecione um tipo acima
🔀

Condicionais

Fazer o programa tomar decisões

if / else

Condicionais permitem que o programa escolha caminhos diferentes. Se algo for verdadeiro, faz X. Senão, faz Y.

🚦 Analogia: Um semáforo. Se verde → avance. Senão → pare. O trânsito segue caminhos diferentes conforme a condição.
condicionais.js
const idade = 17

if (idade >= 18) {
  console.log("Pode votar ✅")
} else if (idade >= 16) {
  console.log("Voto facultativo 🗳️")
} else {
  console.log("Não pode votar ❌")
}
// → "Voto facultativo 🗳️"

// ===  igual   !==  diferente
// &&   E        ||   OU
🎮 Simulador — Nota Escolar
7
ao vivo

              
🔁

Laços de Repetição

Executar código múltiplas vezes automaticamente

Por que usar laços?

Imprimir 1 a 100 sem laço = 100 linhas. Com laço = 3 linhas. Laços automatizam repetição.

🏃 Analogia: Uma esteira. Você define "rodar 30 min" — ela repete sozinha até acabar o tempo, sem você reiniciar a cada passo.
lacos.js
// FOR — sabe quantas vezes
for (let i = 1; i <= 5; i++) {
  console.log(`Volta ${i}`)
}

// WHILE — não sabe quantas vezes
let energia = 10
while (energia > 0) {
  energia -= 3
}

// FOR...OF — percorre arrays
const frutas = ["🍎", "🍌", "🍇"]
for (const f of frutas) console.log(f)
🎮 Visualizador de Laço For
// saída aparecerá aqui...
⚙️

Funções

Blocos de código reutilizáveis com nome

O que é uma função?

Um bloco de código com nome que você chama quantas vezes quiser. Recebe parâmetros e pode devolver um resultado (return).

🧃 Analogia: Uma máquina de suco. Você coloca frutas (parâmetros), aperta o botão (chama a função), recebe o suco (return). Sem montar ela do zero toda vez.
funcoes.js
// Declaração clássica
function somar(a, b) {
  return a + b
}
console.log(somar(3, 4))  // → 7

// Arrow function (forma moderna)
const dobrar = (n) => n * 2
console.log(dobrar(7))    // → 14
🎮 Construtor de Funções — Calculadora

Parâmetros

Operação

📋

Arrays

Listas ordenadas de valores — a estrutura mais usada em JS

O que é um Array?

Um array é uma lista ordenada de valores guardados em sequência. Cada item tem um índice numérico que começa em 0 — não em 1!

🚌 Analogia: Um ônibus com poltronas numeradas. A poltrona 0 é a primeira, a poltrona 1 é a segunda… Você acessa um passageiro pelo número do assento.
Atenção: Arrays em JS começam no índice 0, não no 1. O primeiro item é arr[0]!
arrays.js
// Criando um array
const frutas = ["🍎", "🍌", "🍇", "🍓"]

// Acessando por índice (começa em 0!)
console.log(frutas[0])  // → "🍎"
console.log(frutas[2])  // → "🍇"

// Propriedades úteis
console.log(frutas.length)          // → 4
console.log(frutas[frutas.length-1]) // → último: "🍓"

// Modificando
frutas[1] = "🥭"  // troca "🍌" por "🥭"
🎮 Visualizador de Array — Clique nas células!
⚙️

Métodos de Array

As ferramentas mais poderosas do JS moderno

Por que aprender métodos?

Os métodos de array são usados em todo projeto real — filtrar dados de uma API, transformar listas, calcular totais. São o pão e a manteiga do JavaScript.

🏭 Analogia: Uma esteira de fábrica. Você coloca os itens (array), e aplica operações em sequência: filtra os defeituosos, transforma os bons, e calcula o total produzido.
🧪 Clique num método para ver ao vivo:
.map()
.filter()
.reduce()
.find()
.some()
.sort()
...spread
Destructuring
← Selecione um método acima
métodos.js
const nums = [1, 2, 3, 4, 5, 6]

// map → transforma cada item
nums.map(n => n * 2)          // → [2,4,6,8,10,12]

// filter → filtra por condição
nums.filter(n => n % 2 === 0) // → [2,4,6]

// reduce → acumula em um valor
nums.reduce((acc, n) => acc + n, 0) // → 21

// Encadeando (chaining)!
nums
  .filter(n => n > 2)
  .map(n => n * 10)   // → [30,40,50,60]
🗂️

Objetos (Object)

Dados estruturados com chave e valor

O que é um Objeto JS?

Um objeto é uma coleção de pares chave:valor. Diferente de arrays (que usam índices numéricos), objetos usam nomes descritivos para acessar os dados.

🪪 Analogia: Uma carteira de identidade. Tem campos nomeados: nome, cpf, data_nascimento. Você acessa pelo nome do campo, não por um número.

🖱️ Explore o objeto abaixo — clique em cada propriedade:

nome:"Ana Silva"
idade:28
ehDev:true
skills:["JS", "Python", "CSS"]
cidade:"São Paulo"
objetos.js
const usuario = {
  nome:   "Ana Silva",
  idade:  28,
  ehDev:  true,
  skills: ["JS", "Python", "CSS"]
}

// Acessar propriedades
usuario.nome         // → "Ana Silva"
usuario["idade"]    // → 28

// Destructuring — extrai de uma vez!
const { nome, idade } = usuario
console.log(nome)    // → "Ana Silva"

// Spread — copia e adiciona campos
const atualizado = { ...usuario, cidade: "SP" }
🎮

Playground

Monte seu próprio objeto JavaScript ao vivo

Experimente! Adicione propriedades ao objeto, escolha o tipo de cada valor e veja o código JS gerado em tempo real.
 Construtor de Objeto JS
ao vivo
// Preencha os campos acima ↑
🤔

Por que Async existe?

O problema do código que "trava enquanto espera"

JavaScript é Single-Threaded

O JS executa uma coisa de cada vez, em sequência. Isso é ótimo para simplicidade — mas cria um problema: e quando uma operação demora? Buscar dados de uma API pode levar 2 segundos. Sem async, o programa inteiro travaria esperando.

Analogia: Imagina um café onde tem só um atendente. Se ele precisar fazer o café antes de atender a próxima pessoa, a fila para. Com async, ele anota o pedido, coloca o café pra fazer, e já atende o próximo — quando o café ficar pronto, ele avisa.
Operações assíncronas comuns: buscar dados de uma API (fetch), ler arquivos do disco, consultar banco de dados, aguardar um timer (setTimeout).

Síncrono vs. Assíncrono — veja ao vivo:

 Simulador de Execução
🖼️ renderPage
🌐 fetchDados
🎨 updateUI
// Escolha um modo acima e veja a diferença ↑
sincrono-vs-async.js
// ❌ SÍNCRONO — trava tudo!
console.log("1. Início")
const dados = buscarDados()  // espera 3s → trava!
console.log("2. Dados:", dados)
console.log("3. Fim")

// ✅ ASSÍNCRONO — não trava!
console.log("1. Início")
buscarDados().then(dados => {
  console.log("3. Dados:", dados)  // chega depois
})
console.log("2. Fim")  // executa ANTES dos dados!
// Saída: "1. Início" → "2. Fim" → "3. Dados"
🤝

Promises

Uma promessa de que algo vai acontecer no futuro

O que é uma Promise?

Uma Promise é um objeto que representa uma operação futura. Ela existe em 3 estados — e só passa por cada um uma vez, em sequência.

📦 Analogia: Um pedido de delivery. Assim que você pede, recebe um "número de rastreio" (a Promise). Ela começa Pendente. Quando o entregador chega, vira Resolvida. Se o restaurante cancelar, vira Rejeitada.
Pending
Operação em andamento
Fulfilled
Deu certo! Tem um valor
Rejected
Deu erro. Tem um motivo
← Clique em um estado para ver o código
promises.js
// Criando uma Promise
const minhaPromise = new Promise((resolve, reject) => {
  const deuCerto = true

  if (deuCerto) {
    resolve("🎉 Dados chegaram!")   // Fulfilled
  } else {
    reject("💥 Algo deu errado")   // Rejected
  }
})

// Consumindo com .then() / .catch()
minhaPromise
  .then(resultado => console.log(resultado))
  .catch(erro     => console.log(erro))
  .finally(()   => console.log("Sempre executa"))

⛓️ Encadeamento (.then chain)

Você pode encadear .then() para processar dados em etapas, como um pipeline. Cada .then() recebe o resultado do anterior.

fetch('/api/usuario')
Buscando dados do servidor...
.then(res => res.json())
Convertendo resposta para JSON...
.then(user => filtrar(user))
Processando dados do usuário...
.then(data => renderizar(data))
✅ Tudo pronto! UI atualizada.

Async / Await

A forma moderna e legível de escrever código assíncrono

O que é async/await?

async/await é açúcar sintático sobre Promises — faz código assíncrono parecer e se comportar como síncrono, mas sem travar. É muito mais legível que cadeias de .then().

📖 Analogia: É como escrever um roteiro linear — "Passo 1: busca os dados. Passo 2: processa. Passo 3: mostra." — mesmo que cada passo leve tempo, você lê e escreve de cima pra baixo, como uma história.
async-await.js
// Comparação: .then() vs async/await

// ❌ Com .then() — difícil de ler
buscarUsuario()
  .then(u => buscarPosts(u.id))
  .then(posts => renderizar(posts))
  .catch(err => tratarErro(err))

// ✅ Com async/await — limpo!
async function carregarPagina() {
  try {
    const usuario = await buscarUsuario()
    const posts   = await buscarPosts(usuario.id)
    renderizar(posts)
  } catch (erro) {
    tratarErro(erro)
  }
}

// await só funciona DENTRO de funções async
// try/catch captura erros das Promises

Regras de ouro do async/await

async na função → ela sempre retorna uma Promise automaticamente
await pausa só aquela função, não o programa inteiro
try/catch é o jeito correto de capturar erros com async/await
Promise.all([]) roda várias promises em paralelo — muito mais rápido!
promise-all.js
// Paralelo com Promise.all — muito mais rápido!
async function carregarTudo() {
  // ❌ Em série: 3s + 2s + 1s = 6 segundos
  const a = await tarefa1()  // espera 3s
  const b = await tarefa2()  // espera mais 2s

  // ✅ Em paralelo: max(3s, 2s, 1s) = 3 segundos!
  const [x, y, z] = await Promise.all([
    tarefa1(),
    tarefa2(),
    tarefa3()
  ])
}
🎮

Playground — Fetch Simulado

Simule chamadas à API e veja async/await em ação

Experimente! Escolha um endpoint simulado, defina o delay e clique em Buscar. Veja o async/await executar passo a passo e o resultado aparecer como uma API real.
 Simulador de fetch() com async/await
// resultado aparecerá aqui...
ao vivo
async function buscarDados() {
  try {
    const res    = await fetch("/api/...")
    const dados  = await res.json()
    return dados
  } catch (erro) {
    console.log("Erro:", erro)
  }
}
// ← Escolha um endpoint e clique em Executar
🌐

O que é o DOM?

A ponte entre JavaScript e a página HTML

Document Object Model

O DOM é a representação da página HTML em forma de árvore de objetos que o JavaScript pode ler e modificar. Quando o browser carrega uma página, ele cria esse modelo — e o JS pode acessar cada elemento como um objeto.

🎭 Analogia: O HTML é o roteiro de uma peça. O DOM é o cenário montado no palco. O JavaScript é o diretor que pode mover atores, trocar cenários e mudar o texto das falas — tudo em tempo real, sem parar o espetáculo.
💡 Importante: Você não edita o arquivo HTML diretamente — você manipula o DOM em memória. As mudanças aparecem na tela, mas o arquivo .html não muda.

🌳 Explore a árvore DOM — clique em um nó:

📄 document
<html>
<head>
<body>
<h1>"Olá Mundo"
<div id="app">
<button class="btn">
<p>"Texto aqui"
← Clique em um nó para ver como acessá-lo com JS
🎯

Selecionar Elementos

Encontrar elementos na página com querySelector

Os seletores principais

Antes de modificar qualquer coisa, você precisa encontrar o elemento. O JS usa os mesmos seletores CSS que você já conhece.

seletores.js
// Por ID — retorna 1 elemento
const titulo = document.getElementById("titulo")

// Por seletor CSS — retorna o 1º encontrado
const btn    = document.querySelector(".btn-primario")
const h1     = document.querySelector("h1")
const input  = document.querySelector("#email")

// Por seletor — retorna TODOS (NodeList)
const itens  = document.querySelectorAll("li")
const btns   = document.querySelectorAll(".btn")

// Percorrer todos
itens.forEach(item => console.log(item.textContent))
Dica de ouro: Prefira sempre querySelector — ele aceita qualquer seletor CSS e é mais flexível que os métodos antigos.

🧪 Teste os seletores ao vivo:

🎉 Título da Página

Este é um parágrafo com texto de exemplo.

🖼️ #logo
← Clique num botão para ver qual elemento seria selecionado
✏️

Modificar Elementos

Mudar texto, estilos, classes e criar elementos novos

modificar.js
const el = document.querySelector("#caixa")

// Mudar conteúdo
el.textContent = "Novo texto!"       // só texto
el.innerHTML   = "<b>Negrito!</b>"  // HTML dentro

// Mudar estilos CSS
el.style.color      = "red"
el.style.fontSize   = "24px"
el.style.display    = "none"    // esconde

// Gerenciar classes (preferível!)
el.classList.add("ativo")
el.classList.remove("ativo")
el.classList.toggle("ativo")  // liga/desliga

// Criar e inserir elementos
const novo = document.createElement("p")
novo.textContent = "Sou novo!"
document.body.appendChild(novo)

🎮 Painel de controle ao vivo:

🎯 Elemento #caixa
← Clique em uma operação para ver ao vivo
🎮

Eventos

Reagir às ações do usuário — cliques, teclas, scroll…

addEventListener

Eventos permitem que o JS reaja ao que o usuário faz. Você "escuta" um evento num elemento e define o que acontece quando ele ocorre.

🔔 Analogia: Como uma campainha. Você instala o sensor na porta (addEventListener) e define o que acontece quando tocar (a função callback) — o código só executa quando o evento ocorrer.
eventos.js
const btn = document.querySelector("#meu-btn")

// Ouvir um evento
btn.addEventListener("click", (event) => {
  console.log("Clicado!", event)
})

// Eventos comuns:
// "click"      → clique do mouse
// "input"      → usuário digita
// "submit"     → formulário enviado
// "keydown"    → tecla pressionada
// "mouseover"  → mouse passou por cima
// "DOMContentLoaded" → página carregou

// Objeto event tem info útil:
input.addEventListener("input", (e) => {
  console.log(e.target.value)  // o que foi digitado
})

🎮 Laboratório de Eventos — interaja abaixo:

Passe o mouse
// eventos aparecerão aqui quando você interagir acima ↑
🌿

O que é Git?

Um sistema de controle de versão distribuído

Git salva a história do seu código

Git é uma ferramenta que registra cada mudança no seu código ao longo do tempo. Você pode voltar a qualquer momento anterior, trabalhar em paralelo com outras pessoas e nunca perder trabalho.

💾 Analogia: Imagine um Google Docs com histórico infinito e superpoderes. Cada vez que você salva (commit), cria um checkpoint. Se algo der errado, você volta ao checkpoint. Você também pode criar cópias paralelas do documento (branches) para testar ideias sem mexer no original.
Git ≠ GitHub. Git é a ferramenta local no seu computador. GitHub é um site que hospeda repositórios Git na nuvem e facilita a colaboração.

📜 Histórico de commits — clique para explorar:

a3f9c2e HEADmain
feat: adicionar página de login
Ana Silva · há 2 horas
b7d1e4a
fix: corrigir bug no carrinho
Bruno Costa · há 5 horas
c2a8f3b
style: atualizar cores do tema
Ana Silva · ontem
d5f2c1a
feat: criar componente de navbar
Carlos Lima · há 2 dias
e1b0d9f
chore: initial commit
Ana Silva · há 3 dias
← Clique em um commit para ver detalhes
⌨️

Comandos Essenciais

Os 10 comandos que você usa 90% do tempo

Clique em qualquer comando abaixo para ver explicação e exemplo no terminal.
git init

Inicializa um repositório

git clone

Clona repositório remoto

git status

Ver estado atual

git add

Preparar arquivos

git commit

Salvar checkpoint

git push

Enviar pro servidor

git pull

Baixar atualizações

git branch

Criar/listar branches

git checkout

Trocar de branch

git merge

Juntar branches

git log

Ver histórico

git diff

Ver mudanças

← Selecione um comando acima
🌿

Branches

Linhas paralelas de desenvolvimento

O que é uma branch?

Uma branch é uma linha paralela de desenvolvimento. Você cria uma cópia independente do código para desenvolver uma feature ou corrigir um bug — sem afetar o código principal.

🛤️ Analogia: Imagine uma estrada (branch main). Você cria um desvio (feature branch) para construir uma ponte nova sem bloquear o tráfego. Quando a ponte fica pronta e testada, você une o desvio de volta à estrada principal (merge).

🗺️ Visualização de branches — diagrama ao vivo:

c1
c2
c3
c6
c7
c4
c5
main
feature/login
HEAD
branches.sh
# Criar e entrar na branch
git checkout -b feature/login

# Ver todas as branches
git branch
# * feature/login   ← branch atual
#   main

# Trabalhar normalmente...
git add .
git commit -m "feat: adicionar formulário de login"

# Voltar para main e fazer merge
git checkout main
git merge feature/login

# Apagar branch após merge
git branch -d feature/login
🎮

Simulador Git

Pratique o fluxo de trabalho completo

Experimente! Simule um fluxo de trabalho Git real clicando nos comandos em ordem. Veja os commits aparecendo no gráfico e o log do terminal.
COMMITS → branch: main
// Comece com "git init" ↑
🔍

O que são Algoritmos?

Receitas de passo a passo para resolver problemas

Algoritmo = receita de bolo

Um algoritmo é uma sequência finita de instruções para resolver um problema. Todo código que você escreve é um algoritmo — mas alguns são mais eficientes que outros.

📖 Analogia: Procurar uma palavra num dicionário. Você poderia ler da página 1 até achar (busca linear — lento) ou abrir no meio e decidir se vai pra esquerda ou direita (busca binária — muito mais rápido).
Por que aprender? Algoritmos eficientes fazem a diferença entre um app que demora 0.001s vs 10s para responder — especialmente com grandes volumes de dados.

As duas operações fundamentais

🔍
BUSCA
Encontrar um elemento numa coleção
📊
ORDENAÇÃO
Organizar elementos em ordem
📊

Algoritmos de Ordenação

Bubble Sort vs. Merge Sort — visualize ao vivo

Bubble Sort — O(n²)

Compara pares adjacentes e os troca se estiverem fora de ordem. Fácil de entender, mas lento para listas grandes.

📊 Visualizador de Ordenação
// clique num algoritmo para visualizar ↑
sort.js
// Bubble Sort — O(n²) — simples mas lento
function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length-i-1; j++) {
      if (arr[j] > arr[j+1]) {
        [arr[j], arr[j+1]] = [arr[j+1], arr[j]] // swap
      }
    }
  }
  return arr
}

// Merge Sort — O(n log n) — eficiente!
function mergeSort(arr) {
  if (arr.length <= 1) return arr
  const mid = Math.floor(arr.length / 2)
  const L = mergeSort(arr.slice(0, mid))
  const R = mergeSort(arr.slice(mid))
  return merge(L, R)
}

Big O Notation

Como medir a eficiência de um algoritmo

O que é Big O?

Big O descreve como o tempo de execução cresce conforme o tamanho da entrada aumenta. É a linguagem universal para comparar algoritmos.

📏 Analogia: Se você tem 1.000 itens vs 1.000.000 itens — quanto mais lento fica seu algoritmo? O(1) = igual. O(n) = 1000x mais lento. O(n²) = 1.000.000x mais lento!
O(1)
Constante
Sempre o mesmo tempo. Ex: acessar arr[0]
🚀
O(log n)
Logarítmico
Corta o problema pela metade. Ex: Binary Search
O(n)
Linear
Cresce proporcionalmente. Ex: Linear Search, for loop
🏃
O(n log n)
Linearítmico
Eficiente. Ex: Merge Sort, Quick Sort
🏋️
O(n²)
Quadrático
Lento para grandes entradas. Ex: Bubble Sort, loops aninhados
🐢
O(2ⁿ)
Exponencial
Evitar! Dobra a cada item. Ex: Fibonacci recursivo ingênuo
💀
🔄

O que é Recursividade?

Uma função que chama a si mesma

Definição

Recursividade é quando uma função chama a si mesma para resolver versões menores do mesmo problema, até chegar a um caso simples que pode ser resolvido diretamente.

🪞 Analogia: Dois espelhos frente a frente criam reflexos infinitos — mas em recursividade controlada, você tem uma condição de parada (base case) que impede o infinito.
Duas partes obrigatórias: Base Case — quando parar. Recursive Case — como reduzir o problema.
recursion.js
// ✅ Correto — tem base case!
function fatorial(n) {
  if (n <= 1) return 1       // ← BASE CASE
  return n * fatorial(n - 1)  // ← RECURSIVE CASE
}

fatorial(5)
// = 5 * fatorial(4)
// = 5 * 4 * fatorial(3)
// = 5 * 4 * 3 * fatorial(2)
// = 5 * 4 * 3 * 2 * fatorial(1)
// = 5 * 4 * 3 * 2 * 1 = 120 ✅

// ❌ Errado — sem base case = stack overflow!
function infinita(n) {
  return infinita(n - 1)  // nunca para!
}
📚

A Call Stack

Visualize como as chamadas se empilham e desempilham

O que é a Call Stack?

A call stack é uma pilha de chamadas de função. Cada vez que uma função é chamada, ela entra na pilha. Quando retorna, sai. Em recursão, muitas chamadas se acumulam antes de começar a retornar.

🎮 Visualizador — fatorial(5)
CALL STACK (topo = mais recente)
// clique em Executar para ver a pilha crescer ↑
🌳

Fibonacci & Árvore de Chamadas

Visualize a explosão de chamadas recursivas

Fibonacci recursivo

fib(n) = fib(n-1) + fib(n-2). Parece simples, mas cada chamada gera duas novas chamadas, criando uma árvore exponencial — é O(2ⁿ)!

🌳 Árvore de Fibonacci — clique nos nós
// clique em um nó ou gere a árvore ↑
fibonacci.js
// ❌ Ingênuo — O(2ⁿ) — muito lento!
function fib(n) {
  if (n <= 1) return n
  return fib(n-1) + fib(n-2)
}

// ✅ Com memoização — O(n) — muito mais rápido!
function fibMemo(n, memo = {}) {
  if (n in memo) return memo[n]
  if (n <= 1) return n
  memo[n] = fibMemo(n-1, memo) + fibMemo(n-2, memo)
  return memo[n]
}
🎮

Calculadora Recursiva

Execute funções recursivas e veja o resultado passo a passo

🎮 Escolha uma função recursiva
// selecione uma função acima ↑
🏗️

O que são Design Patterns?

Soluções reutilizáveis para problemas comuns de design de software

Padrões = vocabulário de devs sênior

Design Patterns são soluções testadas e documentadas para problemas que aparecem repetidamente no desenvolvimento de software. Você não inventa a solução — usa uma que já foi validada por milhares de devs.

🔧 Analogia: Como padrões de costura. Um estilista não reinventa como fazer uma manga a cada vez — usa o padrão existente e adapta. Padrões de projeto são os "padrões de costura" do código.
Organizados em 3 categorias: Criacionais — como criar objetos. Estruturais — como compor estruturas. Comportamentais — como objetos interagem.

Livro que originou tudo

O livro "Design Patterns: Elements of Reusable Object-Oriented Software" (1994), escrito pelos Gang of Four (GoF), documentou 23 padrões fundamentais que ainda são usados hoje.

📚

Catálogo de Padrões

Os mais importantes — clique para ver detalhes

1️⃣
Singleton
Criacional
Garante que uma classe tenha apenas uma instância
🏭
Factory
Criacional
Cria objetos sem expor a lógica de criação
👁️
Observer
Comportamental
Notifica múltiplos objetos quando algo muda
🎯
Strategy
Comportamental
Troca algoritmos em tempo de execução
🎁
Decorator
Estrutural
Adiciona comportamentos sem alterar a classe
🔀
MVC
Arquitetural
Separa Model, View e Controller
← Clique em um padrão para ver o código
👁️

Observer Pattern

O padrão por trás de eventos, React state e muito mais

Como funciona

Um Subject (publicador) mantém uma lista de Observers (assinantes). Quando algo muda no Subject, ele notifica todos automaticamente.

📰 Analogia: Uma newsletter. Você se inscreve (subscribe). Quando sai uma edição nova, todos os assinantes recebem ao mesmo tempo — sem precisar ficar verificando manualmente.
🎛️ Subject: EventBus
Observers registrados:
📊 Analytics — ouve: login, compra
📝 Logger — ouve: todos os eventos
🔔 Notificações — ouve: login
🛒 Carrinho — ouve: compra
🖥️ Monitor de Erros — ouve: erro
// emita um evento acima para ver os observers reagirem ↑
🏭

Factory Pattern

Crie objetos sem se preocupar com a implementação

Por que usar Factory?

Em vez de chamar new Classe() diretamente, você pede para uma fábrica criar o objeto certo baseado em parâmetros. Facilita extensão sem quebrar o código existente.

🏭 Fábrica de Notificações
// clique para criar uma notificação ↑
factory.js
class NotificationFactory {
  static create(type, msg) {
    const types = {
      email: EmailNotification,
      sms:   SMSNotification,
      push:  PushNotification,
    }
    const Cls = types[type]
    if (!Cls) throw new Error(`Tipo desconhecido: ${type}`)
    return new Cls(msg)
  }
}

// Uso — não precisa saber COMO é criado
const n = NotificationFactory.create("email", "Olá!")
n.send() // → Enviando email: "Olá!"
🔌

O que é uma API?

A linguagem comum entre sistemas diferentes

Application Programming Interface

Uma API é um contrato entre dois sistemas — define como eles podem se comunicar. Uma API REST usa o protocolo HTTP para trocar dados (geralmente em JSON) entre cliente e servidor.

🍽️ Analogia: Um restaurante. Você (cliente) não vai até a cozinha fazer sua comida — você faz o pedido ao garçom (API). O garçom leva o pedido à cozinha (servidor), busca a resposta (dados) e te entrega.

O fluxo básico

📱
Cliente
App / Browser
──── REQUEST ────→
←─── RESPONSE ───
🔌
API REST
Interface
──── QUERY ──────→
←─── DATA ────────
🖥️
Servidor
+ Database
🌐

HTTP — Métodos & Status

A linguagem da web

Os 5 métodos HTTP

Cada operação tem um método semântico — o verbo que descreve o que você quer fazer com o recurso.

GET
POST
PUT
PATCH
DELETE
← Clique em um método para ver exemplos

Status Codes — a resposta do servidor

Todo response tem um código numérico indicando o resultado. Clique para ver o significado.

200OK
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
500Server Error
← Clique em um status code
📄

JSON

O formato padrão para troca de dados na web

JavaScript Object Notation

JSON é um formato de texto para representar dados estruturados. Parece muito com objetos JS, mas tem regras estritas: chaves sempre entre aspas duplas, sem comentários, sem vírgula no último item.

exemplo.json
{
  "id": 1,
  "nome": "Ana Silva",
  "ativo": true,
  "score": 9.5,
  "tags": ["dev", "frontend"],
  "endereco": {
    "cidade": "São Paulo",
    "uf": "SP"
  },
  "foto": null
}
json-parse.js
// JSON → Objeto JS
const jsonStr = '{"nome":"Ana","idade":28}'
const obj = JSON.parse(jsonStr)
console.log(obj.nome)  // → "Ana"

// Objeto JS → JSON
const dados = { nome: "Bruno", ativo: true }
const str   = JSON.stringify(dados)
// → '{"nome":"Bruno","ativo":true}'

// Pretty print (indentação)
JSON.stringify(dados, null, 2)
🎮

REST Client Simulado

Faça requests para uma API fake e veja as respostas

Experimente! Escolha o método, selecione um endpoint e envie a requisição. Veja os headers, body e resposta JSON exatamente como numa API real.
// A resposta aparecerá aqui...
fetch.js
// Selecione método e endpoint acima ↑
const res   = await fetch("...")
const dados = await res.json()
💡

O que é Terminal?

A interface que separa devs de usuários comuns

Terminal vs GUI — dois caminhos para a mesma máquina

Quando você usa um computador, normalmente clica em ícones, arrasta janelas e interage com interfaces gráficas (GUI). O terminal é o outro caminho: você digita comandos de texto e o sistema operacional executa exatamente o que você pediu. Sem menus, sem cliques — só texto puro e poder absoluto.

🎯 Analogia: Imagine um restaurante. Usar a GUI é como pedir pelo cardápio ilustrado — você aponta pro prato e pronto. Usar o terminal é como falar diretamente com o chef — você pode pedir qualquer combinação, qualquer preparo especial, sem limitações do cardápio.

Shell, Terminal & Console — qual a diferença?

Terminal é a janela (o programa) onde você digita. Shell é o interpretador que entende seus comandos (exemplos: Bash, Zsh, PowerShell). Console é o nome histórico que veio dos primeiros computadores físicos. No dia a dia, usamos esses termos como sinônimos — e tá tudo bem.

primeiro-comando.sh
# O comando mais clássico de todos:
echo "Hello, World!"
# → Hello, World!

# Ver o diretório atual:
pwd
# → /home/artclass

# Listar arquivos da pasta:
ls
# → Documents  Downloads  projeto  index.html
💡 Por que devs amam o terminal? Velocidade. Tarefas que demoram 10 cliques na GUI levam 1 comando no terminal. Instalar pacotes, iniciar servidores, fazer deploy, controlar Git — tudo é mais rápido via CLI. Toda vaga de dev exige familiaridade com o terminal.

Anatomia de um comando

Todo comando no terminal segue este padrão:

🔍 Estrutura de um Comando

Formato
comando [opções] [argumentos]

Exemplo real
ls -la /home

Significado
ls → listar arquivos
-la → -l (formato longo) + -a (incluir ocultos)
/home → o diretório alvo
⌨️

Comandos Essenciais

Os 10 comandos que você vai usar todos os dias

Seu toolkit básico de sobrevivência no terminal

Esses são os comandos mais usados no dia a dia de qualquer desenvolvedor. Com eles, você navega pelo sistema, cria e remove arquivos, e encontra o que precisa. Clique em cada card abaixo para ver a sintaxe e um exemplo prático.

ls

Listar arquivos e pastas

cd

Navegar entre diretórios

mkdir

Criar uma nova pasta

touch

Criar um novo arquivo

rm

Remover arquivo ou pasta

cp

Copiar arquivo ou pasta

mv

Mover ou renomear

cat

Ver conteúdo de arquivo

grep

Buscar texto em arquivos

echo

Imprimir texto no terminal

← Clique em um comando acima para ver detalhes
⚡ Dicas Pro: Pressione Tab para auto-completar nomes de arquivos. Use ↑ / ↓ para navegar no histórico de comandos. Ctrl+C cancela qualquer comando. Ctrl+L limpa a tela (ou digite clear).
workflow-real.sh
# Um workflow real de dev — criando um projeto do zero:

mkdir meu-projeto         # cria a pasta
cd meu-projeto            # entra nela
touch index.html          # cria arquivo HTML
touch style.css           # cria arquivo CSS
mkdir src                  # cria pasta para JS
touch src/app.js          # cria o arquivo principal
ls -la                    # verifica tudo criado
# → index.html  style.css  src/

Pipes & Redirecionamento — o superpoder do terminal

O pipe | conecta a saída de um comando à entrada de outro. O > redireciona saída para um arquivo. Isso permite criar cadeias poderosas de comandos.

pipes.sh
# Encontrar todos os arquivos .js e contar quantos são:
find . -name "*.js" | wc -l
# → 23

# Ver os processos que mais usam memória:
ps aux | sort -k4 -rn | head -5

# Salvar listagem em um arquivo:
ls -la > lista.txt

# Adicionar ao final (sem sobrescrever):
echo "nova linha" >> lista.txt
📂

Sistema de Arquivos & Permissões

Como o Linux organiza tudo — e quem pode acessar o quê

A árvore do sistema Linux

No Linux, tudo começa na raiz /. Diferente do Windows (C:\, D:\), o Linux tem uma única árvore de diretórios. Cada pasta tem um propósito específico. Conheça as mais importantes:

/ ← raiz de tudo
home/ ← pastas dos usuários
artclass/
Documents/
projetos/
.bashrc
etc/ ← configurações do sistema
var/ ← logs e dados variáveis
usr/ ← programas instalados
tmp/ ← arquivos temporários
bin/ ← comandos essenciais
Clique em uma pasta acima para ver detalhes

Caminhos Absolutos vs Relativos

Absoluto começa com / — é o endereço completo desde a raiz. Ex: /home/artclass/projetos
Relativo parte do diretório atual. Ex: ../projetos (volta uma pasta, depois entra em projetos).
~ é um atalho para /home/seu-usuario. Ex: cd ~/projetos

Permissões — rwx (read, write, execute)

No Linux, cada arquivo tem 3 grupos de permissão: dono, grupo e outros. Cada grupo pode ter permissão de leitura (r=4), escrita (w=2) e execução (x=1). Clique nos botões abaixo para montar o chmod!

🔐 Calculadora de Permissões (chmod)

Dono (u)

Grupo (g)

Outros (o)

chmod 755 → rwxr-xr-x
🔑 Atalho mais comum: chmod 755 script.sh — dá permissão total ao dono e leitura+execução para o resto. chmod 644 arquivo.txt — dono lê e escreve, resto só lê.
permissoes.sh
# Ver permissões detalhadas:
ls -la
# → -rwxr-xr-x  1  artclass  staff  2048  Mar 3  app.js
#    │├─┤├─┤├─┤
#    │ u   g   o    ← dono / grupo / outros
#    └ tipo (- = arquivo, d = diretório)

# Tornar um script executável:
chmod +x deploy.sh

# Mudar dono do arquivo:
chown artclass:devs projeto/
🎮

Terminal Simulado

Digite comandos reais e veja o resultado ao vivo

🚀 Experimente! Este é um terminal simulado com sistema de arquivos virtual. Digite comandos como ls, cd pasta, mkdir projeto, touch arquivo.txt e muito mais. Digite help para ver todos os comandos disponíveis.
artclass — bash
Bem-vindo ao Terminal ArtClass.Dev! 🎉
Digite help para ver os comandos disponíveis.
─────────────────────────────────────────
artclass@dev:~$

🏆 Desafio: Crie um projeto do zero!

Complete os passos abaixo usando o terminal acima. A checklist vai atualizar automaticamente conforme você avança.

Crie a pasta projeto com mkdir projeto
Entre na pasta com cd projeto
Crie um arquivo index.html com touch index.html
Verifique com ls se o arquivo foi criado
Escreva algo no arquivo: echo "Hello" > index.html
Veja o conteúdo com cat index.html
💡

O que é SQL?

A linguagem universal dos bancos de dados

SQL — Structured Query Language

SQL é a linguagem usada para conversar com bancos de dados. Com ela você pode perguntar "quais usuários têm mais de 18 anos?" ou "adicione este novo produto ao catálogo" — e o banco responde ou executa na hora.

🏪 Analogia: Imagine um supermercado gigante com milhões de produtos nas prateleiras. O SQL é como um funcionário super eficiente — você pede "me traga todos os chocolates abaixo de R$10" e ele encontra tudo em segundos, sem precisar procurar prateleira por prateleira.

🗄️ Banco de Dados Relacional

Os dados são organizados em tabelas — como planilhas do Excel. Cada tabela tem colunas (campos) e linhas (registros).

📐 Estrutura de um Banco

Hierarquia
🗄️ Banco de Dados — contém várias tabelas
📋 Tabela — organiza dados de um assunto (ex: produtos)
📊 Colunas — definem os campos (nome, preço, estoque...)
📝 Linhas — cada registro/entrada de dado
Exemplo: tabela "produtos"
id · nome · preço · categoria · estoque
primeiro-select.sql
-- Minha primeira consulta SQL!
-- SELECT = "me mostre"   FROM = "da tabela"

SELECT * FROM produtos;
-- → Retorna TODAS as colunas e TODAS as linhas

SELECT nome, preco FROM produtos;
-- → Retorna só nome e preço de cada produto

SELECT nome, preco FROM produtos
  WHERE preco > 300;
-- → Só produtos acima de R$300

SELECT * FROM produtos
  ORDER BY preco DESC;
-- → Todos, ordenados do mais caro ao mais barato
💡 Por que SQL importa? SQL é usado em 90% dos sistemas — apps, sites, jogos, análise de dados, IA. Todo dev precisa saber pelo menos o básico. Bancos como PostgreSQL, MySQL e SQLite usam SQL!

📝 Terminologia Essencial

Query = consulta/pergunta ao banco · Schema = estrutura das tabelas · PK (Primary Key) = identificador único de cada linha · FK (Foreign Key) = referência a outra tabela

⌨️

CRUD — As 4 Operações

Create, Read, Update, Delete — tudo que você faz com dados

O que é CRUD?

CRUD é a sigla para as 4 operações fundamentais que todo sistema faz com dados. Qualquer app que você usa — Instagram, Spotify, iFood — por baixo está fazendo CRUD o tempo todo.

📱 Analogia: Pense na sua lista de contatos do celular. Você adiciona (Create) um contato novo, busca (Read) alguém pelo nome, edita (Update) o número, e apaga (Delete) quem não precisa mais. CRUD é exatamente isso!

C — CREATE (INSERT)

Adicionar novos registros à tabela

Usa o comando INSERT INTO para criar linhas novas. Você especifica a tabela, as colunas e os valores.
🔍

R — READ (SELECT)

Consultar e buscar dados

O comando mais usado! SELECT lê dados com filtros (WHERE), ordenação (ORDER BY) e agrupamento (GROUP BY).
✏️

U — UPDATE

Modificar dados existentes

UPDATE ... SET altera valores. Sempre use WHERE — sem filtro, atualiza TODAS as linhas!
🗑️

D — DELETE

Remover registros

DELETE FROM ... WHERE remove linhas. Cuidado: sem WHERE, apaga TUDO da tabela!
crud-completo.sql
-- ➕ CREATE — adicionar produto
INSERT INTO produtos (nome, preco, categoria, estoque)
VALUES ('Headset Gamer', 199, 'Periféricos', 20);

-- 🔍 READ — buscar produtos caros
SELECT nome, preco FROM produtos
  WHERE preco > 500
  ORDER BY preco DESC;

-- ✏️ UPDATE — dar desconto de 10%
UPDATE produtos
  SET preco = preco * 0.9
  WHERE categoria = 'Eletrônicos';

-- 🗑️ DELETE — remover sem estoque
DELETE FROM produtos
  WHERE estoque = 0;
⚠️ Dica de ouro: NUNCA execute UPDATE ou DELETE sem WHERE! Sem filtro, o comando afeta TODAS as linhas da tabela. Sempre teste primeiro com SELECT para ver o que seria afetado.
funcoes-agregadas.sql
-- Funções que calculam sobre grupos de dados

SELECT COUNT(*) FROM produtos;
-- → Quantos produtos existem? (ex: 6)

SELECT SUM(estoque) FROM produtos;
-- → Soma total do estoque (ex: 181)

SELECT AVG(preco) FROM produtos;
-- → Preço médio (ex: 1164.67)

SELECT MIN(preco), MAX(preco) FROM produtos;
-- → Mais barato e mais caro

SELECT categoria, COUNT(*) as total
  FROM produtos
  GROUP BY categoria;
-- → Quantos produtos por categoria
🔗

JOINs & Relacionamentos

Conectando tabelas para obter dados completos

Por que relacionar tabelas?

Na vida real, dados estão espalhados em várias tabelas. Uma loja tem tabela de "produtos", outra de "pedidos", outra de "clientes". O JOIN conecta essas tabelas usando um campo em comum.

📎 Analogia: Imagine duas planilhas — "Alunos" com nome e matrícula, e "Notas" com matrícula e nota. O JOIN é como um grampo que prende as duas usando a matrícula em comum, criando uma visão completa: nome + nota.

🔑 Chaves — O Elo entre Tabelas

Primary Key (PK) — identificador único de cada linha (geralmente id). Nenhuma linha pode ter o mesmo PK.
Foreign Key (FK) — campo que referencia o PK de outra tabela. É o "ponteiro" que cria a relação.

📐 Exemplo de Relacionamento

Tabela: clientes
id (PK) · nome · email
Tabela: pedidos
id (PK) · cliente_id (FK → clientes.id) · produto · valor
Relação
Um cliente pode ter VÁRIOS pedidos (1:N)
inner-join.sql
-- INNER JOIN — retorna só onde há correspondência
-- "Me mostre o nome do cliente e seus pedidos"

SELECT clientes.nome, pedidos.produto, pedidos.valor
  FROM clientes
  INNER JOIN pedidos
    ON clientes.id = pedidos.cliente_id;

-- Resultado:
-- Ana    | Notebook  | 3500
-- Ana    | Mouse     | 189
-- Bruno  | Monitor   | 2200
-- (Carlos não aparece — não tem pedidos!)

INNER JOIN

Retorna só o que conecta nas DUAS tabelas

O mais comum! Se um cliente não tem pedidos, ele não aparece. Só traz linhas com correspondência em ambos os lados.

LEFT JOIN

Tudo da esquerda + correspondências da direita

Traz todos os clientes, mesmo quem não tem pedidos (campos ficam NULL). Útil para encontrar "clientes que nunca compraram".

RIGHT JOIN

Tudo da direita + correspondências da esquerda

Inverso do LEFT. Traz todos os pedidos, mesmo sem cliente associado. Na prática, LEFT JOIN é mais usado — basta inverter a ordem das tabelas.

FULL OUTER JOIN

Tudo de ambas as tabelas

Combina LEFT + RIGHT. Traz tudo, preenchendo com NULL onde não há correspondência. Menos comum mas útil em relatórios completos.
left-join.sql
-- LEFT JOIN — todos da esquerda, mesmo sem match

SELECT clientes.nome, pedidos.produto
  FROM clientes
  LEFT JOIN pedidos
    ON clientes.id = pedidos.cliente_id;

-- Resultado:
-- Ana    | Notebook
-- Ana    | Mouse
-- Bruno  | Monitor
-- Carlos | NULL      ← aparece, mas sem pedido!

-- Encontrar quem NUNCA comprou:
SELECT clientes.nome
  FROM clientes
  LEFT JOIN pedidos
    ON clientes.id = pedidos.cliente_id
  WHERE pedidos.id IS NULL;
-- → Carlos
💡 Regra prática: Use INNER JOIN quando quer só dados completos (com match). Use LEFT JOIN quando precisa ver TODOS de uma tabela, mesmo sem correspondência na outra. Na maioria dos projetos, esses dois cobrem 95% dos casos!
🎮

Playground SQL

Escreva queries e veja os resultados ao vivo!

🗃️
SQL Sandbox Tabela "produtos" com 6 registros · Digite uma query e execute
📋 Dados atuais da tabela:
SELECT *
WHERE preco > 300
ORDER BY
GROUP BY
AVG()
INSERT
UPDATE
DELETE
← Escreva uma query e clique em Executar
🧪 Experimente! Tente combinar: SELECT nome FROM produtos WHERE estoque > 30 ORDER BY nome. Ou insira novos itens e veja a tabela crescer em tempo real!