Além da Teoria: o Clean Code que se escreve com propósito
Um olhar prático sobre código limpo em JavaScript, React e Node.js
🚀 Introdução
Se no artigo anterior compartilhei aprendizados sobre o porquê de escrever código limpo, agora quero falar sobre o como.
Após o curso "Introdução a Clean Code" aqui da DIO, mergulhei mais fundo nesse tema com o conteúdo da Rocketseat, ministrado pelo Diego Fernandes, e percebi que Clean Code é muito mais do que um conjunto de boas práticas, é uma atitude diante do código e das pessoas que o leem.
> 💬 Porque código limpo não é apenas sobre sintaxe: é sobre empatia, clareza e propósito.
🧩 1. Clean Code é sobre contexto, não sobre perfeccionismo
Uma das primeiras lições reforçadas pelo Diego é que Clean Code não tem nada a ver com Clean Architecture, DDD ou SOLID, e que a maioria dos projetos reais não segue arquiteturas complexas, mas ainda assim podem ter código limpo.
Clean Code é sobre contexto: entender o propósito do código e o impacto das decisões de quem o escreve.
Ele se apoia em três pilares essenciais:
- Legibilidade: o código precisa contar sua própria história
- Manutenibilidade: deve poder evoluir sem dores de cabeça
- Previsibilidade: o comportamento precisa ser claro e confiável
🧠 2. Nomes que contam histórias (JavaScript)
No módulo de JavaScript, uma lição simples, mas poderosa:
> "Nomes contam histórias."
Escrever variáveis como data, obj ou res é o mesmo que criar capítulos sem título em um livro. Um bom nome revela o propósito, e não apenas o tipo do dado.
// ❌ Código confuso
function calc(p, d) {
return p - (p * d / 100);
}
// ✅ Código claro
function calcularDesconto(preco, percentualDesconto) {
return preco - (preco * percentualDesconto / 100);
}
O código limpo não exige tradução mental. Ele conversa com o leitor.
📚 3. Os 9 princípios práticos do Clean Code em JavaScript
Durante o curso, realizei 9 desafios práticos que consolidaram princípios fundamentais:
🔹 Desafio 1: Nomenclatura de variáveis
Princípio: Evite diminutivos e nomes genéricos.
// ❌ Código confuso
const filtered = users.filter(u => u.name.startsWith('D'));
// ✅ Código claro
const usersStartingWithLetterD = users.filter(user =>
user.name.startsWith('D')
);
Lição: Clareza > brevidade. Nomes longos e descritivos são melhores que abreviações crípticas.
🔹 Desafio 2: Booleanos semânticos
Princípio: Use prefixos que revelem o tipo boolean: is, has, can, should.
// ❌ Confuso
if (!ticket) throw new Error("Sem bilhete");
// ✅ Claro
const hasTicket = user?.ticket != null; // null ou undefined => false
if (!hasTicket) throw new Error('Usuário não possui bilhete');
Lição: Nomes booleanos devem responder perguntas diretas: "Is it active?" → isActive
🔹 Desafio 3: Causa vs. Efeito
Princípio: Nomeie pela causa, não pelo efeito.
// ❌ Efeito
const isLoadingUserInformation = true;
// ✅ Causa
const isUserInformationLoading = true;
Lição: O nome deve refletir o que causa o estado, não o que acontece como consequência.
🔹 Desafio 4: Código em inglês
Princípio: Escreva 100% do código em inglês.
// ❌ Mistura de idiomas
const listaProdutos = [
{ title: "Macarrão", preco: "R$ 25,00" },
{ title: "Hamburguer", preco: "R$ 30,00" }
];
// ✅ Código uniforme
const productList = [
{ title: "Macarrão", price: "R$ 25.00" },
{ title: "Hamburguer", price: "R$ 30.00" }
];
Lição: Código em inglês é universal, acessível para ferramentas e outros desenvolvedores.
🔹 Desafio 5: Regras em condicionais
Princípio: Extraia lógica condicional para variáveis descritivas.
// ❌ Confuso
if (studentGrade < 7 || studentAbsences > 100) {
return { error: "Reprovado" };
}
// ✅ Claro
const hasFailedGrade = studentGrade < necessaryGradeToBeApproved;
const hasExcessiveAbsences = studentAbsences > numberOfAbsencesToFailSchool;
if (hasFailedGrade || hasExcessiveAbsences) {
return { error: "Estudante Reprovado" };
}
Lição: Condicionais legíveis = código autodocumentado.
🔹 Desafio 6: Parâmetros e desestruturação
Princípio: Use objetos para múltiplos parâmetros; evite ordem fixa.
// ❌ Ordem rígida
function updateUserRoute(body, params) {
updateUserController(body.name, body.email, body.password, params.id);
}
function updateUserController(name, email, password, id) {
userRepository.update({ name, email, password, id });
}
// ✅ Desestruturação flexível
function updateUserRoute(body, params) {
updateUserController({
name: body.name,
email: body.email,
password: body.password,
id: params.id
});
}
function updateUserController({ name, email, password, id }) {
userRepository.update({ name, email, password, id });
}
Lição: Desestruturação melhora legibilidade e facilita refatoração.
🔹 Desafio 7: Números mágicos
Princípio: Substitua números literais por constantes nomeadas.
// ❌ Números mágicos
function lookForUpdates() {
// Código
}
setInterval(lookForUpdates, 60 * 30 * 1000);
function calculateDiscount(priceInCents, discountAmountInPercentage) {
// Código
}
// ✅ Constantes descritivas
const INTERVAL_30_MINUTES = 60 * 30 * 1000;
function lookForUpdates() {
// Código
}
setInterval(lookForUpdates, INTERVAL_30_MINUTES);
function calculateDiscount(priceInCents, discountAmountInPercentage) {
// Código
}
Lição: Números têm significado. Dê-lhes nomes.
🔹 Desafio 8: Comentários vs. Documentação
Princípio: Código claro não precisa de comentários; use JSDoc para APIs públicas.
// ❌ Comentários explicando código confuso
async function registerUser(userInfo) {
// Verifica se avatar é válido
const isAvatarInvalid = userInfo.avatar;
if (isAvatarInvalid) {
return { error: 'avatar is required' }
}
// Verifica se nome é válido
const isNameInvalid = userInfo.name;
if (isNameInvalid) {
return { error: 'name is required' }
}
// Verifica se email já está em uso
const isEmailInUse = getUserByEmail(userInfo.email);
if (isEmailInUse) {
return { error: 'email already used' }
}
// Essa função foi copiada de um tutorial no YouTube
// Link: https://github.com/rocketseat-education/example-repository/issues/1
const convertedAvatar = convertImageToJPG(userInfo.avatar);
const createdUser = await createUser({
email: userInfo.email,
name: userInfo.name,
avatar: convertedAvatar
});
return { createdUser }
}
// ✅ Código autodocumentado + JSDoc
/**
* Registers a new user in the system
* @param {Object} userInfo - User data
* @param {string} userInfo.email - User email
* @param {string} userInfo.name - User name
* @param {string} userInfo.avatar - User avatar URL
* @returns {Promise<Object>} Created user or error
*/
async function registerUser(userInfo) {
const isAvatarInvalid = !userInfo.avatar;
if (isAvatarInvalid) {
return { error: 'avatar is required' }
}
const isNameInvalid = !userInfo.name;
if (isNameInvalid) {
return { error: 'name is required' }
}
const isEmailInUse = getUserByEmail(userInfo.email);
if (isEmailInUse) {
return { error: 'email already used' }
}
const convertedAvatar = convertImageToJPG(userInfo.avatar);
const createdUser = await createUser({
email: userInfo.email,
name: userInfo.name,
avatar: convertedAvatar
});
return { createdUser }
}
Lição: Comentários explicam porquê. Código explica o quê.
🔹 Desafio 9: Syntatic Sugars
Princípio: Evite atalhos obscuros; prefira clareza.
// ❌ Syntatic sugar obscuro
function getFirstFiveRatings(ratings) {
const ratingsBool = Boolean(ratings);
if (ratingsBool) {
const firstFiveRatings = getFirstFiveRatings + ratings;
if (!firstFiveRatings) return { error: 'there must be at least 5 ratings' };
let ratingsSum = 0;
for (const rating of firstFiveRatings) {
ratingsSum += Number(rating);
}
return { ratingsSum, created_at: Date.now() };
}
return { error: 'ratings is required' };
}
// ✅ Código explícito
function sumFirstFiveRatings(ratings) {
const ratingsBool = Boolean(ratings);
if (!ratingsBool) {
return { error: 'ratings is required' };
}
const firstFiveRatings = ratings.slice(0, 5);
if (firstFiveRatings.length < 5) {
return { error: 'there must be at least 5 ratings' };
}
let ratingsSum = 0;
for (const rating of firstFiveRatings) {
ratingsSum += Number(rating);
}
return { ratingsSum, created_at: Date.now() };
}
Lição: Código elegante não é código críptico. Escolha clareza sobre "esperteza".
⚛️ 4. React: separando o essencial do acessório
Em aplicações React, o Clean Code se mostra na capacidade de separar o essencial do acessório. Nem todo componente precisa ser extraído; componentizar tudo não é sinônimo de organização.
A lição é clara: isolar responsabilidades sem fragmentar o raciocínio.
> 💡 "A pior parte de um código grande não é o HTML, é o JavaScript confuso dentro dele."
A limpeza do React começa com uma pergunta: "O que esse componente precisa fazer de fato?"
🎨 Pattern de Composição vs. Configuração
Ao invés de criar um componente inflado:
// ❌ Pattern de Configuração (inflexível)
<Input
label="Nome completo"
error="Digite seu nome corretamente"
icon={<UserIcon />}
iconPosition="left"
labelProps={{ htmlFor: "name", className: "label-custom" }}
/>
Use composição para flexibilidade total:
// ✅ Pattern de Composição (flexível)
<Input.Root>
<Input.Label htmlFor="name" className="label-custom">
Nome completo
</Input.Label>
<Input.Icon>
<UserIcon />
</Input.Icon>
<Input.Field id="name" />
<Input.ErrorMessage>
Digite seu nome corretamente
</Input.ErrorMessage>
</Input.Root>
Vantagens do pattern de composição:
- Controle total sobre posicionamento de elementos
- Acesso direto a propriedades nativas do HTML
- Sem necessidade de criar props intermediárias
- Extensibilidade natural
🧹 Condicionais fora do render
Mantenha a lógica fora do JSX:
// ❌ Lógica no render
return (
<div>
{todos.length === 0 && <p>Nenhum todo cadastrado</p>}
</div>
);
// ✅ Lógica separada
const isTodoListEmpty = todos.length === 0;
return (
<div>
{isTodoListEmpty && <p>Nenhum todo cadastrado</p>}
</div>
);
🖥️ 5. Backend: simplicidade é maturidade
No backend, a maturidade está em evitar complexidade desnecessária. Como o Diego enfatiza: Clean Code ≠ Clean Architecture.
Você pode escrever código limpo mesmo em aplicações simples, o segredo está em clareza e testabilidade.
> "Se é fácil de testar, provavelmente é fácil de entender."
A simplicidade é um traço de desenvolvedores maduros: usar o suficiente para resolver o problema, não o máximo que a linguagem permite.
🎯 Testabilidade como métrica
Ter testes automatizados é um dos principais sinais de que seu código é limpo. Se você consegue testar facilmente, seu código provavelmente está bem estruturado.
💭 6. O código que se escreve com propósito
Essa jornada pela Rocketseat reforçou algo que já havia aprendido no curso da DIO: Escrever código limpo é um ato de amor.
Amor pelo futuro do projeto, pelos colegas de equipe e pelo seu "eu" de amanhã.
Se no primeiro artigo eu falava sobre conceitos, agora falo sobre consciência.
> "Bons programadores escrevem código que seres humanos podem entender."
> — Martin Fowler
🎓 Conclusão
Clean Code não é uma lista de regras a seguir cegamente. É uma mentalidade de respeito:
- Respeito por quem vai ler seu código
- Respeito pelo projeto que vai evoluir
- Respeito pelo seu tempo futuro
Os 9 desafios do curso me ensinaram que transformar "código que funciona" em "código que faz sentido" não é perfumaria, é profissionalismo.
🔗 Referências
- Artigo anterior: Clean Code - DIO
- Clean Code - Robert C. Martin




