Clean Code em C++: princípios e exemplos na prática
Todo desenvolvedor C++ mais cedo ou mais tarde enfrenta o problema de dar manutenção em código próprio ou de terceiros. Padrões complexos, funções sobrecarregadas e macros infinitas transformam o projeto em um pesadelo. O conceito de Clean Code (código limpo), popularizado por Robert Martin, oferece regras simples, mas eficazes, que tornam o código compreensível, seguro e fácil de modificar. Neste artigo, vamos analisar os princípios-chave do Clean Code aplicados ao C++ e mostrar como aplicá-los na prática.
1. Nomes de variáveis e funções: diga o que você faz
A primeira regra do código limpo é que o nome deve revelar a intenção do desenvolvedor. Em C++, isso é especialmente importante devido à abundância de ponteiros, referências e sobrecargas.
Exemplo ruim:
int d; // tempo decorrido em diasvoid f(int* a, int n); // ???Exemplo bom:
int daysSinceLastLogin;void processUserData(const std::vector<int>& userIds);Use palavras completas, evite variáveis de uma letra (exceto para índices em loops curtos). Para variáveis booleanas, use os prefixos is, has, should:
bool isValidInput;bool hasPermissions;Nomeie classes e estruturas com substantivos, e funções com verbos ou combinações verbais: class UserAccount, void calculateSalary().
2. Funções: pequenas, com uma única responsabilidade
Uma função deve fazer apenas uma coisa e fazê-la bem. O comprimento máximo é de 20 a 30 linhas. Se a função ocupar mais, divida-a em funções auxiliares.
Exemplo ruim (função monolítica):
void processOrder(Order& order) { // verificação de pagamento // atualização de estoque // envio de email // registro em log // geração de recibo}Exemplo bom (decomposição):
void processOrder(Order& order) { if (!validatePayment(order)) return; updateInventory(order); sendConfirmationEmail(order); logTransaction(order); generateReceipt(order);}Tente evitar efeitos colaterais. A função não deve alterar variáveis globais ou argumentos passados por referência sem indicação explícita no nome (resetData, fillBuffer).
3. Gerenciamento de memória e recursos: RAII e ponteiros inteligentes
C++ oferece controle total sobre a memória, mas isso leva a vazamentos. O Clean Code sugere usar a expressão idiomática RAII (Resource Acquisition Is Initialization) e ponteiros inteligentes em vez de new/delete brutos.
Exemplo ruim (gerenciamento manual):
void process() { int* data = new int[100]; // ... muito código ... if (error) { delete[] data; return; } delete[] data;}Exemplo bom (RAII):
void process() { std::unique_ptr<int[]> data = std::make_unique<int[]>(100); // ... código ... // delete é chamado automaticamente ao sair do escopo}Para propriedade compartilhada, use std::shared_ptr; para referências fracas, use std::weak_ptr. Nunca retorne ponteiros brutos para dados internos — use referências ou ponteiros inteligentes.
4. Tratamento de erros: exceções e códigos de retorno
Código limpo exige tratamento de erros explícito e previsível. Em C++, existem duas abordagens principais: exceções e códigos de retorno. Escolha um estilo dentro do projeto.
Exemplo ruim (ignorando erros):
int divide(int a, int b) { return a / b; // divisão por zero!}Exemplo bom (exceções):
int divide(i