DEV Community

Dário Prazeres
Dário Prazeres

Posted on

Como Refatorar Seu Código Com Muitos If-Else? Part 2

Como vimos no post anterior existem várias estrategias de refatorar o codigo quando ele tem muitos If-Else, só para relembrar:

1. Early return
2. Tabelas de decisão
3. Polimorfismo
4. Delegação de funções

Early Return

Early Return: é a abordagem que elimina as outras ramificações e concluído as decisões com retornos imediatos, mesmo se tais condições forem falsas. Como podemos ver:

public class CalculadoraDesconto
{
    public decimal CalculoDesconto(Cliente cliente, Pedido pedido)
    {
        if (cliente.IsPremium)
        {
            return pedido.QuantiaTotal > 100 ? pedido.QuantiaTotal * 0.1m : pedido.QuantiaTotal * 0.05m;
        }
        else
        {
            return pedido.QuantiaTotal > 200 ? pedido.QuantiaTotal * 0.15m : pedido.QuantiaTotal * 0.1m;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Acima temos uma função com a capacidade de fazer um retorno rápido usando operador ternário, agora veremos o cálculo da Complexidade Ciclomática:

Analise: temos 3 pontos de decisão:

  • if (cliente.IsPremium) (1 decisão),
  • pedido.QuantiaTotal > 100 (dentro do primeiro if),
  • pedido.QuantiaTotal > 200 (dentro do else).

Cálculo:
N = 3
E = 6
P = 1
M = E - N + 2P
M = 6 - (3) + 2(1) = 5

Tabelas de Decisão

Tabelas de decisão é uma técnica usada para simplificar a lógica condicional em código, especialmente quando se tem muitos if-else. Elas ajudam a mapear entradas para saídas, eliminando a necessidade de escrever várias condições aninhadas.

public class CalculadoraDesconto
{
    public decimal CalculoDesconto(Cliente cliente, Pedido pedido)
    {
        decimal descontoPercentual = ObterDescontoPercentual(cliente.IsPremium, pedido.QuantiaTotal);
        return pedido.QuantiaTotal * descontoPercentual;
    }

    private decimal ObterDescontoPercentual(bool isPremium, decimal quantiaTotal)
    {
        if (isPremium)
        {
            return quantiaTotal > 100 ? 0.1m : 0.05m;
        }
        else
        {
            return quantiaTotal > 200 ? 0.15m : 0.1m;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Como vimos no código acima, repartiu-se as funções isso para que só depois se fizesse o calculo e não sou acabou por usar a abordagem Early Return na segunda função, o que esteticamente melhorou mas a sua complexidade ciclomática continua a mesma como podemos ver:

Analise: temos 3 pontos de decisão:

  • if (cliente.IsPremium) (1 decisão),
  • pedido.QuantiaTotal > 100 (dentro do primeiro if),
  • pedido.QuantiaTotal > 200 (dentro do else).

Cálculo:
N = 3
E = 6
P = 1
M = E - N + 2P
M = 6 - (3) + 2(1) = 5

Polimorfismo

O polimorfismo é um dos pilares da programação orientada a objetos que permite que diferentes classes respondam de maneiras distintas a uma mesma mensagem (método). Ele possibilita que métodos de mesmo nome, em diferentes classes, tenham comportamentos variados, sem que o código cliente precise saber das diferenças.

Para termos mais detalhes de como funciona veja o exemplo abaixo:

public abstract class Cliente
{
    public abstract decimal CalcularDesconto(Pedido pedido);
}

public class ClientePremium : Cliente
{
    public override decimal CalcularDesconto(Pedido pedido)
    {
        return pedido.QuantiaTotal > 100 ? pedido.QuantiaTotal * 0.1m : pedido.QuantiaTotal * 0.05m;
    }
}

public class ClienteNormal : Cliente
{
    public override decimal CalcularDesconto(Pedido pedido)
    {
        return pedido.QuantiaTotal > 200 ? pedido.QuantiaTotal * 0.15m : pedido.QuantiaTotal * 0.1m;
    }
}
Enter fullscreen mode Exit fullscreen mode

Como vimos criou-se uma classe abstrata chamada Cliente que tem um método chamado CalcularDesconto este método é subscrito nas outras duas funções ClientePremium e ClienteNormal. Esta abordagem permitem fazer cálculos de forma independente e sem condições aninhadas.

Analise: temos 3 pontos de decisão:

  • Na classe ClientePremium: pedido.QuantiaTotal > 100 (1 decisão),
  • Na classeClienteNormal: pedido.QuantiaTotal > 200 (1 decisão).

Cálculo:
N = 1
E = 2
P = 1
M = E - N + 2P
M = 2 - (1) + 2(1) = 3

Esta abordagem requer mais organização por outro lado esta abordagem é mais propensa a escalabilidade. Sem falar que a Complexidade ciclomática é muito inferior que as duas anteriores.

Funções Delegadas

Funções Delegadas (ou simplesmente Delegates) é um conceito de programação que permite tratar métodos como objetos. Em linguagens como C#, um delegate é uma referência a um método e pode ser passado como argumento para outras funções, armazenado em variáveis ou retornado de funções, tornando o código mais flexível e modular.

public class CalculadoraDesconto
{
    private Func<Pedido, decimal> ObterCalculoDesconto(Cliente cliente)
    {
        if (cliente.IsPremium)
        {
            return pedido => pedido.QuantiaTotal > 100 ? pedido.QuantiaTotal * 0.1m : pedido.QuantiaTotal * 0.05m;
        }
        else
        {
            return pedido => pedido.QuantiaTotal > 200 ? pedido.QuantiaTotal * 0.15m : pedido.QuantiaTotal * 0.1m;
        }
    }

    public decimal CalculoDesconto(Cliente cliente, Pedido pedido)
    {
        var calcularDesconto = ObterCalculoDesconto(cliente);
        return calcularDesconto(pedido);
    }
}
Enter fullscreen mode Exit fullscreen mode

Analise: temos 3 pontos de decisão:

  • if (cliente.IsPremium) (1 decisão),
  • Dentro do retorno da função delegada, há outra decisão para pedido.QuantiaTotal.

Cálculo:
N = 2
E = 4
P = 1
M = E - N + 2P
M = 4 - (2) + 2(1) = 4

Conclusão

Algumas das complexidades ciclomáticas tiveram valores diferentes, umas iguais ao if-else aninhado e outras muito inferiores, não é regra mais isso dependerá muito do exercício que estas criar e levarás em conta a melhor abordagem.

Podemos ver que a complexidade ciclomatíca ajuda muito analisar as abordagens e hoje já existem softwares que verificam esta complexidade. Como programador será difícil as vezes de verificar se este é a melhor forma de fazer, mas convenhamos de que códigos com muitos If-elses não são agradáveis de se ver por mais que esta a funcionar e que quando iremos refatorar será como pisar em ovos. Treine até o ponto de teres olho clinico de analisar a melhor via para ti e para os que poderão mexer nesse código.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay