DEV Community

Cover image for Código limpo de JavaScript - práticas recomendadas rápidas
Ivan Trindade
Ivan Trindade

Posted on

Código limpo de JavaScript - práticas recomendadas rápidas

Se você se preocupa com o código em si e como está escrito, em vez de se preocupar apenas se funciona ou não, pode dizer que pratica e se preocupa com o código limpo.

Um desenvolvedor profissional escreverá o código para o eu futuro e para o "outro cara", não apenas para a máquina.

Com base nisso, o código limpo pode ser definido como o código escrito de maneira autoexplicativa, fácil de entender por humanos e fácil de alterar ou estender.

Mesmo um código ruim pode funcionar, mas se o código não estiver limpo, ele pode colocar uma organização de desenvolvimento de joelhos.

Neste artigo, o foco será em JavaScript , mas os princípios podem ser aplicados a outras linguagens de programação.

  1. Verificações de tipo forte
0 == false // true
0 === false // false
2 == "2" // true
2 === "2" // false

// example
const val = "123";

if (val === 123) {
  console.log(val);
  // it cannot not be reached
}

if (val === "123") {
  console.log(val);
  // it can be reached
}
Enter fullscreen mode Exit fullscreen mode
  1. Variáveis

Nomeie suas variáveis ​​de forma que elas revelem a intenção por trás delas. Dessa forma, elas se tornam pesquisáveis ​​e fáceis de entender depois que uma pessoa os vê.

Ruim 👎

let daysSLV = 10;

let y = new Date().getFullYear();

let ok;

if (user.age > 30) {
  ok = true;
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

const MAX_AGE = 30;

let daysSinceLastVisit = 10;

let currentYear = new Date().getFullYear();

...

const isUserOlderThanAllowed = user.age > MAX_AGE;
Enter fullscreen mode Exit fullscreen mode

Não adicione palavras extras desnecessárias aos nomes das variáveis:

Ruim 👎

let nameValue;
let theProduct;
Enter fullscreen mode Exit fullscreen mode

Bom 👍

let name;
let product;
Enter fullscreen mode Exit fullscreen mode

Não imponha a necessidade de memorizar o contexto variável:

Ruim 👎

const products = ["T-Shirt", "Shoes", "Watches", "Bags"];

products.forEach(p => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  // ...
  // What is `p` for?
  register(p);
});
Enter fullscreen mode Exit fullscreen mode

Bom 👍


const products = ["T-Shirt", "Shoes", "Watches", "Bags"];

products.forEach(product => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  register(product);
});
Enter fullscreen mode Exit fullscreen mode

Não adicione contexto desnecessário:

Ruim 👎

const product = {
  productId: 1,
  productName: "T-Shirt",
  productPrice: 8.99,
  productUnits: 12
};

...

product.productName;
Enter fullscreen mode Exit fullscreen mode

Bom 👍


const product = {
  id: 1,
  name: "T-Shirt",
  price: 8.99,
  units: 12
};

...

product.name;
Enter fullscreen mode Exit fullscreen mode

Use o mesmo vocabulário para o mesmo tipo de variável

Ruim 👎

getUserInfo();
getClientData();
getCustomerRecord();
Enter fullscreen mode Exit fullscreen mode

Bom 👍

getProduct();
Enter fullscreen mode Exit fullscreen mode
  1. Funções

Use nomes longos e descritivos.

Considerando que representa um determinado comportamento, o nome de uma função deve ser um verbo ou uma frase que exponha totalmente a intenção por trás dela, bem como a intenção dos argumentos.

Seu nome deve dizer o que elas fazem:

Ruim 👎

function email(user) {
  // implementation
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function sendEmailUser(emailAddress) {
  // implementation
}
Enter fullscreen mode Exit fullscreen mode

Evite um longo número de argumentos, idealmente, uma função deve ter dois ou menos argumentos especificados. Quanto menos argumentos, mais fácil é testar a função:

Ruim 👎

function getProducts(fields, fromDate, toDate) {
  // implementation
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function getProducts({ fields, fromDate, toDate }) {
  // implementation
}

getProducts({
  fields: ['id', 'name', 'price', 'units],
  fromDate: '2020-07-01',
  toDate: '2020-07-22'
});
Enter fullscreen mode Exit fullscreen mode

Use argumentos default em vez de condicionais;

Ruim 👎

function createShape(type) {
  const shapeType = type || "circle";
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function createShape(type = "circle") {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Evite executar várias ações em uma única função:

Ruim 👎

function notifyUsers(users) {
  users.forEach(user => {
    const userRecord = database.lookup(user);
    if (userRecord.isVerified()) {
      notify(user);
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function notifyVerifiedUsers(users) {
  users.filter(isUserVerified).forEach(notify);
}

function isUserVerified(user) {
  const userRecord = database.lookup(user);
  return userRecord.isVerified();
Enter fullscreen mode Exit fullscreen mode

Use 'Object.assign' para definir objetos default:

Ruim 👎

const shapeConfig = {
  type: "circle",
  width: 150,
  height: null
};

function createShape(config) {
  config.type = config.type || "circle";
  config.width = config.width || 300;
  config.height = config.height || 300;
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

const shapeConfig = {
  type: "circle",
  width: 150
  // Exclude the 'height' key
};

function createShape(config) {
  config = Object.assign(
    {
      type: "circle",
      width: 300,
      height: 300
    },
    config
  );
  ...
}

Enter fullscreen mode Exit fullscreen mode

Não use sinalizadores como parâmetros, porque eles estão dizendo que a função está fazendo mais do que deveria:

Ruim 👎

function createFile(name, isPublic) {
  if (isPublic) {
    fs.create(`./public/${name}`);
  } else {
    fs.create(name);
  }
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function createFile(name) {
  fs.create(name);
}

function createPublicFile(name) {
  createFile(`./public/${name}`);
}
Enter fullscreen mode Exit fullscreen mode

Não polua os globais, se você precisar estender um objeto existente, use classes ES e herança em vez de criar a função na cadeia de protótipos do objeto nativo:

Ruim 👎

Array.prototype.myFunction = function myFunction() {
  // implementation
};
Enter fullscreen mode Exit fullscreen mode

Bom 👍

class SuperArray extends Array {
  myFunc() {
    // implementation
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Condicionais

Evite condicionais negativas:

Ruim 👎

function isPostNotPublished(post) {
  // implementation
}
if (!isPostNotPublished(post)) {
  // implementation
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

function isPostPublished(user) {
  // implementation
}
if (isPostPublished(user)) {
  // implementation
}
Enter fullscreen mode Exit fullscreen mode

Use abreviação condicional, esta abordagem serve apenas para valores booleanos e se tiver certeza de que o valor não será null ou undefined:

Ruim 👎

if (isValid === true) {
  // do something...
}
if (isValid === false) {
  // do something...
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

if (isValid) {
  // do something...
}
if (!isValid) {
  // do something...
}
Enter fullscreen mode Exit fullscreen mode

Evite condicionais sempre que possível, em vez disso, use polimorfismo e herança:

Ruim 👎

class Dog {
  // ...
  getBreed() {
    switch (this.type) {
      case "GermanShepherd":
        return this.getStandardSize("GermanShepherd");
      case "JackRussellTerrier":
        return this.getStandardSize("JackRussellTerrier");
      case "ShibaInu":
        return this.getStandardSize("ShibaInu");
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Bom 👍

class Dog {
  // ...
}

class GermanShepherd extends Dog {
  // ...
  getStandardSize() {
    return this.standardSize;
  }
}

class JackRussellTerrier extends Dog {
  // ...
  getSize() {
    return this.standardSize;
  }
}

class ShibaInu extends Dog {
  // ...
  getSize() {
    return this.standardSize;
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. ES Classes

As classes são o novo açúcar sintático em JavaScript. Tudo funciona exatamente como antes com o protótipo, mas agora parece diferente e você deve preferi-los às funções simples do ES5:

Ruim 👍

const Product = function(name) {
  if (!(this instanceof Product)) {
    throw new Error("Instantiate Product with `new` keyword");
  }
  this.name = name;
};

Product.prototype.getSize = function getSize() { /**/ };

const Tshirt = function(name, color) {
  if (!(this instanceof Tshirt)) {
    throw new Error("Instantiate Tshirt with `new` keyword");
  }
  Product.call(this, name);
  this.color = color;
};

Tshirt.prototype = Object.create(Product.prototype);
Tshirt.prototype.constructor = Tshirt;
Tshirt.prototype.printColor = function printColor() { /**/ };
Enter fullscreen mode Exit fullscreen mode

Bom 👍

class Product {

  constructor(name) {
    this.name = name;
  }

  getDiscount() {
    /* ... */
  }
}

class Tshirt extends Product {

  constructor(name, color) {
    super(name);
    this.color = color;
  }

  getSize() {
    /* ... */
  }
}
Enter fullscreen mode Exit fullscreen mode

Use encadeamento de métodos, muitas bibliotecas, como jQuery e Lodash, usam esse padrão. Como resultado, seu código será menos detalhado. Em sua classe, simplesmente retorne isso no final de cada função e você poderá encadear outros métodos de classe nela:

Ruim 👍

class Product {

  constructor(name) {
    this.name = name;
  }

  setPrice(price) {
    this.price = price;
  }

  setUnits(units) {
    this.units = units;
  }

  save() {
    console.log(this.name, this.price, this.units);
  }
}

const product = new Product("Bag");

product.setPrice(23.99);
product.setUnits(12);
product.save();
Enter fullscreen mode Exit fullscreen mode

Bom 👍

class Product {

  constructor(name) {
    this.name = name;
  }

  setName(name) {
    this.name = name;
    // Return this for chaining
    return this;
  }

  setPrice(price) {
    this.price = price;
    // Return this for chaining
    return this;
  }

  save() {
    console.log(this.name, this.price, this.units);
    // Return this for chaining
    return this;
  }
}

const product = new Product("T-Shirt")
    .setName("Jeans")
    .setAge(31.99)
    .save();
Enter fullscreen mode Exit fullscreen mode
  1. Evite usar Eval

A função Eval nos permite passar uma string para o compilador JavaScript e executá-la como JavaScript. Em termos simples, qualquer coisa que você passar em tempo de execução será executada como se tivesse sido adicionada em tempo de execução:

eval("alert('Hi');");
Enter fullscreen mode Exit fullscreen mode

Isso abriria uma caixa de alerta com a mensagem "Olá".

A função Eval deve ser evitada porque não é segura e abre um vetor de ameaça potencial para os programadores mal-intencionados explorarem.

  1. Use ESLint

ESLint é uma ótima ferramenta para ajudá-lo a identificar problemas comuns em seu código JavaScript, ele irá detectar códigos ruins que estão sendo mascarados pelo navegador. Isso tornará seu código mais limpo e ajudará a evitar que esses bugs incômodos apareçam na produção.

  1. Evite em geral

Em geral, você deve fazer o possível para não se repetir, o que significa que não deve escrever código duplicado e não deixar rastros para trás, como funções não utilizadas e código morto.

Remover código duplicado nessa situação significa abstrair as diferenças e tratá-las nesse nível.

E sobre o código morto , bem é o que o nome diz.

É o código parado em nossa base de código que não está fazendo nada porque, em algum momento do desenvolvimento, você decidiu que ele não tem mais um propósito .

Você deve procurar essas partes em sua base de código e excluir todas as funções e blocos de código desnecessários.

Um conselho que posso dar a você é que, assim que decidir que não é mais necessário, exclua-o.

Conclusão

Isso é apenas uma fração do que você poderia fazer para melhorar seu código.

Na minha opinião, os princípios aqui alegados são aqueles que muitas vezes as pessoas não seguem.

Eles tentam, mas não é fácil manter a força mental e fazer um ótimo código o tempo todo .

Talvez no início do projeto, o código esteja organizado e limpo , mas quando se trata de cumprir os prazos, os princípios são frequentemente ignorados e movidos para uma seção “TODO” ou “REFACTOR” .

Obrigado por ler e até o próximo artigo!

Top comments (0)