CiudadLab

Blog / arquitetura

Engenhariaarquiteturakelly academyjava

Por que a Kelly Academy usa arquitetura hexagonal (e quando eu não usaria)

Arquitetura importa num SaaS na hora em que algo fora dele muda. Na Kelly, isso já aconteceu mais de uma vez.

EC

Eduardo Ciudad

9 de novembro de 2026 · 2 min de leitura

AvaliacaoIAPort.javaGeminiAvaliacaoAdapter.java
1package eduar.studymindredacao.domain.port;
2 
3import eduar.studymindredacao.domain.model.ResultadoAvaliacaoIA;
4import eduar.studymindredacao.domain.model.SolicitacaoAvaliacao;
5 
6public interface AvaliacaoIAPort {
7 
8    ResultadoAvaliacaoIA avaliar(SolicitacaoAvaliacao solicitacao);
9}
A estrutura real do projeto e a porta que separa a correção do Gemini.

EM 30 SEGUNDOS

  1. 1A Kelly depende de três coisas que eu não controlo: IA, pagamento e e-mail.
  2. 2O domínio diz do que precisa; adaptadores entregam e podem ser trocados.
  3. 3Custa mais arquivos. Vale quando o que está fora do sistema muda, e num SaaS sempre muda.

01

O problema

Três coisas que eu não controlo

A Kelly Academy corrige redações do ENEM com IA, cobra assinatura e manda e-mail. Qualquer um desses serviços pode mudar de preço, de versão ou de regra, e nenhum deles pergunta antes.

IA

Gemini

Modelo, preço e limites mudam sem aviso.

Pagamento

Stripe

Precisou existir antes de estar pronto.

E-mail

SMTP

Provedor pode mudar; o fluxo de senha não.

02

A ideia

As regras no centro, o resto do lado de fora

A arquitetura hexagonal é uma forma de garantir que, quando algo de fora mudar, o que muda junto seja pequeno. O centro diz do que precisa. Quem entrega fica do lado de fora.

ENTRADANÚCLEOSAÍDAquem chama o sistemao que o sistema usaCASOS DE USOapplication.usecaseEnviarRedacaoServiceIniciarCheckoutServiceDomíniodomain.modeldomain.servicedomain.juliaregras da nota e dos planosRedacaoControlleradapter.in.webAvaliacaoIAPortGeminiAvaliacaoAdapteradapter.out.iaPagamentoGatewayPortStripePagamentoAdapteradapter.out.pagamentoEnvioEmailPortSmtpEnvioEmailAdapteradapter.out.emailRedacaoRepositoryPortRedacaoRepositoryAdapteradapter.out.persistenceAs setas mostram quem depende de quem: todas apontam para dentro.
Os nomes são os pacotes e as classes reais da Kelly Academy.

03

Na prática

Uma redação atravessando o hexágono

Quando o aluno envia um texto, ele passa por quatro lugares. Só o último sabe que o Gemini existe.

PASSO 1

RedacaoController

adapter.in.web

Recebe o texto do aluno.

PASSO 2

EnviarRedacaoService

application.usecase

Valida o tema e os limites do plano.

PASSO 3

AvaliacaoIAPort

domain.port

Pede a avaliação, sem saber quem avalia.

PASSO 4

GeminiAvaliacaoAdapter

adapter.out.ia

Monta o prompt e chama o Gemini.

No caso de uso, a chamada é uma linha. Ele fala com a porta, não com o Gemini:

application/usecase/EnviarRedacaoService.java
public RedacaoDetalhada enviar(UUID usuarioId, UUID temaId, TipoRedacao tipo,
                               String texto, OrigemRedacao origem) {
    // ...
    var resultado = avaliacaoIA.avaliar(
            new SolicitacaoAvaliacao(tema.titulo(), texto));
    // ...
}
O domínio não sabe que o Gemini existe. É por isso que trocar o Gemini é barato.

04

O retorno

Três vezes em que isso pagou a conta

01

Trocar o modelo de IA

A correção conversa com uma porta, não com o Gemini. Trocar de modelo mexe no adaptador e no prompt; a regra da nota fica onde está.

GeminiAvaliacaoAdapter

02

Pagamento desligado sem if

Antes do Stripe estar pronto, um adaptador que só responde “ainda não disponível” ocupou o lugar. O e-mail ganhou um igual.

PagamentoDesligadoAdapter

03

Quase 1.300 testes

Regras de correção, planos e limites de uso são testadas com portas falsas: sem chamar a IA e sem cobrar ninguém.

1.288 @Test no repositório

O segundo é o meu favorito. O pagamento ainda não estava pronto, e o sistema precisava funcionar mesmo assim. Quando o Stripe ficou pronto, troquei o adaptador na configuração. É a mesma lógica do post sobre planos Grátis e Pro sem if.

adapter/out/pagamento/PagamentoDesligadoAdapter.java
public class PagamentoDesligadoAdapter implements PagamentoGatewayPort {
 
    static final String MENSAGEM = "Pagamento ainda não está disponível";
 
    @Override
    public SessaoCheckout criarSessaoCheckout(SolicitacaoCheckout solicitacao) {
        throw desligado();
    }
}

Trocar o modelo de IA: o que entra no diff

·domain/0 arquivos
·application/usecase/0 arquivos
·domain/port/AvaliacaoIAPort.javasem mudança
Madapter/out/ia/GeminiConfig.java+3 −3
Madapter/out/ia/PromptAvaliacaoBuilder.java+12 −8
Exemplo ilustrativo do tamanho de uma troca de modelo.

05

O custo

O custo honesto

Mais arquivos, mais interfaces e um mapper entre o banco e o domínio. Para uma tela de cadastro simples, isso é burocracia.

UM CONCEITO SÓ

para salvar e ler uma redação no banco. Num CRUD simples, seriam dois.

  1. 1

    Redacao.java

    domain.model

  2. 2

    RedacaoRepositoryPort.java

    domain.port

  3. 3

    RedacaoRepositoryAdapter.java

    adapter.out.persistence

  4. 4

    RedacaoJpaRepository.java

    persistence.repository

  5. 5

    RedacaoEntity.java

    persistence.entity

  6. 6

    RedacaoPersistenceMapper.java

    persistence.mapper

No começo parece lento. O retorno aparece quando algo de fora muda e a mudança cabe num arquivo.

06

A decisão

Quando vale a pena num SaaS

VALE A PENA QUANDO

  • ✓O produto depende de serviços que mudam: IA, pagamento, e-mail
  • ✓As regras do negócio são o produto
  • ✓Vai durar anos e ter mais gente mexendo
  • ✓Você quer testar regra sem subir infraestrutura

EU NÃO USARIA QUANDO

  • —Landing page ou site institucional
  • —CRUD simples, sem regra de verdade
  • —MVP para descobrir se alguém quer
  • —Script ou automação interna

FIM

O que levar daqui

Arquitetura não é sobre pastas bonitas. É sobre o tamanho do estrago quando algo que você não controla muda. Num SaaS, sempre muda.

O Radar, que foi ao ar este mês, segue o mesmo desenho, porque também depende de um serviço de fora: o Google Analytics.

EC

Eduardo Ciudad

Desenvolvedor backend e fundador da CiudadLab. Escreve sobre o que constrói e coloca no ar.

LEIA TAMBÉM