Dev (Back & Front)ARTIGO

Programando condições sem escrever condicionais: um exercício de lógica

Escrevemos códigos e não treinamos como pensar diferente para resolver um mesmo problema de maneira até mais simples e limpa, um exercício de lógica.

Programando condições sem escrever condicionais: um exercício de lógica
Imagem: Alan Raphael

Comumente escrevemos códigos como robôs, aprendemos a seguir uma lógica procedural e não treinamos como pensar de forma diferente para resolver um mesmo problema de maneira até mais simples e limpa. Um exemplo é o clássico uso do else em situações completamente desnecessárias, como neste código:

function maior_que_cinco(valor){
if (valor > 5)
return true
else
return false
}

Neste exemplo o else pode ser omitido, pois seu uso é redundante. Assim o código ficará:

function maior_que_cinco(valor){
    if (valor > 5)
        return true    

    return false
}

Para falar a verdade, o else é quase sempre dispensável em qualquer condicional.

Hora de ir além

Quem já programou em Python, por exemplo, deve ter sentido falta do switch e certamente acha muito feio aquele monte de elif como forma de contornar esta falta. E de fato é muito feio! Mas existe uma forma muito simples de contornar este problema, deixa o código até melhor do que switch ou vários “ifs” e isso pode ser utilizado em qualquer linguagem.

Para exemplificar, irei utilizar o JavaScript, pois acredito que é uma linguagem que qualquer desenvolvedor(a) sabe — ou deveria saber — hoje em dia.

Cenário

Imagine que você esteja criando um e-commerce e precisa internacionalizá-lo, certamente precisará formatar os valores monetários.

Vamos pegar este caso como exemplo e criar uma função que irá receber o tipo da moeda e o valor e retornar a string formatada.

const formata_moeda = (moeda, valor) => {
switch (moeda) {
case 'real':
return 'R$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ".$1,$2")
break

case 'dolar':
return 'US$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ",$1.$2")
break
}
}

(Sim, eu sei que existe suporte nativo para resolver isso usando toLocaleString.)

Esse switch pode ser substituído por um dicionário e o resultado será o mesmo.

const formata_moeda = (moeda, valor) => {
const moedas = {
'real': 'R$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ".$1,$2"),
'dolar': 'US$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ",$1.$2")
}

return moedas[moeda]
}

O código já ficou bem melhor! Mas podemos melhorá-lo ainda mais ao explorar a grande vantagem da arrow function e remover a constante e o return, mantendo apenas o dicionário.

const formata_moeda = (moeda, valor) => ({
'real': 'R$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ".$1,$2"),
'dolar': 'US$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ",$1.$2")
})[moeda]

Pronto! O código ficou bem mais enxuto!

Porém há um problema! Caso passemos uma moeda não suportada será retornado um undefined.

console.log(formata_moeda('real', 29899.3)) // R$ 29.899,30
console.log(formata_moeda('dolar', 29899.3)) // US$ 29,899.30
console.log(formata_moeda('euro', 29899.3)) // undefined

Então como vamos tratar caso seja passado uma moeda não suportada?

Simples!

const formata_moeda = (moeda, valor) => ({
'real': 'R$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ".$1,$2"),
'dolar': 'US$ ' + String(valor.toFixed(2)).replace(/([0-9]{3}).([0-9]{2}$)/g, ",$1.$2")
})[moeda] || 'Moeda não suportada!'

Agora temos um valor default.

console.log(formata_moeda('real', 29899.3)) // R$ 29.899,30
console.log(formata_moeda('dolar', 29899.3)) // US$ 29,899.30
console.log(formata_moeda('euro', 29899.3)) // Moeda não suportada!

Talvez você esteja achando o código bem limpo e deve estar se questionando como seria em Python, já que a sintaxe do JS favoreceu muito.

Vejamos um exemplo em Python:

def formata_moeda(moeda, valor):
    return {
        'dolar': f'US$ {valor:,.2f}',
        'real': f'R$ {valor:,.2f}'.replace(',', '.')[::-1].replace('.', ',', 1)[::-1]
    }.get(moeda, 'Moeda não suportada!')

print(formata_moeda("real", 29899.3)) # R$ 29.899,30
print(formata_moeda("dolar", 29899.3)) # US$ 29,899.30
print(formata_moeda("euro", 29899.3)) # Moeda não suportada!

No Python, a não existência da chave no dicionário retorna uma exception KeyError que te permite tratar no local da chamada, porém também temos a opção de retornar um valor default utilizando get. Mas existe um problema neste código em Python… A forma simplificada (jogar o dicionário com get direto no return) não é vista como uma boa prática na comunidade Python, neste caso precisamos refatorar.

def formata_moeda(moeda, valor):
moedas = {
'dolar': f'US$ {valor:,.2f}',
'real': f'R$ {valor:,.2f}'.replace(',', '.')[::-1].replace('.', ',', 1)[::-1]
}

return moedas.get(moeda, ‘Moeda não suportada!’)

O código ainda permaneceu simples, porém mais limpo para quem lê.

Este foi um exemplo simples sobre como podemos resolver problemas de condição sem usar condicionais, agora seja criativo!

Romper a lógica convencional da programação nos ajuda a resolver problemas complexos de maneira mais simples, ou simplesmente melhorar a legibilidade do código. Nem sempre é trivial, mas é só questão de vontade de exercitar.

Artigo original publicado aqui e gentilmente cedido pelo autor.

Formado em Física, atua como Engenheiro de Software desde 2009. Tem como foco principal arquitetura de software, IA e mercado financeiro. Nas horas livres organiza o OpenLabs Conf.

Ver perfil