Por que separar em camadas
Se você juntar o acesso a dados, a validação e a lógica HTTP em uma única função, acaba com um código impossível de testar e de manter. Uma API limpa separa responsabilidades em camadas, cada uma com um trabalho:
Requisição HTTP
│
▼
[ middleware ] ── auth (quem é você?) e validação (dados corretos?)
│
▼
[ controlador/handler ] ── traduz HTTP ↔ dados: lê req, responde res
│
▼
[ repositório ] ── lê e escreve no armazenamento (aqui, um array em memória)
O repositório (acesso a dados)
Funções JavaScript puras que operam sobre o armazenamento. Não sabem nada de HTTP:
function criar(tarefas, titulo) {
const tarefa = { id: tarefas.length + 1, titulo, feita: false };
tarefas.push(tarefa);
return tarefa;
}
function buscarPorId(tarefas, id) {
return tarefas.find((t) => t.id === id);
}
Os middleware (auth e validação)
Eles rodam antes do handler. Se algo der errado, respondem e cortam a
cadeia; se estiver tudo bem, chamam next():
function requerAuth(req, res, next) {
if (!req.headers.authorization) {
res.status(401).json({ error: "Não autorizado" });
return;
}
next();
}
O handler (controlador)
É o único que toca em req e res: lê a entrada, chama o repositório e
escolhe o código de status e o corpo da resposta:
function criarTarefa(req, res) {
const tarefa = criar(tarefas, req.body.titulo);
res.status(201).json(tarefa);
}
Neste módulo você vai construir cada peça separadamente e verificar que funciona de forma isolada. É assim que se monta uma API que escala.