Saltar al contenido
InterviewCrusher
Entrevista por cargo

Perguntas de entrevista para programador / engenheiro de software e como respondê-las

Uma entrevista para programador raramente é um exame de definições. Quem te entrevista quer ver como pensas quando algo se parte, como decides entre dois designs imperfeitos e como trabalhas com código que não foste tu a escrever. Costuma haver uma parte técnica ou de coding (ao vivo ou um teste prévio), mas a maior parte do tempo passa-se a explicares as tuas decisões: porque escolheste aquela estrutura de dados, porque meteste uma fila em vez de chamar diretamente, porque é que aquele bug demorou três dias.

O que separa quem passa de quem não passa raramente é o conhecimento, mas sim a capacidade de raciocinar em voz alta sem bloquear. Muita gente sabe resolver o problema, mas cala-se enquanto pensa, ou despeja a solução sem explicar o caminho. Aqui tens perguntas específicas do cargo com um guia para orientar cada uma. Lê-as, mas não fiques por aí: a resposta só conta se a souberes dizer sob pressão.

O que avaliam nesta entrevista

  • Resolução de problemas e raciocínio técnico em voz alta
  • Debugging sistemático sob incerteza
  • Design e arquitetura: gerir trade-offs sem resposta única
  • Qualidade de código e colaboração em code reviews
  • Comunicação: explicar decisões técnicas com clareza
  • Gestão de código herdado e dívida técnica

Perguntas frequentes para programador / engenheiro de software

  1. 01

    Conta-me o bug mais difícil que já depuraste. Como o encontraste e porque é que te deu tanto trabalho?

    Não descrevas o bug, descreve o teu método: como o reproduziste, que hipóteses descartaste e como isolaste a causa. O que avaliam é o teu processo de debugging, não a anedota.

    Exemplo de resposta
    «Tínhamos um erro de pagamentos que só aparecia em produção, uma em cada mil transações. Primeiro consegui reproduzi-lo: capturei os payloads reais dos casos falhados e montei um teste que os reproduzia em local. Descartei o gateway de pagamento comparando os seus logs com os nossos, e descartei dados corrompidos validando o esquema. No fim era uma condição de corrida: dois webhooks do mesmo pagamento chegavam com milissegundos de diferença e o segundo sobrepunha-se ao primeiro. Deu-me uma semana de trabalho porque o log agregado escondia a ordem real de chegada. Resolvi-o com um lock por id de pagamento e acrescentei um teste de concorrência para que não voltasse a acontecer.»
  2. 02

    Estás numa code review e um colega assinala que a tua solução não escala. O que fazes?

    Mostra que separas o ego do código. Conta como pedes o caso concreto que quebra a tua abordagem, que perguntas fazes para perceber o limite real e quando aceitas por oposição a quando defendes com dados.

    Exemplo de resposta
    «A primeira coisa é pedir-lhe o caso concreto: a partir de que volume é que a minha abordagem deixa de funcionar? Se me disser que com 10 000 elementos por pedido o meu ciclo dispara, verifico-o com dados reais de produção. Aconteceu-nos com uma listagem que eu tinha resolvido em memória: ele tinha razão para os 5% de contas grandes, por isso paginei a consulta. Mas se o caso que me apresenta não existe nem nos nossos dados nem no roadmap, digo-o com números: preferimos o simples hoje e deixamos o limite anotado. Aceito quando há evidência, defendo quando a evidência está do meu lado, e nunca faço disto algo pessoal.»
  3. 03

    Desenha-me em traços gerais um sistema que encurte URLs (ou um feed, um carrinho...). Por onde começas?

    Começa pelas perguntas, não pela solução: volume, leituras vs escritas, latência aceitável. Raciocina os trade-offs em voz alta (consistência vs disponibilidade, onde colocar cache) em vez de despejar uma arquitetura fechada de cor.

    Exemplo de resposta
    «Antes de desenhar seja o que for, faria três perguntas: quantas URLs novas por dia e quantos redirecionamentos?, podem expirar?, interessa a analítica de cliques? Suponhamos mil escritas e um milhão de leituras diárias: é um sistema de leituras, por isso otimizo aí. Geraria códigos de 7 caracteres em base 62 a partir de um contador com blocos pré-reservados por instância, para evitar colisões sem ter de coordenar cada pedido. Guardaria o mapeamento numa base chave-valor e poria uma cache à frente para os 20% de URLs que levam 80% do tráfego. O redirecionamento pode ser eventualmente consistente: se uma ligação demorar um segundo a propagar-se, não faz mal; isso permite-me replicar sem bloquear escritas.»
  4. 04

    Porque escolheste [a tua linguagem/framework principal] no teu último projeto e quando é que teria sido má ideia?

    Fala de critérios reais: ecossistema, desempenho, a equipa que o vai manter. Reconheceres quando NÃO era a opção certa vale mais do que defendê-lo como se fosse perfeito para tudo.

    Exemplo de resposta
    «No meu último projeto escolhi TypeScript com Node porque a equipa já dominava JavaScript, o produto era uma API com muita integração de terceiros e a tipagem poupava-nos os erros parvos de contratos entre serviços. Não foi uma decisão da moda: pesei que contratar perfis fosse fácil e que o ecossistema tivesse bibliotecas maduras para o que precisávamos. Quando é que teria sido má ideia? Se o núcleo fosse cálculo intensivo de CPU, processamento de imagem ou algo com requisitos rígidos de memória: aí o Node afoga-se e eu teria ido para Go ou para Python com extensões nativas. Aliás, um job de geração de PDFs acabámos por passá-lo para um worker separado porque bloqueava o event loop.»
  5. 05

    Tens de adicionar uma feature a uma parte do código que não percebes e que ninguém documentou. Como procedes?

    Mostra estratégia perante o código herdado: ler os testes, traçar as entradas e saídas, fazer alterações pequenas e verificáveis. Menciona o que te recusarias a tocar sem rede de segurança.

    Exemplo de resposta
    «Primeiro leio os testes, se existirem: são a única documentação que não mente. Se não existirem, traço o fluxo com um caso real: ponho logs ou um debugger na entrada e sigo os dados até à saída, e com isso desenho um mapa de o que mexe com o quê. Antes de adicionar a minha feature, escrevo dois ou três testes de caracterização que fixem o comportamento atual, mesmo que me pareça estranho: esse comportamento pode ser um contrato que alguém espera. Depois faço a alteração mais pequena possível e verifico que os testes continuam verdes. O que não faria era refatorizar ao mesmo tempo que adiciono a feature, nem mexer sem rede em algo que envolva dinheiro ou dados de utilizadores: aí primeiro testes, depois alterações.»
  6. 06

    Fala-me de uma vez em que tomaste um atalho técnico (dívida técnica) de propósito. Como o justificaste?

    Deixa claro que foi uma decisão consciente com custo conhecido, não um descuido. Explica o que ganhaste (prazo, validar uma hipótese), como o deixaste documentado e que plano havia para o pagar.

    Exemplo de resposta
    «Para validar uma integração com um cliente grande, fiz hardcode da configuração dele em vez de construir o sistema de configuração por cliente que era o correto. Decidi-o com o meu responsável presente: montar o genérico eram três semanas e o cliente decidia numa. Deixei o atalho sinalizado: um comentário com o porquê, um ticket no backlog com a solução real estimada, e um alerta caso outro cliente chegasse àquele código. O cliente assinou e, no trimestre seguinte, pagámos a dívida com o sistema genérico. Para mim a diferença entre dívida boa e má é essa: a boa tem data, dono e um custo que alguém aceitou em voz alta; a má é a que se descobre seis meses depois por surpresa.»
  7. 07

    Diferença entre duas coisas que parecem semelhantes no teu stack (p. ex. lista vs dicionário, SQL vs NoSQL, síncrono vs assíncrono): quando usas cada uma?

    Responde com o quando, não com a definição de manual. Ancora cada opção a um caso de uso e ao custo que assumes (memória, latência, complexidade). Se puderes, refere uma vez em que escolheste mal e o mudaste.

    Exemplo de resposta
    «SQL contra NoSQL, por exemplo: não é uma guerra de religiões, é uma pergunta sobre os teus dados. Se têm relações que importam (encomendas, clientes, faturas) e precisas de transações, SQL, porque as garantias dá-tas a base de dados e não as tens de reinventar no código. NoSQL uso-o quando o esquema é volátil ou o volume de leituras simples é enorme: sessões, catálogos desnormalizados, eventos. O custo que assumes com NoSQL é que as perguntas que não previste tornam-se caras. Aconteceu-me: montámos analítica sobre uma base de documentos e ao fim de seis meses cada relatório novo era um sofrimento; migrámos essa parte para Postgres e as consultas passaram de horas de trabalho a um JOIN.»
  8. 08

    O teu código passa em local mas falha em produção. O que verificas primeiro?

    Enumera os suspeitos por probabilidade: variáveis de ambiente, versões de dependências, dados reais vs de teste, concorrência, fuso horário. O importante é a ordem do teu raciocínio, não acertar na causa exata.

    Exemplo de resposta
    «Vou por ordem de probabilidade. Primeiro, configuração: variáveis de ambiente que faltam ou que apontam para outro sítio, é a causa mais comum e a mais barata de verificar. Segundo, dados: em local testo com dados limpos e produção tem os casos raros (nulos, acentos, registos de 2015). Terceiro, versões: o lockfile foi respeitado no deploy?, a versão do Node ou da base de dados é a mesma? Quarto, tudo o que em local não existe: concorrência real, latência de rede, permissões, fuso horário do servidor. E enquanto verifico, olho para os logs do erro real em produção em vez de supor: metade das vezes o stack trace já te diz em qual dessas quatro famílias estás.»

Muitas destas perguntas são do tipo «conta-me uma vez em que…». Para estruturar essas respostas com uma história clara, usa o método STAR.

Dicas para te destacares

  • Pensa em voz alta durante o coding. O silêncio penaliza-te mais do que um erro: quem te entrevista precisa de ver o teu raciocínio, não só o resultado.
  • Antes de programar, repete o problema e pergunta pelos casos-limite. Atirares-te a escrever sem esclarecer requisitos é o sinal de alarme número um.
  • Quando defenderes uma decisão técnica, nomeia o trade-off que aceitaste. «Escolhi X mesmo sabendo que Y» soa a sénior; «X é melhor» soa a júnior.
  • Leva dois ou três projetos preparados para contar em detalhe: que problema resolviam, a tua decisão mais difícil e o que farias de diferente. É o material de onde saem metade das perguntas de seguimento.

Pratica uma entrevista para programador / engenheiro de software

Cola o teu CV e a oferta e fala com um recrutador de IA que adapta as perguntas ao teu cargo. Feedback honesto por competências, sem cartão.

Perguntas para outros cargos