Por que "código limpo" não é sobre estética, mas sobre dinheiro e tempo
\n\nImagine que você abre um projeto JavaScript de outra pessoa. As variáveis se chamam a, b, x1. Uma função com 300 linhas. Aninhamento de condições como uma matriosca. Familiar? Se você já amaldiçoou um "autor" assim, então já entende para que serve o código limpo.
Código limpo em JavaScript não é uma questão de moda nem um capricho de perfeccionista. É uma ferramenta que economiza horas de depuração, simplifica a integração de novos desenvolvedores e reduz o custo de manutenção do projeto. Neste artigo, vamos abordar regras e técnicas específicas que ajudarão você a escrever código compreensível não apenas para a máquina, mas também para o ser humano.
\n\nRegra nº1: Nomes de variáveis e funções devem falar por si
\n\nO erro mais comum de iniciantes é usar nomes curtos e sem significado. Exemplo ruim:
\n\nlet d = new Date();\nlet n = d.getDay();\nlet r = n === 0 || n === 6 ? 'Fim de semana' : 'Dia útil';\nconsole.log(r);\n\n\nExemplo bom:
\n\nconst currentDate = new Date();\nconst dayOfWeek = currentDate.getDay();\nconst isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\nconst dayType = isWeekend ? 'Fim de semana' : 'Dia útil';\nconsole.log(dayType);\n\n\nA diferença é óbvia. Na segunda opção, entendemos imediatamente o que o código faz, sem comentários adicionais. Dica: use substantivos para variáveis e verbos para funções. Por exemplo: getUserData(), calculateTotal(), isValidEmail().
Como evitar "números mágicos"?
\n\nNúmeros mágicos são dígitos cujo significado não é claro sem contexto. Em vez deles, use constantes:
\n\n// Ruim\nif (user.role === 1) { ... }\n\n// Bom\nconst ROLE_ADMIN = 1;\nif (user.role === ROLE_ADMIN) { ... }\n\n\nRegra nº2: Funções devem ser pequenas e fazer apenas uma coisa
\n\nO princípio da responsabilidade única (Single Responsibility) se aplica não apenas a classes, mas também a funções. Se uma função faz três coisas, ela deve ser dividida em três funções. Exemplo ruim:
\n\nfunction processOrder(order) {\n // Validação\n if (!order.items || order.items.length === 0) {\n throw new Error('Carrinho vazio');\n }\n // Cálculo de desconto\n let discount = 0;\n if (order.total > 1000) {\n discount = 0.1;\n }\n // Envio de email\n sendEmail(order.email, 'Seu pedido foi recebido');\n return order.total - order.total * discount;\n}\n\n\nExemplo bom (refatoração):
\n\nfunction validateOrder(order) {\n if (!order.items || order.items.length === 0) {\n throw new Error('Carrinho vazio');\n }\n}\n\nfunction calculateDiscount(total) {\n return total > 1000 ? 0.1 : 0;\n}\n\nfunction notifyCustomer(email) {\n sendEmail(email, 'Seu pedido foi recebido');\n}\n\nfunction processOrder(order) {\n validateOrder(order);\n const discount = calculateDiscount(order.total);\n notifyCustomer(order.email);\n return order.total - order.total * discount;\n}\n\n\nEssa estrutura permite testar facilmente cada parte separadamente e alterar a lógica sem afetar o restante do código.
\n\nRegra nº3: Evite aninhamento profundo
\n\nQuanto mais níveis de aninhamento (if dentro de if dentro de for), mais difícil é ler o código. Use retorno antecipado (early return) e guard clauses.
\n\n// Ruim\nfunction getUserDisplayName(user) {\n if (user) {\n if (user.name) {\n if (user.name.length > 0) {\n return user.name;\n }\n }\n }\n return 'Anônimo';\n}\n\n// Bom\nfunction getUserDisplayName(user) {\n if (!user || !user.name || user.name.length === 0) {\n return 'Anônimo';\n }\n return use