Adquira o hábito de escrever juntos! Este é o sexto dia da minha participação no "Nuggets Daily New Plan · April Update Challenge", clique para ver os detalhes do evento .
motivação
As expressões condicionais geralmente vêm em dois sabores:
- Ambos os ramos condicionais são comportamento normal
- Apenas uma ramificação condicional é um comportamento normal, a outra ramificação é anormal
Esses dois tipos de expressões condicionais servem a propósitos diferentes, que devem ser mostrados no código:
-
Se ambas as ramificações são de comportamento normal, uma expressão condicional da forma if...else... deve ser usada
-
Se uma condição for extremamente rara, ela deve ser verificada separadamente e retornada da função assim que a condição for verdadeira
Essas verificações separadas são muitas vezes referidas como "cláusulas de guarda"
A essência de substituir expressões condicionais aninhadas por guardas é dar atenção especial a uma ramificação. Se você usar uma construção if-then-else, você colocará peso igual na ramificação if e na ramificação else. A mensagem para o leitor de tal estrutura de código é que cada ramo é igualmente importante. A instrução guard está dizendo ao leitor: "Esta situação não é o que interessa à lógica central desta função. Se isso acontecer, por favor, faça a limpeza necessária e saia."
A noção de que "toda função pode ter apenas uma entrada e uma saída" está profundamente arraigada em alguns programadores. Quando trabalho com o código que eles escrevem, geralmente preciso usar instruções de guarda em vez de expressões condicionais aninhadas. As linguagens de programação atuais impõem apenas uma entrada por função, e a regra de "saída única" não é tão útil. Manter o código claro é a chave: se uma única saída torna a função mais legível, use uma única saída; caso contrário, não.
prática
Selecione a lógica condicional mais externa que precisa ser substituída e substitua-a por uma instrução guard.
teste.
Se necessário, repita os passos acima.
Se todas as instruções de guarda produzirem o mesmo resultado, você poderá combiná-las usando [Merge Conditional Expressions].
caso
Calcule os salários a serem pagos aos funcionários. Apenas os funcionários que ainda estão trabalhando na empresa precisam ser pagos, então esta carta
O número precisa verificar se há duas situações de "funcionário que não está mais trabalhando".
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
} else {
if (employee.isRetired) {
result = 0;
} else {
// logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
}
} return result;
}
复制代码
A lógica condicional aninhada torna difícil ver o que o código realmente significa. Somente quando nenhuma das duas expressões condicionais atuais é verdadeira, esse código realmente inicia seu trabalho principal. Portanto, as instruções de guarda permitem que o código expresse seu significado com mais clareza
foto. Como sempre, gosto de dar pequenos passos, então lido primeiro com a lógica condicional superior.
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
}
if (employee.isRetired) {
result = 0;
} else { // logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
} return result;
}
复制代码
Após fazer essa modificação, executo o teste e passo para a próxima etapa.
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
return result;
}
复制代码
Neste ponto, a variável de resultado é inútil, então eu a excluo:
public Long payAmount(Employee employee) {
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
return someFinalComputation();
}
复制代码
É sempre bom poder reduzir uma variável mutável.
reverter a condição
Muitas vezes podemos reverter a expressão condicional para substituir expressões condicionais aninhadas por guardas.
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital > 0) {
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
}
return result;
}
复制代码
Substitua um por um. Mas desta vez ao inserir a instrução guard, preciso reverter a condição correspondente:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
return result;
}
复制代码
A próxima condição é um pouco mais complicada, então faço a inversão em duas etapas. Primeiro adicione uma operação NOT lógica:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (!(anInstrument.interestRate > 0 && anInstrument.duration > 0)) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
复制代码
Mas deixar um NOT lógico em uma expressão condicional como essa estragaria minha cabeça, então eu simplifiquei para:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
复制代码
Essas duas linhas de lógica produzem o mesmo resultado, então posso combiná-las com [Merge Conditional Expressions]:
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
复制代码
Neste ponto, a variável result faz duas coisas: primeiro eu a defino como 0, que representa o valor de retorno quando a instrução guard é acionada; e então eu a atribuo com o resultado do cálculo final. Eu posso remover esta variável completamente, evitar dupla responsabilidade com uma variável e reduzir mais uma variável variável.
public int adjustedCapital(Instrument anInstrument) {
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return 0;
}
return (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
复制代码
referir-se
- "Reconstrução"
- "Arquitetura Limpa"