DEV Community

Cover image for CLEAN CODE - BOAS PRÁTICAS
Abraão Duarte
Abraão Duarte

Posted on

CLEAN CODE - BOAS PRÁTICAS

Atualmente estou lendo o livro Clean Code, escrito por Robert C. Martin, conhecido como Uncle Bob, por isso, decidi escrever um artigo com algumas dicas importantes que encontrei na leitura e que tem me motivado a escrever códigos melhores.

Boa parte do tempo dos desenvolvedores de software é gasto escrevendo códigos, portanto devemos ter um cuidado em como escrevemos esses códigos, nós nos expressamos por meio dos códigos que escrevemos e, eles devem ser legíveis e de fácil compreensão.

Talvez você já tenha percebido que nos passamos grande parte de nosso tempo dando manutenção, seja em sistemas legados e antigos, seja nos nossos próprios códigos que escrevemos a pouco tempo, estamos sempre acrescentando algo novo, corrigindo erros, melhorando, etc. Justamente por causa disso que devemos nos esforçar por escrever códigos melhores, mais legíveis, para que a manutenção e mesmo a evolução do sistema seja mais fácil e menos dolorosa.

Quando nos deparamos em situações onde precisamos dar manutenção em algum código ruim, essa tarefa pode ser tornar demorada, difícil e cara, pois iremos gastar um tempo maior do que gastaríamos caso esse código estivesse mais legível 😠. E já vou adiantando, escrever código limpo não é uma tarefa simples e fácil, antes é algo trabalhoso, em outras palavras, você irá suar a camisa, nesse processo você irá errar, e também ver outros errarem, mas não desanime. No fim das contas como o próprio autor do livro diz:

Escrever código limpo é uma arte e vai tempo e prática. 😲

O que seria um código limpo? Juntando algumas definições que encontrei no livro, pode se dizer que: ‘um código limpo é elegante e eficiente, que faz somente uma coisa, aquilo que ele se propõe a fazer. É algo simples e direto, legível e claro. É um código bem testado, bem escrito’.

Para escrever código limpo precisamos estar atentos aos detalhes, pois eles são importantes e no fim das contas fazem a diferença.

Dado essa introdução, irei apresentar algumas sugestões que encontrei no livro e que acho válido compartilhar, os códigos de exemplo estarão em Javascript, porém os conceitos podem ser aplicados em qualquer linguagem.

Nomes são importantes, portanto seja cuidadoso.

Você já deve ter se deparado com nomes de variáveis, funções, métodos que eram obscuros e difíceis de compreender. Para entendermos esses nomes, gastamos um tempo maior que gastaríamos se o nome estivesse claro. Isso mostra que dar nomes corretos e claros fazem diferença.

1. Use nomes que revelam seu propósito.

Um nome deve ter significado que diz o que ele faz ou ao que ele se refere. Se um nome precisa de um comentário, então ele já não revela seu proposito.

Exemplo ruim: 🙈

const d = new Date();
const y = d.getYear();
const m = d.getMonth();
Enter fullscreen mode Exit fullscreen mode

Exemplo bom: 😁

const date = new Date();
const year = d.getYear();
const month = d.getMonth();
Enter fullscreen mode Exit fullscreen mode

2. Use distinções significativas

Exemplo ruim: 🙈

getDetails();
getData();
getRecord();
Enter fullscreen mode Exit fullscreen mode

Às três funções parecem ser a mesma coisa, não existe uma distinção clara que diz o que essa função está fazendo.

Um exemplo melhor pode ser o seguinte: 😁

getUser(); // É melhor que os exemplos acima.
Enter fullscreen mode Exit fullscreen mode

3. Use nomes fáceis de se pronunciar, ou pelo menos que sejam pronunciáveis.

Você já se deparou com nome de variáveis que são impronunciáveis? Isso é uma má prática.

Veja o seguinte exemplo: 🙈

const yyyymmdstr = ‘2021-06-09’;
Enter fullscreen mode Exit fullscreen mode

É uma variável que não tem como pronunciar seu nome. Poderíamos rescrever da seguinte maneira: 😁

const currentDate = ‘2021-06-09’;
Enter fullscreen mode Exit fullscreen mode

4. Use nomes que sejam fáceis de se buscar.

Por exemplo, nomes de uma letra só: const d = new Date(); são difíceis de se pesquisar e irá trazer uma infinidade de resultados

Outro exemplo: 🙈

setTimeout(blastOff, 86400000);
Enter fullscreen mode Exit fullscreen mode

Pesquisar por número que não trazem nenhum significado não, é algo muito bom, e podem acabar retornando resultados inesperados, podemos escrever da seguinte maneira: 😁

const MILLISECONDS_PER_DAY = 86400000;

setTimeout(blastOff, MILLISECONDS_PER_DAY);
Enter fullscreen mode Exit fullscreen mode

Dessa maneira você pode pesquisar pelo nome da variável e também está claro o que esse numero representa.

5. Nomes de classes devem ter nomes com substantivos

Exemplo: 😁

class User {}
class Customer {}
Enter fullscreen mode Exit fullscreen mode

6. Nome de métodos é uma boa prática ter verbos

Exemplo: 😁

getUser();
deleteUser();
handleVote();
Enter fullscreen mode Exit fullscreen mode

Escreva funções melhores

Estamos escrevendo funções a todo momento, é importante que essas sejam claras e legíveis.

Funções devem ser pequenas, você já deve ter se deparado em algum momento com funções com dezenas de linhas, que fazem várias coisas. Funções assim são difíceis de dar manutenção, pois é difícil entende-las.

Algumas dicas para escrever funções melhores

1. Faça apenas uma coisa

Funções devem fazer somente uma coisa e devem fazê-la bem.

Uma boa forma de sabermos se nossa função faz mais de uma coisa é se conseguimos extrair outras funções dela.

Exemplo ruim: 🙈

function emailClients(clients) {
    clients.forEach(client => {
        const clientRecord = database.lookup(client);
        if (clientRecord.isActive()) {
            email(client);
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

Essa função tem mais de uma responsabilidade, ela pega os dados do cliente e verifica se o cliente está ativo.

Poderíamos separar da seguinte maneire: 😁

function emailActiveClients(clients) {
    clients.filter(isActiveClient).forEach(email);
}

function isActiveClient(client) {
    const clientRecord = database.lookup(client);
    return clientRecord.isActive();
}
Enter fullscreen mode Exit fullscreen mode

Veja, cada função é responsável por fazer apenas 1 coisa.

As funções devem fazer uma coisa. Devem fazê-la bem. Devem fazer apenas ela. 😲

2. Um nível de abstração por função

Vários níveis de abstração dentro de uma função sempre geram confusão.
Exemplo: 🙈

function parseBetterJSAlternative(code) {
    const REGEXES = [ // ... ];
    const statements = code.split(" ");
    const tokens = [];
    REGEXES.forEach(REGEX => {
        statements.forEach(statement => { // ... });
    });
    const ast = [];
    tokens.forEach(token => { // lex... });
    ast.forEach(node => { // parse... }); }
Enter fullscreen mode Exit fullscreen mode

Veja essa função, é difícil entender o que acontece mesmo ela sendo pequena. Imagina uma função com o triplo do tamanho, fazendo várias coisas, é difícil dar manutenção nessas funções.

Veja como poderíamos escrever: 😁

function parseBetterJSAlternative(code) {
    const tokens = tokenize(code);
    const syntaxTree = parse(tokens);
    syntaxTree.forEach(node => { // parse... });
}

function tokenize(code) {
    const REGEXES = [ // ... ];
    const statements = code.split(" ");
    const tokens = [];
    REGEXES.forEach(REGEX => {
        statements.forEach(statement => {
            tokens.push(/* ... */);
        });
    });
    return tokens;
}

function parse(tokens) {
    const syntaxTree = [];
    tokens.forEach(token => {
        syntaxTree.push(/* ... */);
    });
    return syntaxTree;
}

Enter fullscreen mode Exit fullscreen mode

3. Use nomes descritivos

Mesma regra que usamos para variáveis, que sejam claro e legível e diga o que a função faz.

Não tenha medo de criar nomes extensos, pois eles são melhores que um pequeno e enigmático.

4. Parâmetros de funções

Devemos evitar passar vários parâmetros para uma função, o ideal é que nossas funções recebam no máximo 2 parâmetros.

Veja o seguinte exemplo: 🙈

function createMenu(title, body, buttonText, cancellable) {
    // doSomething
}
createMenu("Foo", "Bar", "Baz", true);
Enter fullscreen mode Exit fullscreen mode

Veja que é confuso e muito fácil esquecer de passar um parâmetro e quebrar a função.

Prefira fazer assim: 😁

function createMenu({ title, body, buttonText, cancellable }) {
    // doSomething
}
createMenu({
    title: "Foo",
    body: "Bar",
    buttonText: "Baz",
    cancellable: true
});
Enter fullscreen mode Exit fullscreen mode

Dessa maneira fica mais clara, você sabe o que é o que.

5. Parâmetros lógicos

Parâmetros lógicos é uma má prática, pois mostra explicitamente que a função faz mais de uma coisa.

Veja: 🙈

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

O parâmetro temp é um booleano, isso implica que a função tem mais de uma responsabilidade.

Poderíamos fazer: 😁

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

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

Veja que evitamos passar valores booleanos como parâmetro de função.

6. Evite efeitos colaterais

Efeitos colaterais são mentiras. Sua função promete fazer apenas uma coisa, mas ela também faz outras coisas escondidas.

Efeitos colaterais são perigosos, e muitas vezes difíceis de se identificar.

Veja esse exemplo: 🙈

let name = "Ryan McDermott";

function splitIntoFirstAndLastName() {
    name = name.split(" ");
}
splitIntoFirstAndLastName();
console.log(name);
Enter fullscreen mode Exit fullscreen mode

A variável name está sendo modificada na função splitIntoFirstAndLastName isso é ruim, pois em um arquivo com dezenas de linhas, você se perderia para encontrar os lugares onde essa variável está sendo modificada. Você não saberia qual é o valor de name uma vez que em cada função ela pode ter um valor.

Evite variáveis globais.

Veja como poderíamos fazer: 😁

function splitIntoFirstAndLastName(name) {
    return name.split(" ");
}
const name = "Ryan McDermott";
const newName = splitIntoFirstAndLastName(name); console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];

Enter fullscreen mode Exit fullscreen mode

A variável name é um parâmetro da função, e assim não tem nenhum efeito colateral ao alterar esse parâmetro na função.

7. Evite repetição

Duplicação de código pode ser um grande mal no seu software, sempre que você ver que você está repetindo muito código, extraia isso para funções.

Escreva comentários com responsabilidade

Por vezes o uso de comentários é para compensar o nosso fracasso em nos expressar no código.

É melhor você ter um código legível com poucos comentários do que um código complexo, difícil de ler com vários comentários.

Não insira comentários em um código ruim, refatore ele.

Comentários imprecisos são muito piores do que nenhum. O único lugar onde pode-se encontrar a verdade é no código. Só ele pode dizer o que ele realmente faz, comentários podem mentir.

Comentários ruins

  1. Comentários esquecidos no código.
  2. Comentários redundantes, por exemplo:
    // Function that get users
    const getUsers = () => {...}
Enter fullscreen mode Exit fullscreen mode
  1. Comentários longos
  2. Comentários ruidosos
    // Return the day of month
    const getDayOfMonth = () => {...}
Enter fullscreen mode Exit fullscreen mode
  1. Códigos como comentários

Conclusão

A conclusão é que se você é um programador você deveria se importar com seu código, se seguirmos essas dicas, ou pelo menos algumas delas, já estaremos escrevendo códigos melhores.

Ao escrever código limpo estaremos ajudando futuras pessoas que venham dar manutenção no nosso código, e também estaremos ajudando a nós mesmo, caso no futuro tenhamos que dar manutenção no código que fizemos.

Este é apenas alguns pontos que eu achei interessante nos primeiros 4 capítulos do livro, espero ainda trazer mais alguns artigos a respeito do assunto.

Fonte

Martin, Robert C. Código Limpo: Habilidades práticas do agile software. Ed. Revisada São Paulo: Alta Books, 2011.

Exemplos: https://github.com/ryanmcdermott/clean-code-javascript

Top comments (0)