Além do código limpo (clean code) — sacadas para escrever códigos simples

Marcio Jalber
Nov 2 · 6 min read

Se você trabalha com criação de software ou com gestão de equipes de desenvolvimento, você sabe do que estou falando. O cliente de software é um ser humano normal investido de uma capacidade estranha de pedir coisas complexas.

Por vezes, recebemos a missão de desenvolver um produto cujas regras de negócio são um emaranhado obscuro de caminhos ambíguos. Quantas vezes esses desafios já te custaram horas de trabalho e a sensação de que não será possível concluir com êxito.

Mas depois de dizer sim a muitos desafios que eu, no meu íntimo, titubeava comigo mesmo “você está louco? Isso não dá pra ser feito!”, conclui que você pega o jeito e aprende alguns princípios.

Quero compartilhar aqui alguns princípios que aprendi para criação de classes.

Primeiro escreva o roteiro

Quando for criar uma classe, SEMPRE utilize o padrão de projeto FACHADA ( https://code.tutsplus.com/pt/tutorials/design-patterns-the-facade-pattern--cms-22238).

A atividade se torna muito mais simples quando você deixa claro todos os procedimentos necessários que serão realizados antes de começar a codificar.

Por exemplo, imagine que você irá escrever uma classe para cadastrar uma nova pessoa. Em vez de sair codificando, escreva primeiro o roteiro de execução dessa tarefa. Veja como fica mais simples implementar e manter:

<?phpnamespace App\Domain\Pessoas\Cadastrar;/**
* Classe para cadastro de uma pessoa.
*/
class Feature
{
/**
* Implementa a funcionalidade.
*/
public function execute()
{
$this->validarDados();
$this->checarSeEmailJaCadastrado();
$this->cadastrarPessoa();
$this->enviarEmailConfirmacao();
return [ 'pessoa' => $this->pessoa->values() ];
}
/**
* Valida os dados informados no formulário.
*/
protected function validarDados()
{
}
/**
* Checa se já existe uma pessoa cadastrada com o e-mail.
*/
protected function checarSeEmailJaCadastrado()
{
}
/**
* Efetiva o cadastro da pessoa
*/
protected function cadastrarPessoa()
{
}
/**
* Envia e-mail de confirmação para a caixa de e-mail da pessoa.
*/
protected function enviarEmailConfirmacao()
{
}

/**
* Valida os dados informados no formulário.
*/
protected function validarDados()
{
}
}

Expressões condicionais dentro de variáveis

Não precisamos ficar lendo todo o código para entender como ele funciona ou ficar poluindo com comentários para explicar expressões condicionais complexas. Podemos criar variáveis para facilitar essa atividade.

Veja o exemplo abaixo:

<?phpnamespace App\Domain\Conta;/**
* Classe para cadastro de uma pessoa.
*/
class ContaCorrente extends ContaBancaria
{
/**
* Implementa a funcionalidade de sacar dinheiro no caixa eletrônico.
*/
public function sacar( $valor )
{
$saldo_conta = $this->consultarSaldoConta();
$limite_saque = $this->valorDisponivelSaque();
$saldo_maquina = $this->consultarSaldoMaquina();
$saldo_suficiente = $saldo >= $valor;
$limite_saque_diario = $limite_saque >= $valor;
$maquina_possui_valor = $this->valorDisponivelMaquina() >= $valor;
if ( !$saldo_suficiente )
{
$msg = "Seu saldo é insuficiente. Valor solicitado: {$valor}. Saldo: {$saldo}.";
throw new \Exception( $msg );
}
if ( !$limite_saque_diario )
{
$msg = "O valor solicitado ultrapassa o limite disponível para saque diário: {$limite_saque}.";
throw new \Exception( $msg );
}
if ( !$maquina_possui_valor )
{
$msg = "Desculpe, mas a maquina não possui o valor suficiente para realizar o saque.";
throw new \Exception( $msg );
}
return $this->efetivarSaque();
}
}

Expressões if/switch x arrays

Podemos simplificar bastante nossos códigos reduzindo o uso de expressões if/case sequencias quando os valores a serem comparados são fixos e pré-conhecidos.

Veja uma função escrita com IFs:

<?phpfunction validarCategoria( $categoria ) {
if ( $categoria == 'pessoal' ) {
return 'Pessoal';
}
if ( $categoria == 'profissional' ) {
return 'profissional';
}
if ( $categoria == 'hoobies' ) {
return 'Hobbies';
}
if ( $categoria == 'financas' ) {
return 'Finanças';
}
if ( $categoria == 'outras' ) {
return 'Outras categorias';
}
return null;
}

Agora a mesma função utilizando switch:

<?phpfunction validarCategoria( $categoria ) {
switch ( $categoria ) {
case 'pessoal':
return 'Pessoal';
case 'profissional':
return 'profissional';
case 'hoobies':
return 'Hobbies';
case 'financas':
return 'Finanças';
case 'outras':
return 'Outras categorias';
default:
return null;
}
}

Nos dois casos acima, percebe-se que a manutenção do código será cansativa, tendo que navegar em linhas intercaladas. Agora, veja o mesmo código escrito com arrays:

<?phpfunction validarCategoria( $categoria ) {
$categorias = [
'pessoal' => 'Pessoal',
'profissional' => 'Profissional',
'hoobies' => 'Hobbies',
'financas' => 'Finanças',
'outras' => 'Outras categorias',
];
return $categorias[ $categoria ] ?? null;
}

Evitar chamadas recursivas

Uma classe com chamadas recursivas te obriga a ler todo o código para você entender o funcionamento. E, se você não tiver a sacada de desenhar um fluxograma logo no início, pode acabar perdendo tempo lendo o mesmo código várias vezes para se memorizar com seu fluxo.

Veja como na classe abaixo você é obrigado a navegar até a última linha para saber o que está acontecendo.

<?phpnamespace App\Domain\SupermercadoX;/**
* Classe para adicionar um produto nas compras de um cliente.
*/
class Caixa
{
/**
* Implementa a funcionalidade.
*/
public function cadastrar()
{
$this->procedimentoA();
$this->procedimentoB();
$this->procedimentoC();
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA()
{
// Algum codigo
$this->procedimentoA1();
$this->procedimentoA2();
$this->procedimentoA3();
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA1()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA2()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoB()
{
// Algum código
$this->procedimentoC();
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoC()
{
// Algum código

$this->procedimentoD();
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoD()
{
// Algum código
}
}

Agora perceba a diferença, quando você não possui chamadas recursivas:

<?phpnamespace App\Domain\SupermercadoX;/**
* Classe para adicionar um produto nas compras de um cliente.
*/
class Caixa
{
/**
* Implementa a funcionalidade.
*/
public function cadastrar()
{
$this->procedimentoA();
$this->procedimentoA1();
$this->procedimentoA2();
$this->procedimentoA3();
$this->procedimentoB();
$this->procedimentoC();
$this->procedimentoD();
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA1()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoA2()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoB()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoC()
{
// Algum código
}
/**
* Implementa a funcionalidade.
*/
public function procedimentoD()
{
// Algum código
}
}

Cada regra de negócio em uma classe separada

Quando escrevemos uma classe, pensamos que todas as classes devem ter mais de um método para justificar sua existência; assim, algumas classes ficam muito extensas e devem ser lidas obrigatoriamente para verificar se todas as regras de negócio foram implementadas.

<?phpnamespace App\Domain\EmprestimoFinanciamentos;/**
* Classe para adicionar um produto nas compras de um cliente.
*/
class Emprestimo
{
/**
* Implementa a funcionalidade.
*/
public function conceder()
{
$this->avaliarHistoricoCliente();
$this->avaliarPatrimonioAtualCliente();
$this->prospectarCapacidadeClientePagarEmprestimo();

$this->executarProcedimento1();
$this->executarProcedimento2();
$this->executarProcedimento3();
$this->concluirOperacao();
}
}

Uma sacada simples para deixar a classe principal mais simples e as regras de negócio mais fácil de serem encontradas (inclusive ver se já foram implementadas), é criar uma classe específica para cada regra de negócio, deixando na classe apenas os métodos da implementação técnica do código.

Veja como ficaria seu a árvore de arquivos do seu projeto:

Estrutura de arquivos do projeto

E sua classe mais limpa:

<?phpnamespace App\Domain\EmprestimoFinanciamentos;/**
* Classe para adicionar um produto nas compras de um cliente.
*/
class Emprestimo
{
/**
* Implementa a funcionalidade.
*/
public function conceder()
{
$this->avaliarHistoricoCliente();
$this->avaliarPatrimonioAtualCliente();
$this->prospectarCapacidadeClientePagarEmprestimo();

$this->executarProcedimento1();
$this->executarProcedimento2();
$this->executarProcedimento3();
$this->concluirOperacao();
}
}

Conclusão

O clean code não precisa acabar onde os livros terminam. Experimente você mesmo fazer suas descobertas e construir códigos cada vez mais simples.

    Marcio Jalber

    Written by

    Especialista em sistemas corporativos de alta complexidade, com foco na Experiência de Usuário e arquitetura de software

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade