Introdução
Existe uma boa prática de programação que recomenda que se faça aninhamento excessivo de condições if-else, para evitar códigos conforme da figura abaixo.
Algumas soluções e padrões de projeto podem ser aplicados, desde uso de estrutura de dados (Maps/Dicionários), a padrão de projetos (strategy. explicado no excelente post de @ivanqueiroz).
Recursos da linguagens observadores e experimentados
Nessa seção, pretendo falar de alguns recursos que pude experimentar durante o curso, e pratiquei em um projeto piloto que está disponível em um repositório no meu github onde pretendo colocar os demos do que ando testando com Kotlin. Esse repositório é o kotlin-lab.
Um pouco de teoria
O if/else demasiadamente, não deve ser evitado apenas por questões de legibilidade mas também porque impacta na performance e na complexidade do algorítimo. A complexidade sintomática é uma métrica de software utilizada para definir a complexidade de um programa. Ela é medida como a medida quantitativa do número linar de caminhos que um programa pode percorrer através de seu código-fonte. Explicações mais detalhadas sobre o tema pode ser obtidas nos links 1,2 e 3. Existe toda uma teoria matemática que fundamenta essa explicação e de maneira “grosseira” porém, objetiva temos um resumo da seguinte forma:
- Se temos entre 0 e 5 condições - Provávelmente o programa é ok
- Se temos entre 6 e 10 - Devemos pensar em simplificar essa rotina
- Se temos mais de 10 - devemos quebrar essa rotina em subrotinas
Falando exclusivamente pelo viés da performance, a tendência é que o algorítimo do primeiro anexo de código, seja mais performático do que o segundo.
Implementação 2:
Quando temos um contexto onde é necessário se testar essas condições, o que podemos usar?
Em computação poucas perguntas não podem ser respondidas com a simples palavra depende. Existem contextos e estruturas onde é necessário trabalhar com diversas condicionais, então o que as linguagens oferecem como recurso mais elegante que o if/else. A grande vantagem de utilizar recursos nativos da linguagem, é que a mesma oferece uma implementação para reduzir a complexidade sintomática. Instruções como Switch (Java) e When (Kotlin), reduzem significativamente o impacto do grafo de decisão do algoritimo pois a condição da expressão é avaliada apenas uma vez. O compilador normalmente trata e garante uma otimização no uso desse tipo de instrução.
Java
Em Java, temos a instrução switch/case, que desde a release 8 vem sofrendo diversas melhorias mas apresenta algumas limitações, como por exemplo, no passado não suportava Strings dentro das condições.
Sintaxe da instrução switch/case em Java.
Como isso funciona:
- A instrução boolean dentro do switch é avaliada uma única vez.
- O resultado dessa expressão é avaliado com cada case.
- Se algum acontece o match, o bloco dentro do case é executado.
- É opcional utilização de break e default.
Evolução Switch/case no Java vem acontecendo e ele atualmente suporta comparação com Strings (desde o Java 7) e outros recursos que vou tentar enumerar logo abaixo:
- Switch Expressions - Preview Java 12
- Switch Expressions - Preview Java 13
- Switch Expressions - Standard Java 14
O que é possível com esses recursos:
Kotlin
Mas e como o Kotlin fornece trata esse problema? Eu particulamente achei muito simples e eficiente a forma como Kotlin traz isso. Como é uma linguagem mais nova e não precisa pensar em retrocompatibilidade, já nasceu da maneira otimizada e baseada em linguagens menos verbosas que o Java.
When
A instrução foi pensada para compensar diversos recursos não suportados nativamente pelo switch/case do Java.
A primeira grande vantagem é que o when já nasceu como uma expressão (suporta um valor a ser calculado em tempo de execução). A instrução é executada quando uma das condições é satisfeita. When pode ser usada tanto como expressão, como comando. When suporta um bloco else que tem comportamento similar a um else de uma instrução if.
When suporta ranges e expressões como condicionais, também é possível utilizar a função is.
Exemplos de uso diversos:
A gramática do when pode ser vista no link da linguagem
Conclusão
Conhecemos mais um recurso bacana e muito rico da linguagem Kotlin. A medida que for descobrindo mais, vou registrando aqui como nota mental e para compartilhar com outras pessoas que possam estar estudando mesmo tópico.
Outras Fontes:
- http://www.thedevpiece.com/why-you-should-avoid-if-else-statements/
- https://www.w3schools.com/java/java_switch.asp
- https://blog.codefx.org/java/switch-expressions/
- https://medium.com/better-programming/a-look-at-the-new-switch-expressions-in-java-14-ed209c802ba0
- https://www.baeldung.com/java-switch
- https://www.baeldung.com/kotlin-when
- https://kotlinlang.org/docs/reference/control-flow.html
- https://superkotlin.com/kotlin-when-statement/