Eu concordo com @MartinMaat sobre escolher suas batalhas.
Existem muitos casos de "just in case" devido ao fato de não entender o idioma, apesar de o idioma estar fixado em suas regras para muitas dessas coisas - entre parênteses uma expressão que não é necessária por não entender as regras de precedência de o idioma. Mas ainda assim, essa prática é principalmente inofensiva.
Quando eu era jovem, achava que deveríamos aprender os detalhes do idioma e, assim, evitar escrever esse código supérfluo. (Uma de minhas irritações foi return (0);
com suas parênteses desnecessárias.) No entanto, agora eu modero essa posição, em particular, porque agora usamos tantos idiomas diferentes, saltando de cliente para servidor, etc. folga para alguns desses problemas.
Seu ponto de vista sobre o início ciclomático é o argumento logicamente fundamentado. Vejamos a Cobertura de código e os níveis de cobertura especialmente mais altos :
- Cada decisão leva todos os resultados possíveis
Como não podemos forçar a nova operação a retornar NULL, não há como atingir níveis mais altos de cobertura de código para esta operação condicional. Obviamente, isso pode ou não ser importante para sua organização!
No entanto, devido a esse problema de cobertura do código, eu o priorizaria mais do que entre parênteses.
Por outro lado, o código gerado subjacente provavelmente não sofrerá um pouco com isso, pois as gerações de código, JIT e otimizadores entendem que um new
valor ed nunca será nulo. Portanto, o custo real vem apenas em termos de legibilidade e recursos de cobertura do código fonte.
Gostaria de perguntar como é a "parte mais" de tal declaração if?
Se não houver outra parte, eu argumentaria que simplesmente cair no final da rotina ou passar para outro código (ou seja, não else
para isso if
) é potencialmente perigoso, pois agora esse "apenas no caso" sugere logicamente que os chamadores e / ou outro código abaixo da linha também lida com NULL.
Se estiver escrito:
p = new Object ();
if ( p != null ) {
p.field = value;
}
else {
throw new NullReferenceException ();
}
então isso é realmente um exagero, pois a linguagem faz tudo isso por nós.
Eu poderia sugerir reverter o sentido do condicional - talvez seu colega se sinta mais confortável com isso:
p = new Object ();
if ( p == null ) {
throw new NullReferenceException ();
}
else {
p.field = value;
}
Agora você pode defender a remoção do wrapper else, pois é claramente desnecessário:
p = new Object ();
if ( p == null ) {
throw new NullReferenceException ();
}
p.field = value;
Com isso, o "apenas no caso" agora é o que é condicional, enquanto o código seguinte não é. Essa abordagem reforça ainda mais que, quando a alocação falha, a resposta apropriada é lançada, em vez de continuar executando o código nesse método e / ou nessa cadeia de chamadas (sem qualquer outro tratamento adequado da falha na alocação).
Portanto, em resumo, existem dois argumentos logicamente fundamentados a serem apresentados aqui contra essa prática:
- Não é possível alcançar níveis mais altos de cobertura de código, pois não podemos forçar a falta de memória (ou qualquer falha no construtor) para retornar nulo.
- O "just in case" (como mostrado acima na pergunta) está incompleto e, como tal, é defeituoso devido à inconsistência nas expectativas de como o nulo deveria ser tratado por outro código além / além do
p.field = value;
.
Fundamentalmente, parece que talvez seu colega esteja em dúvida sobre o uso de exceções - mesmo que não haja escolha aqui em C # para essas coisas. ( Se queremos código bem testado , não podemos codificar um modelo de exceção para manipular um modelo nulo e um não-exceção usando valores de retorno nulo, lado a lado.) Talvez se você argumentar com seu colega sobre estes tópicos, eles verão alguma luz!