Clean Code: Por um mundo com código melhores

Thiago Barradas
thiagobarradas
Published in
5 min readMay 10, 2018
Daqui pra frente, vamos ter orgulho do nosso código?

Como desenvolvedores temos basicamente os mesmos desejos relativos aos nossos códigos. Elaboramos cada linha pensando em ter um resultado que funcione muito bem, praticamente sem bugs e atendendo a todo escopo/negócio. Desejamos também que o código esteja extremamente elegante, bem estruturado, fácil para novas implementações e modificações, aquele código que nos proporcione orgulho na hora de mostrar aos colegas do trabalho ou disponibilizar na comunidade. Por último, temos o desejo mais difícil de todos: fazer tudo isso dentro do prazo programado.

Por isso, muitas vezes ouvimos frases como:

“Fiz o meu melhor dentro do tempo que eu tinha”
“Mas o prazo era extremamente curto”
“Meu gestor me faz pressão o tempo inteiro”
“Preciso entregar, preciso ser muito produtivo”

Quando ouvimos essas frases, sem dúvidas, temos um profissional que não se orgulha do que foi feito. O código provavelmente está feio e desprovido de manutenção. Em muitos casos, ao analisar o código, outros desenvolvedores irão preferir iniciar outro projeto do zero do que se arriscar nesse código poluído.

Clean Code: Por um mundo melhor

Este artigo tem como objetivo colaborar para um mundo melhor. Um mundo onde as pessoas se importem de verdade com o código que está sendo desenvolvido. O código que provavelmente necessitará de novas implementações ou ajustes, e tal tarefa, será fácil. Um código que gere orgulho. Por isso reuni os principais conceitos do Clean Code, uma forma de codificar projetada para facilitar a escrita, a leitura e a manutenção do código.

Esses conceitos foram extraídos do livro Clean Code: A Handbook of Agile Software Craftsmanship, de Robert C. Martin (aproveite a indicação).

Nomenclatura

Podemos considerar que o nome de variáveis, classes, métodos ou parâmetros seja um dos pontos mais importantes para um código legível e organizado. Escolha bem os nomes. Não importa se o nome for grande. O mais importante é expressar o que aquele elemento realmente representa.

Original

int txI;
repo.Get();

Clean Code

int transactionInstallments;
transactionRepository.GetTransactions();

Classes

Devem ser representadas por substantivos e seu nome deve ser claro ao seu contexto.

Original

public class Cut 
{
//...
}
public class CustomerDTO
{
//...
}

Clean Code

public class Cutter 
{
//...
}
public class CustomerRepository
{
//...
}

Métodos

  • Devem ser representados por verbos e seu nome deve ser claro ao seu objetivo.
  • Devem ser pequenos. Quanto menor, melhor.
  • Extraia sempre que puder em métodos auxiliares, seja um método privado ou utilitários.
  • Um método deve fazer apenas uma coisa. Uma.
  • Muitos parâmetros devem ser substituídos por objetos.
  • Argumentos booleanos não costumam ser elegantes.

Original

public void New(string name, string email, int age)
{
var repo = new UserDTO();
var u = repo.Get(email);
if (u == null)
{
//...
}
}
public List<Transaction> GetTransactions(bool isAuthorized)
{
//...
}

Clean Code

public void RegisterUser(User user)
{
if (IsEmailAvailable(user.Email))
{
//...
}
}
public List<Transaction> GetAuthorizedTransactions()
{
//...
}
public List<Transaction> GetNotAuthorizedTransactions()
{
//...
}

Condições

Sempre que possível, extraia condições para métodos privados.

Original

if (transaction.Status == "Authorized" || transaction.Status == "Captured")
{
//...
}

Clean Code

if (IsEligibleForCancellation(transaction))
{
//...
}
private bool IsEligibleForCancellation(Transaction transaction)
{
return (transaction.Status == TransacationStatusEnum.Authorized ||
transaction.Status == TransacationStatusEnum.Captured);
}

Objetos e Estruturas de Dados

Basicamente devem seguir a Lei de Demeter:
Um método M de uma classe C só deve conhecer:

  • Métodos de C;
  • Objetos criados por M;
  • objetos passados por parâmetro para M;
  • Objetos em propriedades de instâncias de C.

Abstração

Tente ao máximo generalizar suas classes, abstraia em quantos níveis for preciso e flexibilize futuras modificações:

Original

public class CreditCardTransaction 
{
public long AmountInCents { get; set; }
//...
}
public class OnlineDebitTransaction
{
public long AmountInCents { get; set; }
//...
}

Clean Code

public abstract class Transaction
{
public long AmountInCents { get; set; }
}
public class CreditCardTransaction : Transaction
{
//...
}
public class OnlineDebitTransaction : Transaction
{
//...
}

Comentários

Um código bem escrito dispensa comentários. A leitura do código deve ser como uma história ditada pela forma que ele foi escrito e suas nomenclaturas. Comentários não servem para melhorar um código ruim. Comentários são aceitáveis quando há necessidade de explicação do negócio, licença de uso, documentação, entre outros pequenos e exclusivos casos.

Original

// check if gateway is MundiPagg
if (gateway == "MundiPagg")
{
transaction.Retry();
}

Clean Code

// MundiPagg is the only gateway that retries a transaction
if (gateway == "MundiPagg")
{
transaction.Retry();
}

Formatação do Código

Não existe um padrão para formatação. O que vale é o bom senso e principalmente a regra do time. Se existir um padrão, não ignore. A escrita padronizada facilita a leitura. Então, se o time definir que constantes são escritas sempre em maiúsculo, faça assim. Se o time definir que variáveis de escopo limitado iniciam com letra minúscula, siga a regra.

Exceções

Utilize exceções específicas para seus erros. Evite (leia-se: não utilize) códigos de erro. Trate exceções exclusivamente em métodos (o método basicamente deve servir para tratar a exceção).

Original

TransactionResult result = GetTransaction(transactionId);
if (result.Success == false && result.Error == Error.NOT_FOUND)
{
//...
}
return result.Transaction;

Clean Code

try 
{
return GetTransaction(transactionId);
}
catch (NotFoundException ex)
{
//...
}
catch (Exception ex)
{
//...
}

Testes

Apesar de muita gente ter dificuldade, tentar seguir o TDD sempre é o melhor caminho. Projetando primeiramente o comportamento esperado da aplicação em testes para posteriormente implementa-los, os métodos tendem a ser mais objetivos na resolução dos problemas, logo, a sua leitura e escrita ficam mais fáceis.

No escopo dos testes, siga tudo que já foi visto até aqui. Podemos seguir também a regra do “F.I.R.S.T.”:

  • Fast: Testes rápidos, resultados rápidos. Podem ser executados diversas vezes;
  • Indepedent: Não deve ter dependências. Lembre-se que o nome é teste unitário pois testa uma unidade isolada da aplicação. Dependências podem gerar resultados falso-positivos;
  • Repeatable: Os testes devem funcionar na sua máquina, no servidor de homologação, produção, em qualquer ambiente;
  • Self-validation: Não é necessária nenhuma validação manual para garantir que o teste passou;
  • Timely: Os testes devem ser elaborados antes do código a ser testado (TDD). Caso contrário o código pode ter sua complexidade elevada, dificultando ou impossibilitando o teste.

Regra do Escoteiro

De acordo com os escoteiros, após um acampamento devemos seguir a seguinte regra:

“Deixe a área do acampamento mais limpa do que quando e como você a encontrou.”

Podemos traduzir e levar essa regra para o nosso cotidiano:

“Deixe o código mais limpo do que quando e como você o encontrou.”

É isso!

Como desenvolvedores sabemos as dificuldades de manter a qualidade de um projeto equilibrando principalmente com o cronograma (apertado na maioria das vezes). Porém, com alguns padrões somados com boas práticas, nossas chances aumentam muito.

Tenha muito orgulho do seu código e mostre que você se importa com o que está fazendo. Um bom código gera boas soluções para sua empresa e reconhecimento profissional. Códigos ruins destroem carreiras e até mesmo podem decretar o fim de uma empresa.

Espero que seu desempenho codificando possa melhorar após este artigo, afinal, o objetivo dele é justamente esse, fazer do mundo um lugar melhor para os devs e para os códigos.

--

--

Thiago Barradas
thiagobarradas

Microsoft MVP, Elastic Contributor. Entusiasta de novas tecnologias e arquiteto de software na Stone. Cultuador do hábito de formar cabeças pensantes.