Entenda o porque você deveria evitar o else em seu código
Inicialmente parece quase desnecessário pensar em evitar usar o else, uma vez que ele geralmente está muito presente em nosso código. Mas vamos comigo que eu te explico o porquê dessa pequena alteração no seu code style pode impactar de uma forma interessante o resultado do seu código.
Quebra de paradigma
Em primeiro lugar preciso rapidamente comentar sobre a quebra de paradigma que essa pequena alteração na sua rotina de código pode te trazer.
Uma quebra de paradigma geralmente é uma chance para sairmos da nossa zona de conforto, uma oportunidade de começarmos a fazer algo rotineiro de uma forma completamente diferente e ocasionalmente melhor.
Então, antes de entrar na parte técnica da coisa, imagina ver seu código e ponderar: Cara, como eu posso fazer isso sem usar else?
Garanto que só essa pequena argumentação interna vai te auxiliar, não só para reescrever aquele código sem else
, mas vai te valer como um belo exemplo que podemos sempre melhorar o nosso trabalho.
Agora sim, vamos falar de código…
Menos código
Quanto menos código escrevemos, menos código nós e nossos colegas precisamos revisar, certo?
— Aaaah Real… mais agora você vai me dizer que só de deixar de usar
else
vou escrever menos código?
Sim, exatamente isso. Parece simples demais, e é… você vai de fato codar menos ao deixar de usar o else
. Vamos ver o primeiro exemplo:
public function isPositive($amount)
{
if($amount > 0) {
$result = true;
} else {
$result = false;
}
return $result;
}
Agora vamos ver sem o else
:
public function isPositive($amount)
{
if($amount > 0) {
return true;
}
return false;
}
Bom… Esse pequeno exemplo parece safe o suficiente para começar.
Se for pensar em quantidade absoluta de linha desse primeiro exemplo, claro que a diferença parece pequena. Mas podemos notar que o trecho sem else
fica muito mais clean
que o primeiro.
Agora imagina um trecho de código com várias condições… vamos ver no tópico seguir como fica?
Menos complexo
Existe uma métrica chamada complexidade ciclomática
que calcula o quão complexo está seu método (um dia escrevo sobre ela e posto por aqui). Essa complexibilidade é determinada pela quantidade de pontos de decisão do método analisado. São os pontos de decisão: if
, while
, for
e case
. A ideia dessa métrica é medir a quantidade de caminho que o software pode seguir.
Ok… mas por que estamos falando sobre isso?
Porque quanto mais else's
, mais complexo o código... pegou?
Vamos ver como exemplo um método que verifica de forma simples a disponibilidade de acesso de um usuário dado seu status de ativação e o horário limite de uso da aplicação:
if ($user) {
if (date('H') > 22) {
if ($user->active) {
$hasAccess = true;
} else {
$hasAccess = false;
}
} else {
$hasAccess = false;
}
} else {
$hasAccess = false;
}
Sem else
…
$hasAccess = true;
if (!$user && !$user?->active) {
$hasAccess = false;
}
if (date('H') > 22) {
$hasAccess = false;
}
Fala verdade dev, ficou muito mais fácil de entender esse exemplo refatorado sem o else
... notou a quantidade de código a menos?
E nem me refiro apenas ao total de linhas de código, mas também a eliminação do efeito hadouken no código:
O ponto óbvio que preciso mencionar é que um código menos complexo facilita sua compreensão, logo uma revisão de código e futura manutenção passa a ser uma tarefa muito mais simples.
Outro ponto a se comentar nesse tópico é a respeito de testes unitários
, quanto menos if-elses
tivermos, menor a complexidade do código e logo, menos testes unitários distintos para o mesmo trecho de código precisamos fazer, pois assim teremos menos caminhos possíveis.
Um código mais "SOLID"
O fato de você abandonar o uso excessivo do else
pode te dar mais visão para um uso mais assertivo dos princípios do SOLID, principalmente do princípio de responsabilidade única.
Imagina uma classe onde você recebe os dados de uma transação financeira que aceita 3 principais tipos de pagamento diferentes: boleto
, crédito
ou pix
. Nessa classe você precisa calcular a taxa desse serviço de acordo com o tipo de pagamento, sendo cartão um valor percentual e os demais um valor fixo, e retornar o valor total deduzindo a taxa cobrada.
Podemos fazer de diversas formas certo? Utilizando if-else
, ou o bom e velho switch/case
, e também com match
a partir do PHP v8.0.
Para o exemplo, vamos considerar:
Crédito: 5%
Boleto: R$2,50
Pix: R$0
Outros meios: R$3,75
class Transaction
{
public function calculateFee($transaction)
{
if ($transaction->method == 'credit') {
$fee = $transaction->amount * 0.05;
} elseif ($transaction->method == 'boleto') {
$fee = 2.5;
} elseif ($transaction->method == 'pix') {
$fee = 0;
} else {
$fee = 3.75;
}
return [
'fee' => $fee,
'total' => $transaction->amount - $fee,
];
}
}
Agora vamos aplicar um pouco de SOLID
e remover os if-else's
. Dessa vez a quantidade toda de linhas não vai ficar exatamente menor, mas vai ficar bem mais interessante:
class Transaction
{
public function calculateFee($transaction)
{
$method = $this->getMethod($transaction->method);
return [
'fee' => $this->$method($transaction->amount),
'total' => $this->calcTotal($transaction->amount, $fee),
];
}
protected function getMethod($method)
{
if (method_exists($this, $method)) {
return $method;
}
return 'any';
}
protected function credit($amount)
{
return $amount * 0.5;
}
protected function boleto($amount)
{
return 2.5;
}
protected function pix($amount)
{
return 0;
}
protected function any($amount)
{
return 3.5;
}
protected function calcTotal($amount, $fee)
{
return $amount - $fee;
}
}
Eu tenho bastantes pontos relevantes para comentar sobre esse exemplo, porém vou manter o foco no uso do else
e em um outro artigo falo mais sobre o SOLID
, beleza?
Note que a classe, por mais que tenha ficado um pouco mais extensa que o exemplo com else
, ela ficou muito simplificada e fácil de editar qualquer regra de negócio quando precisarmos.
Imagina se além da taxa principal, seria necessário calcular uma nova taxa e/os juros se o pagamento for crédito, ou se apenas adicionássemos mais 3 tipos de pagamentos, com poucas novas linhas resolve e com um maior nível de segurança pois não será necessário alterar métodos já existentes.
Se o nosso exemplo não fosse de pagamento e sim um CRUD
, quantos if-else
ele poderia ter para validar todos os dados? O código vira uma bagunça, linhas extensas e confusas... ao separar tudo, você tem cada trecho de código com sua exata responsabilidade (S do SOLID), tornando mais fluido o fluxo de desenvolvimento e diminuindo drasticamente as horas de debug
, pois é muito mais fácil identificar um método falho entre 100 outros do que uma linha entre 100 outras.
Precisão
Note que em todos os exemplos de refatoração sem else
, acabamos criando a variável antes mesmo do if? Esse é um comportamento de boa prática de código pois pode evitar bugs, pois se errarmos em nossa condicional, a variável com um valor default já existe.
Imagina o exemplo do pagamento, porém dessa vez precisamos calcular os juros além da taxa, e em um dos elseif
acabamos esquecendo de adicionar a variável com o cálculo. Na menor das hipóteses teremos um erro de PHP Notice: Undefined variable
, e na pior das hipóteses estaríamos deixando de cobrar os juros do pagamento.
Agora imagina se uma variável passa em branco em um método de autenticação e acabamos por dar acesso irrestrito a um usuário nocivo.
E mesmo que o time tem uma boa cultura de revisão de código e um QA exclusivo para testar todos os PRs, vale a pena fazer nosso código o mais assertivo quanto conseguirmos.
Performance
Até agora muito falei sobre estilo de código e nada falei sobre performance, pois não há diferença significante em performance de máquina entre ambos os estilos de código. Vale ressaltar que o foco nesse assunto é apenas a performance humana, de acordo com os tópicos que vimos acima.
Usar else
ou não usar, eis a questão!
Obviamente que não estou falando de eliminar o else
do seu fluxo de trabalho para sempre, mas deixo aqui o desafio de utilizá-lo o menos possível.
Para finalizar, acredito que vale a pena enfatizar que tudo que compartilhei nesse artigo são opiniões pessoais baseados em anos de experiência, e entendo que nós devs tendemos a ter fortes preferências pessoais quando se trata de estilos de código, então fique a vontade para discordar e comentar a respeito.
E aí dev? Depois de tudo que falamos até aqui, qual a sua opinião? Se já utiliza essa prática, ou se resolver segui-la, conte aí o que achou, beleza?
Valeu e até a próxima 🖖