Como parar de escrever código em cadeia?
-
28-09-2019 - |
Pergunta
por exemplo...
if ( /* Condition */ ) {
if ( /* Condition */ ) {
if ( /* Condition */ ) {
// Superb!
} else {
// Error 3
}
} else {
// Error 2
}
} else {
// Error 1
}
Você sabe como evitar isso?Obrigado!
Solução
Se esta for uma função de biblioteca, throw
pode ser a ação apropriada.
if (!condition1) {
throw "Condition 1 failed.";
}
if (!condition2) {
throw "Condition 2 failed.";
}
if (!condition3) {
throw "Condition 3 failed.";
}
// Superb!
Outras ações aceitáveis podem ser:
- Retornando
0
,null
, ouundefined
. - Exibindo um erro para o usuário e retornando.
Você terá que determinar qual ação de falha é adequada para seu caso de uso.
Outras dicas
Parece que você tem 3 condições para verificar e 4 ações (3 erros diferentes + 1 sucesso). Infelizmente, no caso geral, exigirá três verificações condicionais e 4 ações. Eu acho que o código pode ser limpo um pouco usando a seguinte estrutura
if (! /* condition 1 */ ) {
// Error 1
} else if (! /* condition 2 */ ) {
// Error 2
} else if (! /* condition 3 */ ) {
// Error 3
} else {
// superb
}
Bem, você pode usar exceções ou quebras em um bloco ou várias funções. Muitas vezes, isso requer inverter suas condições para obter o código encomendado da maneira certa.
do {
if (! /* Condition 1 */ ) {
// Error 1
break;
}
if (! /* Condition 2 */ ) {
// Error 2
break;
}
if (! /* Condition 3 */ ) {
// Error 3
break;
}
// Superb!
} while (false);
O loop Do-While (False) é uma maneira de criar um bloco que você pode romper em idiomas que não toleram um bloco anônimo. Poderia ser facilmente uma função e usar retornos ou uma pega de tentativa com exceções.
Você prefere isso?
if ( /* Condition 1*/ && /* Condition 2*/ && /* Condition 3 */) {
// Superb!
}
else if (! /* Condition 1*/){
// Error 1
}
else if (! /* Condition 2*/){
// Error 2
}
else if (! /* Condition 3*/){
// Error 3
}
if ( ! /* Condition */ ) {
Error 1
throw someSortOfException
}
if (! condition 2){
Error 2
throw someSortOfOtherException
}
if (! condition 3){
Error 3
throw another Exception
}
// Success!
Dependendo da situação, seu código pode ser preferido. Você provavelmente vai querer pegar essas exceções em algum lugar, por exemplo.
if (!condition1)
// Error 1 (and exit scope if necessary)
if (!condition2)
// Error 2 (and exit scope if necessary)
if (!condition3)
// Error 3 (and exit scope if necessary)
// Superb!
Sim; você pode compor seu if
declarações em uma única instrução composta usando o operador e lidera as condições de erro em um único bloco. Dependendo das suas necessidades de manuseio de erros, porém, pode ser necessário ter novamente vários if
s para garantir que você esteja lidando com o erro corretamente (depende da sua resolução de lidar com erros, na verdade).
A saber:
if (CondA && CondB && CondC)
{
// Execute success
}
else
{
if (!CondA)
// Do error A
else if (!CondB)
// Do error B
else if (!CondC)
// Do error C
}
}
Existem algumas maneiras, o mais simples é simplesmente eliminar algumas funções e abstrair as diferentes camadas (isso deve ser feito de qualquer maneira, se você se sentir profundo.)
if ( /* Condition */ ) {
value = aFunctionSaysWhat();
} else {
// value = Error 1
}
....
value aFunctionSaysWhat(){
if ( /* Condition */ ) {
return aSecondFunctionHere();
} else {
// return Error 2
}
}
A premissa básica é que uma função deve viver em uma camada de abstração, se possível, e fazer uma coisa.
A próxima possibilidade é achatar tudo, isso é superior ao seu método aninhado inicial, mas basicamente tem complexidade semelhante. Pode ser muito mais limpo que a abordagem funcional se você tiver apenas algumas opções e não planeja adicionar mais.
if(ErrorCondition1){
//Error 1
}else if(ErrorCondition2){
//Error 2
}else if(ErrorCondition3){
//Error 3
}else{
//Superb
}
Por fim, você pode armazenar um hash ou mapear com as respostas desejadas e remover o IF completamente, a capacidade de implementar isso depende da sua capacidade de hash algum resultado:
Results = {'Result1':'Error1', 'Result2':'Error2', 'Result3':'Error3', 'Success':'Superb'}
return Results[ConditionHash(Condition)];