voltar aos artigosadvanced topics
$cd~/artigos/clean-code-javascript-codigo-limpo
Advanced Topics
série 33 Conceitos JS·parte 38 de 38

Clean Code: Escrevendo Código que Outros (e Você no Futuro) Vão Amar Ler

22 minVanderlei José Alamino

"Qualquer tolo consegue escrever código que um computador entende. Bons programadores escrevem código que humanos entendem." — Martin Fowler

Neste artigo final da série 33 Conceitos JS — projeto open source criado por Leonardo Maldonado — você domina os princípios que transformam código bom em código extraordinário: nomes auto-documentados, funções pequenas, DRY consciente, funções previsíveis, guard clauses, comentários que explicam o porquê, SOLID aplicado ao JavaScript e código testável.

Pré-requisitos: Pure Functions, Modern JS Syntax, Error Handling e Design Patterns.

clean-code-javascript-codigo-limpo.meta.jsonjson

// metadados do artigo

{
  "tag": "advanced topics",
  "readTime": "22 min",
  "author": "Vanderlei José Alamino",
  "source": "33jsconcepts.com",
  "series": "33 Conceitos JS",
  "part": {
    "current": 38,
    "total": 38
  }
}
abrir fonte original
clean-code-javascript-codigo-limpo.mdmarkdown

Fonte de referência

Conteúdo adaptado a partir do guia original em inglês.

33jsconcepts.com
01

seção

Analogia: Código como um Jornal

Leia um jornal: o título entrega a essência, o primeiro parágrafo detalha, o restante traz suporte. Seu código deve funcionar igual — funções de alto nível no topo, implementação abaixo.

snippetJavaScript
// MANCHETE: o que este módulo faz?export function processUserOrder(userId, orderId) {  const user = getUser(userId);  const order = getOrder(orderId);  validateOrder(user, order);  return chargeAndShip(user, order);} // DETALHES: como ele faz?function getUser(userId) { /* ... */ }function getOrder(orderId) { /* ... */ }function validateOrder(user, order) { /* ... */ }function chargeAndShip(user, order) { /* ... */ }

Leia de cima para baixo. O o quê vem antes do como — nunca enterre a intenção principal no fundo de uma função de 200 linhas.

02

seção

Nomenclatura Significativa

Nomes estão em todo lugar: variáveis, funções, classes, arquivos. Bons nomes tornam comentários desnecessários.

Pronunciáveis e buscáveis:

snippetJavaScript
// ❌ O que isso significa?const yyyymmdstr = moment().format('YYYY/MM/DD'); // ✅ Cristalinoconst currentDate = moment().format('YYYY/MM/DD');

Mesma palavra para o mesmo conceito — se você busca usuários com getUser(), não tenha também fetchClient() e retrieveCustomer().

Evite mapeamento mental — variáveis de uma letra forçam o leitor a lembrar o que l significa cinquenta linhas depois. Prefira location.

Sem contexto redundante — se a classe se chama Car, use make, model, color — não carMake, carModel.

03

seção

Funções Devem Fazer Uma Única Coisa

A regra mais importante do código limpo — SRP (Single Responsibility Principle). Como Robert C. Martin afirma em Clean Code: "uma função deve fazer uma coisa, fazê-la bem e fazê-la apenas."

snippetJavaScript
// ❌ Faz coisas demaisfunction emailClients(clients) {  clients.forEach(client => {    const record = database.lookup(client);    if (record.isActive()) email(client);  });} // ✅ Cada função, um trabalhofunction emailActiveClients(clients) {  clients.filter(isActiveClient).forEach(email);}function isActiveClient(client) {  return database.lookup(client).isActive();}

Limite parâmetros — dois ou menos é o ideal. Para mais, use objeto com destructuring:

snippetJavaScript
createMenu({ title: 'Settings', body: 'User preferences', cancellable: true });

Não use flags booleanas — sinal de que a função faz mais de uma coisa. Divida em createFile() e createTempFile().

04

seção

Evite Números e Strings Mágicas

Literais inexplicáveis tornam o código difícil de entender e de alterar.

snippetJavaScript
// ❌ O que é 86400000? Por que 18?setTimeout(blastOff, 86400000);if (user.age > 18) allowAccess(); // ✅ Constantes nomeadasconst MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000;const MINIMUM_LEGAL_AGE = 18;const STATUS = { ACTIVE: 1, INACTIVE: 0 }; setTimeout(blastOff, MILLISECONDS_PER_DAY);if (user.age > MINIMUM_LEGAL_AGE) allowAccess();

Dica: a regra no-magic-numbers do ESLint sinaliza números mágicos automaticamente.

05

seção

DRY: Don't Repeat Yourself

Código duplicado significa múltiplos lugares para atualizar quando a lógica muda. Andy Hunt e Dave Thomas em The Pragmatic Programmer: "cada fragmento de conhecimento deve ter uma única representação autoritária."

snippetJavaScript
// ✅ Unificado com tratamento específicofunction showEmployeeList(employees) {  employees.forEach(employee => {    const baseData = {      salary: employee.calculateSalary(),      experience: employee.getExperience(),    };    const extraData = employee.type === 'developer'      ? { githubLink: employee.getGithubLink() }      : { portfolio: employee.getPortfolio() };    render({ ...baseData, ...extraData });  });}

Cuidado: uma abstração ruim é pior que duplicação. Só abstraia quando você vê um padrão claro.

06

seção

Evite Efeitos Colaterais

Efeito colateral = fazer algo além de receber inputs e retornar outputs: mutar global, escrever arquivo, mutar parâmetro de entrada.

snippetJavaScript
// ❌ Muta o array originalfunction addItemToCart(cart, item) {  cart.push({ item, date: Date.now() });} // ✅ Retorna novo arrayfunction addItemToCart(cart, item) {  return [...cart, { item, date: Date.now() }];}

Funções puras são previsíveis e fáceis de testar. Aprofunde em Pure Functions.

07

seção

Early Returns e Guard Clauses

Código profundamente aninhado é difícil de acompanhar. Trate casos de borda primeiro:

snippetJavaScript
// ❌ Aninhadofunction getPayAmount(employee) {  let result;  if (employee.isSeparated) {    result = { amount: 0, reason: 'separated' };  } else if (employee.isRetired) {    result = { amount: 0, reason: 'retired' };  } else {    result = { amount: calculateSalary(employee), reason: 'employed' };  }  return result;} // ✅ Guard clausesfunction getPayAmount(employee) {  if (employee.isSeparated) return { amount: 0, reason: 'separated' };  if (employee.isRetired) return { amount: 0, reason: 'retired' };  return { amount: calculateSalary(employee), reason: 'employed' };}

Em loops, use continue para pular iterações em vez de aninhar if dentro de if.

08

seção

Comentários: O Ópio do Código Ruim

Bom código se documenta sozinho. Comentários explicam por quê, não o quê. Se precisa de comentário para explicar o que o código faz, reescreva o código.

Não afirme o óbvio — // Loop por cada caractere não acrescenta nada.

Delete código morto — código comentado é lixo. O git lembra.

Não use comentários como controle de versão — // 2016-12-20: Removed monads pertence ao histórico do git, não ao arquivo.

09

seção

SOLID no JavaScript

S — Single Responsibility: UserSettings não deve verificar credenciais e alterar configurações — separe UserAuth de UserSettings.

O — Open/Closed: estenda adicionando classes (Circle, Rectangle com getArea()), não modificando if/else gigantes.

L — Liskov Substitution: Square extends Rectangle quebra quando setWidth/setHeight têm semânticas diferentes — prefira classes separadas.

I — Interface Segregation: torne features opcionais (animationModule?) em vez de exigir tudo no construtor.

D — Dependency Inversion: injete dependências — new InventoryRequester() dentro da classe acopla; passe requester no construtor.

No monorepo Alamino, MVC + SOLID guiam cada app — detalhes em Design Patterns e na documentação do projeto.

10

seção

Escrevendo Código Testável

Funções que fazem uma coisa sem efeitos colaterais são fáceis de testar. Se é difícil de testar, provavelmente faz coisas demais ou tem dependências ocultas.

snippetJavaScript
// ❌ Difícil — mockar sendEmail, logActivity, updateDatabasefunction processUser(user) {  if (user.email.includes('@')) {    sendEmail(user.email);    logActivity(user);    updateDatabase(user);  }} // ✅ Trivial de testarfunction isValidEmail(email) {  return email.includes('@');}

Regra: uma função, uma responsabilidade, sem side effects = teste trivial.

11

seção

Teste Seu Conhecimento

12

seção

Fim da Série — Advanced Topics Completa

Parabéns! Você completou o nono e último conceito da trilha Advanced Topics — e toda a série 33 Conceitos JS publicada neste portfólio.

Conecte clean code com Error Handling (erros legíveis), Modern JS Syntax (features que simplificam leitura) e Design Patterns (soluções reutilizáveis).

→ Revise o catálogo completo em 33 Conceitos JS — trilhas, busca e filtros interativos.

→ E agora?

A jornada continua no Beyond 33 — 29 conceitos avançados em 9 categorias. Leia a visão geral e explore a trilha em Beyond 33. Os artigos individuais serão publicados gradualmente.

→ Referência adaptada: clean-code-javascript (Ryan McDermott) — 94k+ estrelas no GitHub.

Fonte de referência: 33jsconcepts.com/concepts/clean-code ⬀

$ summary --quick

Resumo rápido

  • Nomes importam — pronunciáveis, buscáveis, vocabulário consistente
  • Uma função, uma coisa — SRP é a regra mais importante
  • Poucos parâmetros — destructuring de objeto auto-documenta
  • Sem flags booleanas — divida em funções focadas
  • Constantes nomeadas — elimine números mágicos
  • DRY consciente — abstração ruim pior que duplicação
  • Sem efeitos colaterais — prefira funções puras
  • Early returns — guard clauses achatam aninhamento
  • Comentários explicam por quê — delete código morto
  • SOLID + testabilidade — código limpo e testável andam juntos

Créditos da série

Este artigo encerra a série de estudos inspirada no projeto 33 Conceitos JS, criado por Leonardo Maldonado. Todo o conteúdo original está disponível em 33jsconcepts.com.