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.
- 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
}
- 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;
}
Bom 👍
const MAX_AGE = 30;
let daysSinceLastVisit = 10;
let currentYear = new Date().getFullYear();
...
const isUserOlderThanAllowed = user.age > MAX_AGE;
Não adicione palavras extras desnecessárias aos nomes das variáveis:
Ruim 👎
let nameValue;
let theProduct;
Bom 👍
let name;
let product;
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);
});
Bom 👍
const products = ["T-Shirt", "Shoes", "Watches", "Bags"];
products.forEach(product => {
doSomething();
doSomethingElse();
// ...
// ...
// ...
register(product);
});
Não adicione contexto desnecessário:
Ruim 👎
const product = {
productId: 1,
productName: "T-Shirt",
productPrice: 8.99,
productUnits: 12
};
...
product.productName;
Bom 👍
const product = {
id: 1,
name: "T-Shirt",
price: 8.99,
units: 12
};
...
product.name;
Use o mesmo vocabulário para o mesmo tipo de variável
Ruim 👎
getUserInfo();
getClientData();
getCustomerRecord();
Bom 👍
getProduct();
- 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
}
Bom 👍
function sendEmailUser(emailAddress) {
// implementation
}
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
}
Bom 👍
function getProducts({ fields, fromDate, toDate }) {
// implementation
}
getProducts({
fields: ['id', 'name', 'price', 'units],
fromDate: '2020-07-01',
toDate: '2020-07-22'
});
Use argumentos default em vez de condicionais;
Ruim 👎
function createShape(type) {
const shapeType = type || "circle";
// ...
}
Bom 👍
function createShape(type = "circle") {
// ...
}
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);
}
});
}
Bom 👍
function notifyVerifiedUsers(users) {
users.filter(isUserVerified).forEach(notify);
}
function isUserVerified(user) {
const userRecord = database.lookup(user);
return userRecord.isVerified();
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;
}
Bom 👍
const shapeConfig = {
type: "circle",
width: 150
// Exclude the 'height' key
};
function createShape(config) {
config = Object.assign(
{
type: "circle",
width: 300,
height: 300
},
config
);
...
}
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);
}
}
Bom 👍
function createFile(name) {
fs.create(name);
}
function createPublicFile(name) {
createFile(`./public/${name}`);
}
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
};
Bom 👍
class SuperArray extends Array {
myFunc() {
// implementation
}
}
- Condicionais
Evite condicionais negativas:
Ruim 👎
function isPostNotPublished(post) {
// implementation
}
if (!isPostNotPublished(post)) {
// implementation
}
Bom 👍
function isPostPublished(user) {
// implementation
}
if (isPostPublished(user)) {
// implementation
}
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...
}
Bom 👍
if (isValid) {
// do something...
}
if (!isValid) {
// do something...
}
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");
}
}
}
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;
}
}
- 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() { /**/ };
Bom 👍
class Product {
constructor(name) {
this.name = name;
}
getDiscount() {
/* ... */
}
}
class Tshirt extends Product {
constructor(name, color) {
super(name);
this.color = color;
}
getSize() {
/* ... */
}
}
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();
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();
- 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');");
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.
- 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.
- 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)