Logo Dallington Augusto

  • Home
  • Artigos
  • Sobre

Código Limpo: Algumas práticas que melhoraram meu código

Este artigo foi publicado em 16/07/2022, e leva aproximadamente 10 minutos para ler.

Introdução

Eu ganhei o livro “Código Limpo - Robert Cecil Martin” de um amigo. Confesso que em um primeiro momento eu não dei a devida importância.

Mas após a leitura de uma postagem de um outro amigo, Clean Code: O que é? Porque usar?, comecei a entender a importância de tal assunto.

Hoje posso falar com propriedade, se você quer estar mais motivado ao trabalhar em seus projetos, impressionar seu revisor de código e levar seu desenvolvimento a outro nível, você deve começar a escrever código limpo.

A diferença entre criar um código ilegível, e um código tão claro quanto o céu, não é algo de outro mundo, pelo contrário, apenas tornará a programação mais fácil.

Neste artigo vou deixar algumas práticas com alguns exemplos, que elevaram meus códigos para um novo nível. 🚀

O que é código limpo?

Muitos desenvolvedores ainda pensam que código limpo é escrever o menor número de linhas possível. Mas isso não é inteiramente verdade. Código limpo tem tudo a ver com tornar o código compreensível.

Código limpo não é apenas um código conciso, mas, mais importante, é legível. Uma regra prática ao escrever código é escrever código como se os comentários não existissem. O código deve ser autoexplicativo.

Outra parte sobre código limpo, sobre o qual poucos desenvolvedores falam, é como o mesmo código pode ser escrito de muitas maneiras diferentes. Isso deixa muito espaço para confusão, especialmente em uma linguagem de tipo dinâmico como javascript. Um código realmente limpo não pode ser interpretado de várias maneiras.

Então… Código limpo é conciso, autoexplicativo e não pode ser interpretado de várias maneiras .

Por que precisamos disso?

Não há dúvida de que o código limpo pode exigir mais trabalho e pode levar mais tempo para escrever. Mas também não existe isso, código sujo e rápido é super impraticável a longo prazo…

Implementar, manter e refatorar será um desafio se você estiver trabalhando com código ilegível. seu futuro eu e/ou outros desenvolvedores precisarão gastar muito tempo entendendo o que está acontecendo no código.

Aprender código limpo é o melhor truque de produtividade que qualquer desenvolvedor pode fazer!

Boas Práticas

Nos exemplos abaixos utilizei a linguagem javascript, mas os conceitos são praticamente os mesmos em qualquer linguagem.

1: Melhores nomes

Apesar de não podermos alterar a sintaxe, ainda temos total controle sobre nossas variáveis. Este é um dos melhores lugares onde podemos melhorar nosso código. A chave para uma boa nomenclatura não está em ter os nomes de variáveis mais curtos, mas sim em ter nomes mais descritivos

Sem números mágicos

Em primeiro lugar, não use números mágicos. Certifique-se de que todos os números estejam armazenados em uma variável, para que você saiba o que o número representa. E se você estiver usando uma primitiva constante (um valor primitivo que não mudará), você deve nomeá-las em maiúscula snake_case.

com números mágicos 👎
for (i=0; i < 8765; i++){
    // faz alguma coisa
    // faz alguma coisa
    // faz alguma coisa
}
magicNumbers.js
sem números mágicos 👍
const WEEKS_IN_A_YEAR = 52

for (i=0; i < WEEKS_IN_A_YEAR; i++){
    // faz alguma coisa
}
magicNumbers.vue

Nome por tipo

Em uma linguagem dinâmica como javascript, você pode facilmente se confundir quando não consegue acessar o tipo de variável. E uma única variável pode ser interpretada de várias maneiras, o que gera muita confusão na hora de ler o código.

nomes ruins 👎
// isso pode significar um booleano, data ou até mesmo um não primitivo.
const expired = true; 

// ninguém sabe o que significam nomes de variáveis de uma única letra 🤷
const e = true; 
nomes bons 👍
// booleanos sempre devem ter um prefixo como "is", "has" ou "was"
const hasExpired = true; 
const hasExpired = true; 
const expiredDate = new Date()

let expiredElementsAmount = 0
let allExpiredElemnts = []

2: Seja conciso

Embora a nomenclatura não seja uma questão de brevidade, o código geral é, até certo ponto. Muitos programadores perdem o controle

- DRY (Não se repita)

Para obter um código conciso melhor, certifique-se de seguir o princípio DRY (Don’t Repeat Yourself) .

Código repetido 👎
async function notifyUsers(userIds, message) {
    userIds.foreach(userId => {
        userIds.foreach(userId => {
            const user = await User.findByPk(userId)
            if(user.isSubscribed) {
                const Notification = await Notifications.create({ 
                date: new Date(),
                user_id: userId,
                message,
                emailNotify: true
                });   
                Notification.save();
            } else {
                const Notification = await Notifications.create({ 
                date: new Date(),
                user_id: userId,
                message,
                emailNotify: true 
                });   
                Notification.save();
            }
        }
    }
}
DRY 👍
async function notifyUsers(userIds, message) {
    userIds.foreach(userId => {
      const user = await User.findByPk(userId)
      notifyUsers(userId, message, user.isSubscribed)
    }
}
                    
async function createNotification(userId, message, isSubscribed) {
    const Notification = await Notifications.create({ 
        date: new Date(),
        user_id: userId,
        message,
        emailNotify: isSubscribed 
    });   
    Notification.save();
}
- Princípio de responsabilidade única

Com o princípio de responsabilidade única, você pode nomear facilmente suas funções, que fazem apenas uma coisa. Você sabe exatamente o que a função faz pelo nome, e a função não será longa e esmagadora.

a função faz muitas coisas 👎
async function signupUser(email) {
  // criando o usuário
  const user = await User.create({ email });
  await user.save();
  
  // criando a notificação
  const notification = await Notification.create({ email });
  await notification.save();
  
  // log de registro de novo usuário 
  const date = new Date()
  Log.add(date, "signed up", email)
}
funções de um único propósito 👍
const logSignup(email) => Log.add(new Date(), "signed up", email)

async function signupUser(email) {
  createUser(email)
  notifyUser(email)
  logSignup(email)
}

async function createUser(email) {
  const user = await User.create({ email });
  await user.save();
}

async function notifyUser(email) {
  const notification = await Notification.create({ email });
  await notification.save();
}

Template Literals Strings

Template Strings são strings que permitem expressões embutidas. Você pode utilizar string multi-linhas e interpolação de string com elas. Template strings são envolvidas por (acentos graves) ( ) em vez de aspas simples ou duplas. Template strings podem possuir placeholders. Estes são indicados por um cifrão seguido de chaves (${expression}).

Basicamente é uma nova forma de criar strings e tornar o seu código um pouco mais curto, legível.

sem template strings 👎

const welcomeMessage = “Hi ” + user + “, today you need to “ + firstTodo

com template strings 👎

const welcomeMessage = `Hi ${user}, today you need to ${firstTodo}`

3: Livre-se do aninhamento profundo

Um dos lugares mais fáceis de perder ao ler o código é se você encontrar um código profundamente aninhado dentro de um monte de colchetes diferentes. Tente manter seu código o mais linear possível, usando as técnicas abaixo.

Usar cláusulas de proteção

Não aninhe sua instrução de retorno em um if-else. Livre-se do aninhamento e encurte o código com cláusulas de guarda.

sem qualquer cláusula de guarda👎
const getUSTime = (time) => {
  if(time <= 12){
    return time + "AM"
  } else {
    return time + "PM"
  }
}
com uma cláusula de guarda 👍
const getUSTime = (time) => {
  if(time <= 12) return time + "AM"
  return time + "PM"
}
Às vezes é até possível usar um ternário 👍
const getUSTime = (time) => time +  (time <= 12 ? "AM" : "PM")

Async Await em vez de Promisses

Assim que você tiver um conjunto de promessas encadeadas, você terá um código aninhado com má legibilidade.

promisses 👎
const sharePost = () => {
  getPost().then(post => {
    sendTweet(post.url, `this is an awesome article: ${post.title}`)
    .then(() => {
      console.log("tweet shared");
    });
  });
}
async await 👍
const sharePost = async () => {
  const post = await getPost();
  await sendTweet(post.url, `this is an awesome article: ${post.title}`);
  console.log("tweet shared");
}

4: Desestruturar

Você pode poupar muito código reestruturando seus objetos e arrays. No exemplo abaixo, você pode ver como é fácil extrair, nomear e fornecer valores de fallback para valores reestruturados.

// desestruturação de objeto renomeando o id para userId
const { id: userId, name, email } = user;

// es-6 fail-soft desestruturação
const [a = 1, b = 2, c = 3] = list 

// desestruturação de argumentos com valor padrão.
function ({id, name, type = "unSubscribed"}) {} 

5: Aprenda sintaxes

Lembrar a sintaxe não é o que se trata de programação, mas conhecer as sintaxe linguagens (principalmente as novas) definitivamente aumenta sua capacidade de escrever código limpo.

Optional Chaining (Encadeamento opcional)

O operador ?. funciona de maneira similar ao operador . de encadeamento, exceto que, ao invés de causar um erro se a referência é nullish (null ou undefined), a expressão sofre um “curto-circuito” e retorna com um valor de undefined. Quando utilizado com uma chamada de função, retorna undefined se a função executada não existir.

function userFirstArticleLikes(user) {
  // grande quantidade de condicionais  👎
  if(user && user.articles && user.articles[0] && user.articles[0].likes) 
    return user.articles[0].likes.map(() => /*...*/)
  return []

  // Optional chaining 👍
  const userFirstArticleClaps = user?.articles[0]?.likes.map(() => /*...*/) 
}

Conselho bônus

Pense no seu “eu do futuro”.

Quem nunca escreveu um código “meia boca”, e após algum tempo foi dar manutenção e ao ler o código, pensou “WHAT A FUCK ?”. Portanto, escrever um código bem feito e limpo, vai te poupar horas e horas em um futuro próximo.

Tenha práticas recomendadas comuns em sua equipe

O código limpo pode ser diferente de desenvolvedor para desenvolvedor, o que significa que os padrões e as melhores práticas serão diferentes em todo o projeto. Portanto, se você estiver trabalhando em um projeto com uma equipe, eu o encorajo a decidir sobre algumas práticas recomendadas fixas, para alcançar uma estrutura uniforme em sua base de código. Você pode se beneficiar do uso do Eslint para identificar melhor padrões problemáticos e recursos desnecessários no código. Também pode ajudá-lo a seguir os padrões de codificação decididos e manter o código uniforme. Além disso, você pode adicionar o Prettier ao projeto e obter seu código formatado automaticamente.

Índice

  • Introdução
  • O que é código limpo?
  • Por que precisamos disso?
  • Boas Práticas
    • 1: Melhores nomes
    • 2: Seja conciso
    • 3: Livre-se do aninhamento profundo
    • 4: Desestruturar
    • 5: Aprenda sintaxes
  • Conselho bônus

Gostou desse artigo ?

  • 🤩
  • 😑
  • 😒
  • Home
  • Artigos
  • Jardim
  • Sobre
  • Contato

Exceto onde indicado de outra forma, o conteúdo deste site é licenciado sob uma licença CC BY 4.0