Intermediate Class - Ballet Intermediate Class - IFBC
Ballet Intermediate Class - IFBC

O que é uma classe intermediária na prática

Uma classe intermediária é aquele trecho de código que aparece quando você precisa separar lógica de negócio da interface com o banco de dados ou com APIs externas. Não é um padrão elegante. É mais uma correção que todo mundo acaba escrevendo depois de se dar mal com acoplamento direto. Eu comecei a usar esse conceito há uns anos porque meus controladores estavam virando sucos de funcionalidades e testá-los era um pesadelo.

Classe intermediária serve para intermediar, como o nome já diz. Ela fica entre a camada que recebe a requisição e a camada que efetivamente processa os dados. O resultado é código mais legível, mais testável e muito menos dependência de frameworks específicos.

Por que usar intermediate class no seu projeto

Eu fiz isso pela primeira vez num projeto de Ruby on Rails onde tínhamos um serviço de pagamento integrado com múltiplos provedores. O controlador chamava diretamente os três provedores, fazia parsing, tratava erros e montava respostas. Tinha umas 400 linhas. Depois de extrair tudo para uma classe intermediária que chamava um adapter em cada caso, o controlador ficou com 12 linhas. Sim, 12. A diferença não é estética, é funcional. Mudar o provedor de pagamento virou alterar uma classe, não caçar código em cinco arquivos. O problema que eu encontrei na prática foi mais específico do que o normal. Tinhamos um caso onde a resposta do provedor A vinha em JSON e a do B vinha em XML, mas ambos precisavam ser convertidos para o mesmo modelo interno. A classe intermediária começou a virar um filtro de formatos e aí a coisa apertou. Eu resolvi criando um método privado dentro dela que aceitava qualquer formato de entrada e devolvia um hash padronizado antes de qualquer processamento. O ganho foi imediato: não precisei mexer na estrutura principal quando adicionamos um terceiro provedor meses depois.

Como implementar passo a passo

O primeiro passo é identificar onde a complexidade mora. Geralmente é onde você vê chamadas diretas a bibliotecas externas, conversões de dados repetidas ou testes que precisam de um banco de dados rodando. Quando encontrar esses pontos, isola aquela lógica numa classe separada.

Dentro dessa classe, defina uma interface clara. Métodos públicos que façam sentido do ponto de vista do domínio, não do framework. Se você precisa de um método chamado processar_dado_do_banco_mongo_db, está fazendo errado. Um nome como atualizar_cadastro já comunica a intenção real. O segundo passo é lidar com as dependências. Injeta-as pelo construtor, nunca importa a classe lá dentro. Isso parece óbvio, mas na prática muita gente esquece e depois passa horas quebrando a cabeça porque o teste unitário falha por causa de uma dependência que deveria estar isolada.

👉 Clique no botão abaixo para saber mais sobre o assunto!

O terceiro passo é escrever o teste primeiro. Antes de colocar qualquer lógica na classe intermediária, escreva o caso de uso esperado. Isso te força a pensar na interface antes de se perder nos detalhes da implementação. Eu vi muitos colegas pularem essa etapa e acabarem com classes que resolviam problemas que nunca deveriam existir.

Pegadinhas que ninguém conta

Aarmadilha mais comum é criar uma classe intermediária que só repassa chamadas. Isso é um anti-padrão e se chama God Class disfarçada. Se a sua classe intermediária está apenas delegando para outras classes sem adicionar valor, ela não está fazendo nada pelo seu código. Remova e use as classes originais direto.

Outro erro frequente é confundir classe intermediária com facade. A facade esconde complexidade. A classe intermediária traduz entre camadas. Elas têm propósitos diferentes e misturá-las gera confusão na hora de manter o código.

Eu tive um caso bem específico onde precisei lidar com rate limiting de uma API externa dentro da classe intermediária. A solução ingênua seria colocar o controle de requisições dentro da própria classe, mas isso criava um acoplamento que eu não queria. A solução foi usar um middleware de taxa separado que interceptava as chamadas antes de chegar à classe intermediária. O ganho foi poder reutilizar esse middleware em outros lugares do sistema sem precisar duplicar a lógica.

Quando não usar

Classes intermediárias não são bala de prata. Se o seu sistema é pequeno, se você não tem múltiplas fontes de dados, se os testes não são necessários no momento, adicionar uma camada extra só vai aumentar a complexidade desnecessariamente. Eu já vi gente criar classes intermediárias para métodos que faziam três linhas de código e depois se arrependerem porque a manutenção virou uma caça ao tesouro. O custo real de introduzir uma classe intermediária é o tempo de onboarding de quem chega no projeto. Alguém novo precisa entender onde a lógica está, como as camadas se comunicam, e qual a responsabilidade de cada uma. Se isso não traz benefício proporcional, talvez seja melhor deixar como está.

Intermediate class vs service layer: qual escolher

A diferença principal está na granularidade. Service layer é mais abrangente e geralmente lida com fluxos completos de uso. Classe intermediária é mais pontual, focada em um detalhe específico de tradução ou adaptação. Eu uso service layer quando preciso orquestrar múltiplos passos. Uso classe intermediária quando preciso converter algo de um formato para outro de forma reutilizável. Na prática, eu costumo começar com uma classe intermediária e, se a coisa crescer, transformo em service layer. Isso evita antecipar complexidade que talvez nunca apareça.