Clean Code: Exerça a habilidade de escrever código simples e eficiente🔥

Hosana Barcelos - Sep 8 - - Dev Community

Hoje eu trago alguns métodos e técnicas simples de Clean Code, mas que fazem toda a diferença na hora de escrevermos nosso código.


O que veremos?

Você vai acompanhar comigo:

  • Código limpo? O que é isso?
  • Funções
  • Nomes significativos
  • Comentários
  • Formatação
  • Benefícios
  • Dicas

Código limpo? O que é isso?

Resumidamente, Clean Code é uma filosofia de desenvolvimento de software que auxilia programadores a aplicarem técnicas e métodos simples ao escrever código. Se você é programador, provavelmente já se deparou com códigos de difícil compreensão que acabaram dificultando e atrasando seu trabalho. Essas técnicas tem como objetivo facilitar a escrita, leitura e compreensão tanto de quem escreveu o código, quanto de quem possa pegá-lo no futuro.

“…escrever um código limpo é como pintar um quadro. A maioria de nós sabe quando a figura foi bem ou mal pintada.

Mas ser capaz de distinguir uma boa arte de uma ruim não significa que você saiba pintar.

Assim como distinguir um código limpo de um ruim não quer dizer que saibamos escrever um código limpo.”

Livro Clean Code — Página 6

Se preferir, você pode entender mais sobre a definição de Clean Code aqui. A seguir, veremos algumas técnicas de Clean Code na prática.

Funções

Usar responsabilidade única

É uma boa prática criar funções com responsabilidade única. Abaixo é possível visualizar um exemplo simples de uma função que faz soma, subtração e exibe o resultado, tudo em um mesmo lugar:

❌ Exemplo de código sujo:

function calculateAndDisplay(a, b, operation) {
  let result;

  if (operation === 'sum') {
    result = a + b;
  } else if (operation === 'subtract') {
    result = a - b;
  }

  DisplayResult(result);
}

function DisplayResult(result) {
  console.log('O resultado é: ' + result);
}
Enter fullscreen mode Exit fullscreen mode

Essa implementação pode ser aprimorada se mantermos uma responsabilidade única para cada função. Vamos ver como ficaria fazendo o uso de Clean Code? Se liga:

✅ Exemplo de código limpo:

function DisplayResult(result) {
  console.log('O resultado é: ' + result);
}

function sum(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

const totalSum = sum(3, 7);
DisplayResult(totalSum);

const totalSubtract = subtract(3, 7);
DisplayResult(totalSubtract);

Enter fullscreen mode Exit fullscreen mode

Se ligou? Agora vemos que separamos as responsabilidades, fizemos reutilização de código, usamos flexibilidade pois podemos facilmente adicionar novas operações criando novas funções, sem alterar o código existente, o que segue o princípio "aberto para extensão, fechado para modificação" e além disso, fazemos o bom uso de menor complexidade condicional.

A primeira versão usa condicionais (if e else if) para determinar a operação, o que adiciona um pouco mais de complexidade, né? Já na segunda versão, cada operação é isolada, e o código que chama essas operações (totalSum e totalSubtract) é simples e direto, sem necessidade de lógica condicional.

Usar técnicas para nomes de funções

VERBO + PALAVRA-CHAVE

Essa técnica é ideal para deixar nomes de funções mais claras e explicativas. Vejamos alguns exemplos:

sendEmail();
removeUser();
createNewUser();
createPdfTicket();
updateUserProfile();
Enter fullscreen mode Exit fullscreen mode

Evitar repetições

Quem trabalha com programação sabe que quando percebe-se que um código está grande demais, significa que algo dá pra ser melhorado (refatorado). Nesse caso, muitas vezes acabamos repetindo códigos que poderiam ser aproveitados em outros lugares. Vejamos um exemplo prático:

❌ Exemplo de código sujo e repetitivo:

function calculateArea(width, height) {
    if (width <= 0) {
        throw new Error('Width must be positive.');
    }
    if (height <= 0) {
        throw new Error('Height must be positive.');
    }
    return width * height;
}
Enter fullscreen mode Exit fullscreen mode

✅ Exemplo de código limpo:

function validatePositive(value, name) {
    if (value <= 0) {
        throw new Error(`${name} must be positive.`);
    }
}

function calculateArea(width, height) {
    validatePositive(width, 'width');
    validatePositive(height, 'height');
    return width * height;
}
Enter fullscreen mode Exit fullscreen mode

Observe que o valor recebido pela condicional, possui a mesma regra de validação. Com isso, não é necessário criarmos duas regras de validação para que tudo ocorra como o esperado e ainda conseguimos manter a função clara. Essa refatoração torna o código mais modular e reutilizável, eliminando a necessidade de repetir a verificação em diferentes partes do código. Massa, né?

Nomes significativos

Responder questões para definir um nome

Uma boa técnica para se pensar na hora de definir um nome para variáveis, funções e etc, é usar a habilidade de descrição. Pense:

Por que existe? O que faz? Como é usado?

Responder essas três questões pode ajudar o programador a definir um nome significativo e que esteja claro para quem pegar esse código no futuro. Por exemplo:

❌ Exemplo de nome não significativo:

const d = 25; // tempo decorrido em dias
Enter fullscreen mode Exit fullscreen mode

Sabemos que é uma boa prática evitar comentários no código. Esse exemplo acima mostra que mesmo recebendo um comentário, essa variável não possui um nome significativo. Porque esse tempo existe? O que esse tempo faz? Como esse tempo é usado? A getnte não faz ideia!

Agora veja alguns exemplos de nomes significativos parecidos com o objetivo do exemplo anterior:

✅ Exemplo de nomes significativos:

const daysSinceAccountCreation = 25;
const daysSinceLastPostModification = 25;
const daysSinceLastLogin = 25;
Enter fullscreen mode Exit fullscreen mode

Vamos pegar a primeira variável e usar a técnica de responder as três questões:

-> Por que existe? Para saber há quanto tempo a conta existe.
-> O que faz? Exibe a quantidade de dias desde a criação de conta.
-> Como é usado? Pode ser usado como um campo de exibição na seção de informações da conta, por exemplo.

Agora ficou mais simples e claro, não é?

Não usar números mágicos

Como programadora, por diversas vezes me deparei com números em que eu não fazia ideia do porquê existiam. A função existe, funciona perfeitamente e tudo ocorre como o esperado. Mas por que é esperado esse tal número? Ou por que não é esperado esse tal número? Vejamos um exemplo prático:

❌ Exemplo de uso de número mágico:

if (new Date().getHours() > 18) {
    console.log('Atendimento indisponível.');
}
Enter fullscreen mode Exit fullscreen mode

A cafeteria fecha às 18h. Após esse horário, atendimentos não são mais realizados na loja. Podemos transformar essa informação em código, usando Clean Code:

✅ Exemplo de código limpo sem uso de número mágico:

const currentHour = new Date().getHours();
const closingHour = 18;

if (currentHour > closingHour) {
    console.log('Atendimento indisponível.');
}
Enter fullscreen mode Exit fullscreen mode

Agora é explícito para qualquer reviewer que esse número 18 presente no código, é equivalente ao horário de fechamento da loja.

Evitar informações confusas

❌ Exemplo de informação confusa:

const userList = {
    groupName: 'Admin',
    users: ['user01', 'user02'],
};
Enter fullscreen mode Exit fullscreen mode

Essa variável faria mais sentido se estivesse recebendo diretamente um array com TODOS os tipos de usuários, concorda? Esse nome pode acabar causando confusão, pois o objeto retorna apenas usuários do tipo Admin.

✅ Exemplo de informação clara:

const adminUserGroup = {
    groupName: 'Admin',
    users: ['user01', 'user02'],
};
Enter fullscreen mode Exit fullscreen mode

Agora fica claro que o uso dessa variável retorna apenas usuários do tipo Admin.

Fazer distinção significativa

❌ Exemplo de distinção suja:

getActiveAccount();
getActiveAccounts();
Enter fullscreen mode Exit fullscreen mode

Se você é programador ou programadora, muito provavelmente já teve problemas com um ponto e vírgula pelo menos alguma vez na vida. Dá pra compararmos um ponto e vírgula com esse exemplo acima. A letra S ao final da função, pode causar um erro difícil de ser percebido rapidamente, atrasando todo o trabalho do programador.

A partir disso, é importante lembrarmos de fazer distinção significativa ao escrever código que tenha funções diferentes mas no mesmo contexto:

✅ Exemplo de distinção significativa:

getActiveAccount();
getAllActiveAccounts();
Enter fullscreen mode Exit fullscreen mode

Comentários

Nome claro >>>>>>> comentários

O que você quer escrever no comentário? Por que não dizer a mesma coisa em nome de funções ou variáveis? Sempre que sentir a necessidade de fazer um comentário, tente fazer isso.

Comente só o necessário

Muitos comentários poluem e confundem o código. Não comente o óbvio.

Comentários absoletos

O código evolui com o tempo, mas nem sempre os comentários são atualizados. Ao surgir necessidade de deixar um comentário no código, é importante lembrarmos de atualizá-lo também.

Não usar como versionamento

EXCLUIR código não usado ao invés de comentar, é uma boa prática. Já me deparei com alguns colegas dizendo:

Mas iremos usar no futuro.
É muito simples, não foi trabalho a mais e a gente pode precisar depois.

Já temos o versionamento com GIT para nos ajudar nisso, não é? Ao precisar desse código, é só consultarmos nosso código em versões passadas. Sendo assim, sempre que o código não estiver sendo mais usado, exclua-o.

Formatação

Lembre-se de três pontos importantes:

  • Padronização
  • Consistência
  • Definição do time

Padronização

Escolher um estilo de indentação, ponto e vírgula, aspas simples ou dupla, idioma e etc.

Consistência

Ser consistente no código, traz facilidade aos desenvolvedores para identificar a estrutura e a lógica do código.

Definição do time

É uma boa prática seguir o que for decidido pelo time, mesmo se não for a sua preferência pessoal. Algumas vezes já aderi à formatações específicas de um framework, mesmo preferindo outro tipo de formatação.

Dentro de um time, em ambiente de trabalho, não é diferente. Por isso, é importante que o time faça uma definição de formatação que faça sentido para os projetos em que estiverem trabalhando. Todos do time devem seguir esse padrão definido.

Benefícios

"E pra que eu vou usar Clean Code no dia a dia, Hosana?" Se você não quiser ter facilidade na manutenção do seu código, melhorar a legibilidade dele, previnir erros, aumentar sua produtividade, facilitar os testes e aumentar a qualidade, nem precisa usar mesmo. :D

Dicas adicionais

  • Revise seu próprio código antes de entregar a tarefa, torne isso um hábito como parte do esforço que você vai ter nela.
  • Pense antes de nomear e exerça a habilidade de descrição. Como você explicaria o que está acontecendo no código para outra pessoa?
  • Faça o uso de ferramentas que facilitam a padronização, como: ESLint e Prettier.
  • Exerça refatoração. Deixe o código sempre mais limpo do que quando encontrou, sempre que possível.
  • Livro sobre Clean Code em português disponível para compra na Amazon.

Curtiu? Se conecte comigo onde preferir acessando minhas redes em: https://www.hosana.me.

. . . . .