Removendo excesso de if’s e cases

54w5g4

Introdução

Normalmente durante a execução de algum algoritmo, precisamos verificar algumas condições para poder desviar o fluxo do programa para atender determinadas condições, para isso usamos o if para poder seguir um novo fluxo, ou quando esperamos determinados valores usamos o switch para executar determinada clausula case. Até aí não existe nenhum problema, mas quando surge a necessidade de adicionar um novo if/case quando se há um novo valor esperado, isso aumenta o número de if/case utilizado resultando em um algoritmo difícil de ler devido à quantidade de fluxos que o programa pode tomar durante sua execução, em qualidade de código isso gera um problema de complexidade ciclomática, sendo a quantidade de caminhos um programa pode seguir.

Nesse artigo é demonstrado como reduzir a quantidade de if’s/cases do algoritmo assim separando de forma organizada o processamento em função da entrada fornecida. Para demonstrar, implementaremos uma calculadora aritmética simples, onde com dois números podemos realizar as operações básicas.

Implementação usando if

Nessa primeira versão usaremos o if para realizar a seleção das operações

Nessa primeira versão podemos notar o seguinte, para cada operação precisamos adicionar um novo if e verificar se o simbolo corresponde à entrada, caso sim realizamos o processamento. Agora vamos adicionar uma nova operação por exemplo exponenciação, então adicionamos um novo if, assim fica da seguinte forma:

Podemos notar que o algoritmo começa a ficar maior, e devido à isso começamos a não ter a visão de toda a implementação, nos fazendo rolar a barra lateral para poder ver todo o algoritmo. Imagine se houver 10 ou 50 if’s, o entendimento desse algoritmo fica comprometido devido a extensão do arquivo, porque passaremos mais tempo usando o mouse do que lendo e entendendo o algoritmo ali implementado.

Implementação usando switch case

Nessa segunda versão usaremos o switch case para realizar a seleção das operações

Nessa segunda versão notamos uma melhora em relação ao tamanho da primeira versão, o algoritmo está mais agradável de ser lido, porém exercitemos o mesmo exemplo da primeira versão, adicionaremos a exponenciação, ou seja, devemos adicionar mais uma cláusula case para isso ficando da seguinte forma:

Apesar de o algoritmo estar mais agradável para se ler, já começamos a necessitar rolar para termos o total entendimento, resultando assim novamente em gastar mais tempo manipulando o mouse do que de fato entendendo o algoritmo ali implementado. Mas como implementar um algoritmo sem tantos if’s ou cases? Bom responderemos no próximo tópico.

Absorvendo if’s e cases

Para implementar um algoritmo com poucos if’s e cases, precisamos utilizar o recurso de mapeamento, onde através de uma estrutura contendo um atributo que é responsável por mapear o simbolo no qual será comparado, e um callback que será executado quando o simbolo de entrada corresponder ao simbolo comparado, vejamos isso na prática.

Para que possamos realizar tal mapeamento precisamos definir uma callback, que não devolve nada e que recebe dois argumentos do tipo double, argumentos esses utilizados para realizar o cálculo com a operação realizada.

E também precisamos definir a estrutura que irá corresponder ao mapeamento que será realizado, ficando da seguinte forma

Com a definição do callback é possível implementar as funções que realizarão as operações, sendo:

Com as funções definidas podemos iniciar o mapeamento, para cada operação temos agora uma função responsável por executar essa operação, assim criamos um array da estrutura DoMath

Para processar esse mapeamento, precisamos saber a quantidade de itens que esse array possui então calculamos da seguinte forma:

E a rotina do processamento propriamente dito, usamos um for, que carinhosamente apelidei de for primordial, onde somente ele é capaz de processar todo o mapeamento independente que quantos itens possa ter.

Assim se a operação selecionada corresponder à algum item do array o if será verdadeiro e executará o callback à ele associado, a listagem completa vem a seguir

Para completarmos vamos adicionar a exponenciação, assim como foi feito nos exemplos anteriores

Adicionamos na tabela e voilá, nada muda.

A listagem completa com a exponenciação

Conclusão

O uso de switch case e de if’s é interessante quando há poucas comparações, porém quando em excesso pode provocar perda na produtividade e no entendimento do algoritmo, o modelo apresentando permite uma separação mais organizada, onde por meio da tabela é possível verificar qual função será executada para aquele determinado símbolo, facilitando assim a modularização, já que estão encapsuladas em funções, um outro ponto interessante é, que com esse modelo foi criado um framework para essa aplicação, onde para cada nova função criada, precisamos somente mapear qual vai ser o símbolo que vai corresponder a essa função, não necessitando alterar mais nada na aplicação.

Veja + conteúdo

Engenheiro Elétrico de Formação mas é Engenheiro de Software de profissão, Pós Graduado em Sistemas Embarcados. Apaixonado por Idiomas, mas o idioma que mais lhe fascina é a Linguagem C.
Jogador de CTF, mas prefire Battlefield 1, exige menos da capacidade cognitiva :P. Atualmente atua como desenvolvedor de sistemas distribuídos no ramo aeronáutico. Quando está de bobeira fica desenhando personagens de Anime, criando conteúdo para o canal[Solidcris - Zerando Games] ou pedalando pela cidade de São Paulo.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
3 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Cleisson Tavares Brito
Cleisson Tavares Brito
09/05/2021 21:16

Muito bom, meus parabéns. Curti muito a implementação.

Grupo de Engenharia Elétrica e Eletrônica da UFRPE (GEEE)
João Pimentel
07/05/2021 10:32

Muito bom! No caso foi preciso usar um struct por que a resposta era uma função, mas quando a resposta é um valor só fica mais simples, basta usar dois arrays ou um array bidimensional. Por exemplo, para saber o preço de um produto em uma lanchonete, poderia ter um array com o nome (ou código) dos produtos e um outro array com os preços.

Talvez você goste:

Nenhum resultado encontrado.

Séries

Menu