DevPath · Aprenda a programar ESPTEN

Dados, ORMs e arquitetura em camadas

Arquitetura em camadas

Separar responsabilidades

Uma aplicação de backend manutenível separa o código em camadas, cada uma com uma única responsabilidade. A requisição as atravessa de fora para dentro:

HTTP → Controlador → Serviço → Repositório → Banco de dados

Controlador (HTTP)

É o handler (req, res). Seu único trabalho é traduzir HTTP: ler req.body/req.params, chamar o serviço e responder com o status e o JSON adequados. Não contém regras de negócio nem SQL.

async function criar(req, res) {
  const usuario = await servico.registrar(req.body);
  res.status(201).json(usuario);
}

Serviço (lógica de negócio)

Contém as regras: validações de domínio, "não permitir emails duplicados", calcular totais, orquestrar vários repositórios. Não sabe de req/res nem de SQL; pede dados ao repositório.

async function registrar(dados) {
  const existe = await repo.buscarPorEmail(dados.email);
  if (existe) throw new Error("Email duplicado");
  return repo.criar(dados);
}

Repositório (dados)

O que você viu antes: acesso a dados.

Injeção de dependências

Repare que o serviço usa repo e o controlador usa servico. Em vez de criar essas dependências dentro (const repo = new RepoSQL()), elas são recebidas de fora. Isso é injeção de dependências:

function criarServico(repo) {        // recebe o repo como parâmetro
  return {
    async registrar(dados) {
      if (await repo.buscarPorEmail(dados.email)) {
        throw new Error("Email duplicado");
      }
      return repo.criar(dados);
    },
  };
}

Vantagens: em produção você injeta o repositório real; nos testes você injeta um mock ou um repo em memória, sem tocar no serviço. Cada camada se testa isolada, e o conjunto fica desacoplado e fácil de mudar.

Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← O padrão RepositórioAlém do monólito: microsserviços e eventos →