Clean code, por onde começar?

*Texto de Luziane Freitas
Desenvolvedora front-end júnior na Convenia e membro do SpaceSquad da Rocketseat

Se você é desenvolvedor(a), com certeza já ouviu falar em código limpo, mas afinal o que é isso?

O clean code ou código limpo é um conjunto de práticas na escrita de código que podem ser aplicados para uma maior legibilidade e manutenibilidade do seu projeto. Fazendo uma simples analogia, podemos pensar que o código é seu quarto e o clean code são ações que você executa para organizá-lo da melhor forma possível, facilitando seu dia a dia.

Mas antes de falar sobre código limpo, precisamos entender o porquê utilizá-lo.

Um código ruim pode causar problemas que afetam não só o dia a dia do desenvolvimento e o desempenho de um time, mas também a usabilidade do software.

Entre as primeiras dificuldades que encontramos ao trabalhar com um código ruim, podemos citar a resolução de bugs e demora em executar tarefas simples. Isso acontece pois quando lidamos com um código ruim temos dificuldades na leitura e entendimento do que está acontecendo.

Além disso, com o passar do tempo o software pode ficar defeituoso, causando problemas não só para o desenvolvedor mas para a empresa como o todo, levando em consideração os custos envolvidos em todos os processos.

Dessa forma devemos sempre estudar e praticar a escrita de um código bom para nos tornarmos um bom profissional.

Como identificar códigos ruins?

Para quem está iniciando nessa área, identificar um código ruim nem sempre será fácil, mas com o passar do tempo e com prática isso se tornará possível e corriqueiro. Podemos começar analisando alguns pontos que são mais simples de reconhecer no começo, como por exemplo:

  • O código não possui organização em sua escrita, como por exemplo quebra de linhas entre blocos de funções, importações e declaração de variáveis etc;
  • O código não segue um padrão na escrita das variáveis, funções que não seguem ou misturam sem uma justificativa camelCase, snake_case e etc;
  • O código não tem um padrão de indentação. Lembre-se que quanto mais profunda a indentação em um bloco de código, é sinal que, provavelmente, ele precisa ser refatorado;
  • Números ou strings mágicos, ou seja, aqueles valores obscuros espalhados pelo código e que não dizem o que de fato eles são.

Esses são alguns dos muitos pontos que são analisados para identificar melhorias no código.

Refatoração

Agora que já sabemos como identificar possíveis códigos ruins, vamos entender como melhorá-los e, para isso, precisamos entender o conceito de refatoração, pois ela será nossa amiga durante esse processo.

A refatoração é um processo de modificação de um código existente, que tem como objetivo  melhorar sua estrutura e qualidade sem alterar sua funcionalidade. Ela pode ser aplicada desde as coisas mais simples, como renomear variáveis, até as mais complexas, como a organização de códigos em funções e módulos menores e também a remoção de códigos desnecessários, entre outros.

Esse é um processo muito importante por ajudar a manter o código limpo e organizado, facilitando a manutenção e a adição de novas funcionalidades. É claro que saber identificar o código sujo e saber o que é refatoração não garantem que você vá saber escrever um código limpo. Mas a intenção deste artigo é te ajudar a começar a praticar, para que, no futuro, você tenha mais habilidades que te auxiliem nesse processo.

Exemplos para iniciar sua prática

Aqui vou apresentar alguns pontos que já foram abordados anteriormente e alguns exemplos práticos. irei utilizar o JavaScript para exemplificar, mas você poderá usar a base a seguir como modelo para outras linguagens, seguindo suas respectivas nomenclaturas.

Então aqui vão alguns exemplos do que evitar ao escrever seu  código.

  • Mistura de idiomas.

Como mencionado anteriormente, é ideal seguir um padrão dentro do nosso código, inclusive para o idioma escrito. Entre os padrões que podemos citar,  um deles é o inglês tanto para a escrita de código quanto para documentações. Normalmente as linguagens possuem como padrão comandos e palavras-chave em inglês.

Evitar:

let moeda = {
	value: 10,
	country: 'USA'
} 

Fazer:

let currency = {
	amount: 10,
	country: 'USA'
} 
  • Dê nomes significativos e dentro do contexto aplicado evitando a abreviação.

Evitar:

const fName = 'Sheldon Lee Cooper'

Fazer:

const fullName = 'Sheldon Lee Cooper'

Evite nomes redundantes

Evitar:

let person = {
	personName: 'Sheldon',
	personLastName: 'Lee Cooper',
	personAge: 42,
}

Fazer:

let person = {
	name: 'Sheldon',
	lastName: 'Lee Cooper',
	age: 42,
}
  • Evite colocar tipos no nome da variável

Evitar:

let arrayOfFruits = [ 'banana', 'morango', 'manga' ]

Fazer:

let fruits = [ 'banana', 'morango', 'manga' ]

Utilize um padrão para escrever e crie constantes para os números mágicos.

Evitar:

function calcMedia (a, b) {
	const media_notes = (a + b) / 2

	if (media_notes >= 6) {
		return 'Media alcançada'
	}
	return 'Media não alcançada'
}

Fazer:

function calculateAverage (noteA, noteB) {
	const minValue = 6
	const success = 'Media alcançada'
	const noSuccess = 'Media não alcançada'
	const average = (noteA + noteB) / 2

	return (average >= minValue) ? success : noSuccess
}
  • Evite encher seu código de comentários que não sejam relevantes

Utilize os comentários a seu favor, como, por exemplo, para explicar regras de negócio, decisões e motivações que foram escolhidas para o contexto que determinada funcionalidade foi escrita.

Evitar:

 /*
	função que entra em contato com a API de conversões 
	de moeda.
	@params
	valor da moeda, pais
	@return
	valor da moeda convertido
*/
function currencyCoin(coin, country) {...}
  • Tente escrever funções menores, delegando a elas apenas uma tarefa, assim o código fica mais claro durante a leitura.

Evitar:

Neste primeiro exemplo é feita a separação de números pares e impares, assim como suas somas e multiplicações, o que pode tornar mais dificil a compreensão

function splitArrayNumbers (list) {
	let pairs = []
	let odd = []
	let pairSum = 0
	let oddMultiplication = 1
	
	for (let item of list) {
		if (num % 2 === 0) {
			pairs.push(num)
			pairSum += num
		} else {
			odd.push(num)
			oddMultiplication *= num
		}
	}
	
	return {
		pairs,
		odd,
		pairSum,
		oddMultiplication
	}
}

Fazer:

Para melhorar, podemos fazer um ajuste simples, separando em funções especificas para cada funcionalidade

function splitNumbers (list) {
	let pairs = []
	let odd = []
	
	for (let item of list) {
		if (item % 2 === 0) {
			pairs.push(item)
		} else {
			odd.push(item)
		}
	}
	
	return { pairs, odd }
}

function calculate (list) {
	let pairSum = 0
	let oddMultiplication = 1
	
	for (let item of list) {
		if (item % 2 === 0) {
			pairSum += item
		} else {
			oddMultiplication *= item
		}
	}
	
	return { pairSum, oddMultiplication }
}
  • Evite inserir parâmetros demais nas funções

Uma função idealmente deve receber no máximo 2 parâmetros, caso seja necessário passar mais, o ideal é fazer então com que essa função receba um objeto ou array como parâmetro, dependendo da funcionalidade.

Evitar

function calculateAverage ( note1, note2, note3, note4) {
	let average = (note1 + note2 + note3 + note4 ) / 4
	return average
}

const name = “Jhony Test”
const average = calculateAverage (8,10,6,4)

console.log(`A média do aluno ${name} é ${average}.`)

Fazer:

function calculateAverage ( notes) {
	let sum = 0
	for (let note of notes) {
		sum += note
	}
	
	let average = sum / notes.length
	return average
}

const name = “Jhony Test”
const notes = [8, 10, 6, 4]
const average = calculateAverage (notes)

console.log(`A média do aluno ${name} é ${average}.`)
  • Priorize passar valores padrão

Quando se está escrevendo uma função, tente priorizar a prática de passar valores padrão, isso evita que o código quebre caso algum dado esteja com o valor errado.

Neste exemplo, caso um dos valores não seja passado para a função, poderá ocorrer erros durante a execução:

function calculateTotalPrice (value, quantity, rate) {
	const priceWithoutRate = value * quantity
	const priceWithRate = priceWithoutRate + (priceWithoutRate * rate)
	return priceWithRate
}

Atribuindo valores padrão, mesmo que um dos parâmetros não seja passado, a função irá calcular com os valores padrões:

function calculateTotalPrice (value, quantity = 1, rate = 0.1) {
	const priceWithoutRate = value * quantity
	const priceWithRate = priceWithoutRate + (priceWithoutRate * rate)
	return priceWithRate
}

calculateTotalPrice(100); // Saída: 110
calculateTotalPrice(50, 2); // Saída: 110
calculateTotalPrice(50, 2, 0.2); // Saída: 120

Assim como ter um padrão para escrever as variáveis as funções se encaixam neste item, então padronize a escrita e as nomenclaturas de funções.

Evitar:

getuserData()
getProductRecord()
get_email_info()

Fazer:

getUserData()
getProductData()
getEmailInfoData()

Esses são alguns exemplos que podem te ajudar no começo dos seus estudo de Clean Code, mas lembre-se se não se prender somente a eles, pois temos uma variedade de possibilidades quando falamos dessa prática.

Conclusão

Agora já sabemos um pouco do conceito de código limpo, código sujo e seus malefícios. Além disso, conseguimos identificar alguns pontos para melhoria de código e algumas práticas para escrever códigos melhores.

Você pode se aprofundar ainda mais nesse tema lendo o livro Código limpo: Habilidades práticas do Agile Software, de  Robert C. Martin,  e praticando ao aplicar a teoria na prática.

E aí, curtiu o conteúdo?

Que tal dar uma nessa super aula do nosso educador Mayk Brito, que reúne 4 dicas para escrever código limpo em JavaScript:

Sugestões de leitura

Livro "Clean Code" de Robert Cecil Martin, disponível aqui.

Padrão do Airbnb, disponível aqui.

Artigo "O que é refatoração", disponível aqui.