Pular para o conteudo principal

Escrever Código que Gente Consegue Entender

Um jeito simples de escolher nomes, estrutura e nivel de abstração sem transformar o código em um quebra-cabeca caro de manter.

Andrews Ribeiro

Andrews Ribeiro

Founder & Engineer

O problema

Existe uma confusão comum na programação: achar que código bom é código curto, esperto ou cheio de abstrações.

Às vezes ele funciona, passa nos testes e até parece elegante. O problema aparece depois, quando alguém precisa mudar aquele trecho.

Se para entender uma regra simples a pessoa precisa decifrar abreviações, abrir vários arquivos e adivinhar contexto escondido, esse código ficou caro de manter.

E esse custo quase nunca aparece no dia do commit.

Ele aparece depois:

  • quando chega um bug em produção
  • quando outra pessoa assume o módulo
  • quando você mesmo volta tres meses depois
  • quando a regra muda sob pressao

Código difícil de ler cobra juros.

Modelo mental

Você escreve código para a máquina executar, mas também para pessoas lerem. Na prática, legibilidade é isso: fazer a intenção ficar óbvia.

Uma pergunta útil é esta:

Uma pessoa do time consegue bater o olho nesse trecho e entender o que ele faz sem abrir cinco arquivos?

Se a resposta for não, o problema quase sempre está em nome, estrutura ou abstração demais.

Clareza não significa deixar tudo infantil.

Significa reduzir o trabalho mental desnecessario para entender a regra principal.

Quebrando o problema

Quatro decisões ajudam muito aqui:

  1. Use nomes que mostram intenção: Um bom nome ajuda a pessoa a entender por que aquele dado ou função existe. activeUsers diz mais do que items. calculateLateFee diz mais do que process.
  2. Deixe cada função com um trabalho claro: A função não precisa ser minúscula. Ela precisa ser fácil de entender. Se ela busca usuário, valida entrada, grava log, salva no banco e manda email, provavelmente está fazendo coisas demais.
  3. Mantenha perto o que muda junto: Se duas partes do código quase sempre mudam juntas, separar isso em camadas ou arquivos demais pode piorar a leitura em vez de melhorar.
  4. Abstraia só quando isso simplifica de verdade: Repetição não é automaticamente o maior problema. Às vezes duplicar um pouco é mais barato do que obrigar a pessoa a navegar até uma abstração genérica para entender uma regra simples.

O objetivo aqui não é impressionar. É reduzir o esforço mental de quem vai ler, alterar e debugar esse código depois.

Também vale uma quinta regra simples:

  1. Deixe a regra principal visível: Se o fluxo mais importante some no meio de helpers genéricos, a leitura piora mesmo que cada pedaco isolado pareca “limpo”.

Exemplo simples

Olhe este exemplo:

// Tenta achar ativo
function p(u) {
  return u.filter(x => x.a).map(x => x.n)
}

Esse código até pode ser curto, mas obriga quem lê a traduzir tudo antes de entender a regra.

Uma versão melhor seria:

function getActiveUserNames(users: User[]) {
  return users.filter(user => user.isActive).map(user => user.name)
}

Agora a regra aparece de imediato: filtrar usuários ativos e pegar seus nomes.

Essa é a diferença entre código que apenas funciona e código que também é fácil de manter.

Outro exemplo comum:

async function h(req) {
  const u = await repo.get(req.params.id)
  if (!u) throw new Error("not found")
  if (!u.active) throw new Error("inactive")
  if (!u.email) throw new Error("missing")
  return sender.send(u.email)
}

Esse trecho pode funcionar, mas esconde a intenção.

Uma versão melhor seria:

async function sendActivationReminder(userId: string) {
  const user = await repo.get(userId)

  if (!user) throw new Error("user not found")
  if (!user.isActive) throw new Error("user inactive")
  if (!user.email) throw new Error("user without email")

  return sender.send(user.email)
}

Não ficou “mais avancado”.

Ficou mais claro.

Erros comuns

  • Abreviar variáveis sem necessidade (usr, ctx, ev).
  • Dar nomes técnicos demais e esconder a regra de negócio.
  • Quebrar um fluxo simples em várias microfunções e perder o contexto principal.
  • Criar abstrações genéricas cedo demais, como BaseManager, GenericFactory ou utilitários vagos.
  • Esconder uma regra importante dentro de uma função com nome genérico demais.
  • Quebrar fluxo simples em tanta indirecao que a leitura vira caça ao tesouro.

Como um sênior pensa

Quem já teve que manter sistema em produção aprende isso rápido: o problema raramente é só escrever o código. O problema é entender o que ele faz quando alguém precisa mexer nele com pressa.

Por isso, a pergunta muda:

Se eu ou outra pessoa precisar alterar isso sob pressão, a intenção do código vai continuar clara?

Essa pergunta costuma levar a decisões mais maduras: aceitar um pouco de repetição, manter o fluxo principal visível e evitar abstração demais antes da hora.

O que o entrevistador quer ver

Em entrevista ou revisão de código, clareza pesa bastante. Quem está avaliando geralmente percebe:

  • Se seus nomes ajudam ou atrapalham a leitura.
  • Se o fluxo principal está fácil de seguir.
  • Se você sabe quando evitar abstrações desnecessárias.
  • Se você consegue explicar o trade-off entre repetição e clareza.

Uma resposta forte costuma soar assim:

“Eu tento deixar a intenção visível no nome, no fluxo principal e no nível de abstração. Se eu preciso escolher entre um pouco de repetição clara e uma abstração genérica que esconde a regra, normalmente prefiro a clareza.”

A mensagem que código claro passa é simples: você não está escrevendo só para fazer funcionar agora. Você está escrevendo para alguém conseguir continuar o trabalho depois.

Código bom não faz o leitor se sentir burro. Ele faz a intenção parecer simples.

Resumo rápido

O que vale manter na cabeça

Checklist de pratica

Use isto ao responder

Você concluiu este artigo

Próximo artigo Como o event loop funciona Artigo anterior Como pensar em trade-offs

Continue explorando

Artigos relacionados