Clean Code: Lições essenciais do terceiro capítulo
Tags: cleancode, programming, softwareengineering
Published: 2023-12-14 19:01:10

O capítulo 03 do livro “Código limpo” fala sobre como escrever boas funções. A principal questão é: como fazer uma função transmitir o seu propósito?

## 1. As funções devem ser pequenas

As funções devem ser pequenas. E elas devem ser menores do que você provavelmente está imaginando.
 
O livro diz que uma função deve ter no máximo 20 linhas, e que uma linha de código  — independentemente do que seja  — deve ter no máximo 150 caracteres. 

As funções devem ter os seus objetivos declarados de forma transparente. Devem contar a sua história e devem te levar a próxima ordem/instrução.

## 2. Máximo de 2 níveis de indentação

As funções não devem ter muitas estruturas aninhadas. Ou seja, if dentro de if, muitas condicionais, etc. O nível de indentação de uma função deve ser de no máximo 1 ou 2. Isso facilita a leitura e compreensão.

Além disso, blocos dentro de instruções como if, else, while, devem ter apenas 1 linha, possivelmente uma chamada para outra função.

```
If…
	if…
	else if…
else...
	if…
	else if…
	else..
		if…
```

Evite isso!

## 3. Faça apenas uma coisa

Eu julgo este o princípio mais importante. As funções devem fazer apenas uma única coisa. Devem fazê-la bem. Devem fazer apenas ela. É o princípio da responsabilidade única.

## 4. Mantenha um nível de abstração

A chave para entender se uma função está realmente fazendo "uma única coisa" está em olhar para o nível de abstração.

Quando dizemos que uma função deve fazer "uma coisa", estamos nos referindo a manter todas as suas ações dentro do mesmo nível de abstração. Isso significa que todos os passos ou operações dentro da função devem contribuir diretamente para realizar o propósito geral da função, como indicado pelo seu nome.

Você pode estar se perguntando: o que significa níveis de abstração?

Um "nível de abstração" refere-se à camada ou nível de detalhamento e complexidade de um código ou de uma parte do código.

* Alto nível de abstração: Isso é como olhar de um avião. Você vê a cidade, mas não as ruas individuais. Em termos de programação, é quando você lida com conceitos amplos e gerais, sem se preocupar com os detalhes específicos de implementação. Por exemplo, uma função chamada `processarPagamento()` pode ser uma operação de alto nível, pois você não precisa saber imediatamente como o pagamento é processado, apenas que ele será processado.
* Baixo Nível de Abstração: Isso é como estar na rua, vendo cada detalhe ao seu redor. Em programação, isso envolve lidar com os detalhes específicos e complexidades de uma tarefa. Continuando o exemplo anterior, em um nível mais baixo, `processarPagamento()` pode envolver validar os detalhes do cartão, comunicar-se com o banco, verificar o saldo, etc.

**Misturar níveis de abstração pode gerar confusão.**

## 5. Leia o código de cima para baixo: Regra decrescente

A regra decrescente diz que a leitura do código deve ocorrer de cima para baixo, como uma narrativa, uma série de parágrafos.

## 6. Use nomes descritivos

> Você sabe que está criando um código limpo quando cada rotina que você lê é como você esperava.

Metade do esforço para satisfazer esse princípio é escolher bons nomes para funções pequenas que fazem apenas uma coisa.

Quando menor e mais centralizada for sua função, mais fácil será pensar em um nome pra ela. E não tenha medo de criar nomes extensos. 

Um nome longo e descritivo é melhor do que um comentário extenso e descritivo.

Seja consistente nos nomes. Use as mesmas frases, substantivos e verbos.

## 7. Parâmetros de funções

A quantidade de parâmetros ideal para uma função é zero. Caso não consiga ser zero, deve ser um. Caso não consiga ser um, deve ser dois. Sempre que possível, evite três (ou mais) parâmetros. A utilização de muitos parâmetros complica a interpretação do código.

Parâmetros são difíceis de lidar em caso de teste também. Imagine a dificuldade em escrever um teste para uma função que requer três parâmetros. Precisamos escrever todos os casos de teste para certificar que todas as combinações de parâmetros funcionem adequadamente.

Além disso, não use parâmetros lógicos, ou seja, valores booleanos. Esse tipo de parâmetro complica a função, mostrando que ela faz mais de uma coisa. Ela faz uma coisa se for verdadeiro, e outra se for falso. Separe em duas funções.

Funções que recebem um único parâmetro são chamadas de mônades. Dois parâmetros, díades. Três parâmetros, tríades. 

## 8. Objetos como parâmetros

Quando uma função precisar de mais de dois ou três parâmetros, considere criar uma classe específica para eles. Exemplo:

```swift
func createPerson(name: String, age: String, job: String)
func createPerson(person: Person)
```

## 9. Verbos e palavras-chave

Escolher bons nomes para uma função pode contribuir muito para explicar a intenção da função e a ordem e intenção dos argumentos. A função e o argumento devem formar um par verbo/substantivo. Por exemplo: `write(name)` é bastante claro. Um nome será escrito. Um nome ainda melhor seria `writeField(name)`, que nos diz que nome é um campo.

## 10. Evite efeitos colaterais

Evitar efeitos colaterais significa garantir que uma função ou método não altere nenhum estado fora de seu escopo ou cause mudanças inesperadas no sistema na qual não estão propostas a fazer dentro do escopo da função. 

## 11. Separação comando-consulta

As funções devem fazer ou responder algo, mas não ambos. Sua função ou altera o estado de um objeto ou retorna informações sobre ele. Efetuar as duas tarefas normalmente gera confusão.

## 12. Prefira exceções a retorno de códigos de erro

Em vez de usar códigos de erro para sinalizar problemas ou falhas em uma função, você deve utilizar mecanismos de exceção. Assim, você obtém clareza do código, separação da lógica de erro da lógica de negócios e a prevenção de erros passando despercebidos.

Além disso, extraia blocos try/catch, pois eles já são um código extenso e devem possuir sua própria função, uma função exclusiva para tratamento de erro/sucesso. Uma função que trata erros não deve fazer mais nada. 

## 13. Evite repetição (DRY)

DRY significa don’t repeat yourself, que basicamente diz para evitar duplicidade de código. 

A duplicação é um problema porque ela incha o código e exigirá uma modificação dupla caso o algoritmo precise mudar. Também representa uma oportunidade dupla para um erro de omissão.

## Conclusão

> Programadores experientes veem os sistemas como histórias a serem contadas em vez de programas a serem escritos. 

Se seguir as regras descritas neste resumo, você terá funções mais curtas, bem nomeadas e organizadas. Lembre-se que seu objetivo verdadeiro é contar uma história.