Quiz
Clique em "Resposta" para revelar a resposta correta e a explicação.
Q1. Por que o catalog devolve records EventOut em vez da entidade JPA Event?
- A. Records são serializados mais rápido que classes
- B. O contrato da API fica independente da tabela: colunas novas não vazam, e associações lazy nunca são serializadas fora de uma transação
- C. O Spring MVC não consegue serializar entidades
- D. Entidades não podem ter um campo
id
Resposta
B — Desacoplar o contrato do armazenamento.
Uma entidade é um mapeamento de tabela; um DTO é uma promessa aos clientes. Se forem o mesmo objeto, toda mudança de schema é uma mudança de API, e um venue lazy tocado pelo Jackson depois do fim da transação lança LazyInitializationException.
Q2. Listar 20 eventos sem join fetch e.venue executa quantas consultas SQL (ignorando a contagem)?
- A. 1
- B. 2
- C. 20
- D. 21
Resposta
D — 21: o problema N+1.
Uma consulta carrega os 20 eventos; depois cada event.getVenue() dispara mais uma. Com join fetch vira um único JOIN. Sob carga, 21 idas e voltas por requisição multiplicam o tempo em que cada requisição segura uma conexão do pool.
Q3. Um colega edita V2__seed_catalog.sql, que já rodou na máquina de todos, para corrigir um erro de digitação. O que acontece na próxima inicialização?
- A. O Flyway aplica a nova versão da V2 automaticamente
- B. O Flyway detecta um checksum diferente e o serviço não inicia
- C. Nada: o Flyway ignora arquivos que já rodaram
- D. O Hibernate corrige os dados com
ddl-auto
Resposta
B — Checksum diferente, a inicialização falha.
O Flyway guarda um checksum de toda migration aplicada. Migrations aplicadas são história e não podem mudar; uma correção vai em uma nova migration (V3__fix_typo.sql). É isso que faz todo ambiente convergir para o mesmo schema.
Q4. O que faz spring.jpa.hibernate.ddl-auto: validate?
- A. Cria as tabelas que faltam
- B. Apaga e recria o schema a cada inicialização
- C. Verifica que as entidades batem com as tabelas existentes e falha se não baterem, sem alterar nada
- D. Valida o JSON das requisições recebidas
Resposta
C — Verificar, nunca alterar.
O schema tem um único dono: o Flyway. O Hibernate só verifica que o mapeamento está consistente, o que pega uma migration faltando na inicialização em vez de na primeira consulta em produção.
Q5. Um cliente chama GET /catalog/events?size=5000. O que o serviço responde, e por que isso é uma decisão de projeto?
- A. 200 com 5.000 eventos — o cliente pediu
- B. 400, porque
sizetem@Max(50): toda coleção deve ser limitada, ou uma requisição pode carregar a tabela inteira - C. 404, porque a página 5.000 não existe
- D. 500, porque o Hibernate não carrega mais de 50 linhas
Resposta
B — 400: coleções limitadas.
Um tamanho de página sem limite é um vetor de negação de serviço que você mesmo entrega. O limite faz parte do contrato, imposto na borda do serviço, antes de qualquer consulta rodar.
Q6. No smoke test, a listagem (?city=) é ~5–10× mais lenta que o detalhe (/{id}). Qual é o motivo principal?
- A. A serialização em JSON de 20 itens
- B. A listagem junta duas tabelas, filtra, ordena e conta milhares de linhas sem índice; o detalhe é uma busca por chave primária
- C. A listagem usa HTTP/1.0
- D. O nome da cidade tem acento
Resposta
B — Trabalho feito no banco.
O detalhe toca uma linha pelo índice da chave primária. A listagem varre os eventos de uma cidade inteira duas vezes (página + count(*)) e os ordena. O lab 6 mostra o EXPLAIN e resolve com um índice; o lab 5 esconde o custo com um cache.
Q7. Por que o container do catalog tem deploy.resources.limits.cpus: "1.0"?
- A. O Spring Boot não consegue usar mais de um núcleo
- B. Para fazer de cada réplica um "servidor" pequeno e de tamanho fixo, de modo que as medições sejam comparáveis e acrescentar réplicas (lab 3) tenha um efeito visível
- C. O Docker exige limite de CPU para imagens Java
- D. Para deixar o build mais rápido
Resposta
B — Uma unidade fixa de capacidade.
Sem limite, um container pode usar todos os núcleos do seu notebook, e escalar horizontalmente não mostraria ganho. Servidores e pods reais também têm tamanhos fixos; planejamento de capacidade é "quantas unidades deste tamanho?".
Q8. Por que usar um Dockerfile multi-stage?
- A. É o único jeito de gerar imagens Java
- B. A imagem final tem só o JRE e o jar: menor, mais rápida de baixar e sem ferramentas de build que aumentam a superfície de ataque
- C. Imagens multi-stage iniciam mais rápido porque pulam o JIT
- D. Faz a imagem rodar como root
Resposta
B — Imagem de execução pequena, ferramentas de build ficam para trás.
O estágio de build (JDK + Maven, centenas de MB) é descartado. Imagens menores significam deploys e autoescala (lab 10) mais rápidos, e menos pacotes para corrigir.
Q9. O catalog inicia antes de o PostgreSQL estar pronto e quebra no Flyway. Qual configuração do Compose resolve?
- A.
restart: alwaysnodb - B.
depends_on: db: condition: service_healthycom umhealthcheck(pg_isready) nodb - C.
links: - db - D. Aumentar o limite de memória do
catalog
Resposta
B — Esperar a saúde, não o início.
Um depends_on simples só espera o container iniciar; o PostgreSQL precisa de mais alguns segundos para aceitar conexões. O healthcheck transforma "iniciado" em "pronto". No Kubernetes (lab 10) a mesma ideia vira readiness probes.
Q10. O smoke test mostra p50 = 5 ms e p99 = 40 ms para o detalhe com um usuário. Qual explicação é a mais plausível?
- A. A rede entre o k6 e o container perde pacotes
- B. Pausas ocasionais que não dependem da carga: compilação JIT, coleta de lixo, abertura de conexões do pool, páginas frias do banco
- C. O banco está sobrecarregado
- D. O k6 mede o p99 de forma errada
Resposta
B — Latência de cauda existe mesmo sem carga.
Com um usuário não há fila, então a cauda vem do próprio runtime. Por isso testes de carga têm um período de aquecimento e por isso você sempre olha percentis, não só a mediana.