Estou fazendo um curso intermediário de estruturas de dados como pré-requisito para ingressar no programa CS MS em uma universidade da qual todos os EUA já ouviram falar. Uma linha de código escrita em classe chamou minha atenção:
if (a > 33 | b++ < 54) {...}
Isso não passaria em uma revisão de código no meu local de trabalho. Se você escreveu um código como esse em uma entrevista, isso seria um golpe significativo contra você. (Além de ser condicional com efeitos colaterais, é inteligente às custas da clareza.)
Na verdade, nunca vi um condicional com efeitos colaterais, e o Google também não aparece muito. Outro aluno ficou para trás depois da aula para perguntar sobre isso também, então não sou o único que achou isso estranho. Mas o professor foi bastante inflexível quanto ao fato de ser um código aceitável e que ele escreveria algo assim no trabalho. (O trabalho dele no FT é como SWE principal em uma empresa que você já ouviu falar.)
Não consigo imaginar um mundo em que essa linha de código seja aceitável, muito menos desejável. Estou errado? Isso está bom? E o caso mais geral: condicionais com efeitos colaterais? Eles estão sempre bem?
fonte
Respostas:
Há um efeito colateral semicondicional em que posso pensar:
while(iter.MoveNext())
Dito isto, acho que isso se encaixa principalmente na categoria " nunca é um grande qualificado". Eu posso pensar em alguns casos raros em que eu já vi isso aceitável, mas em geral isso é vil e deve ser evitado.
Também não consigo pensar em um cenário em que essa linha em particular seria aceitável, mas também não consigo pensar em um cenário em que essa linha em particular seria útil , por isso é difícil imaginar o contexto em que está.
fonte
while(v = *p++)
varreduras no estilo C / C ++ através de uma matriz terminada em zero (por exemplo, string C) são bastante comuns e amplamente aceitas.while(c = input.read() != '\n')
razoavelmente idiomáticas.No meu mundo, uma leitura da memória pode ser considerada um efeito colateral (por exemplo, E / S mapeada na memória).
Agora, considere o seguinte:
E compare com:
Evitar o efeito colateral (a leitura) na condição ajudou na legibilidade; ou apenas duplicou o código e adicionou confusão?
Não é aceitável que uma condição tenha efeitos colaterais (se isso torna o código menos legível) e também não é aceitável que uma condição tenha efeitos colaterais (se isso torna o código mais legível). O fator chave é "legibilidade". Tudo o resto são regras criadas por tolos em uma tentativa equivocada de melhorar a legibilidade (embora muitas vezes tenham o efeito oposto).
fonte
Como sempre com essas perguntas, isso é uma questão de grau. Se houvesse prova inequívoca de que qualquer efeito colateral em uma
if
expressão sempre levasse a um código pior, não seria legal criar essas expressões. Projetistas da linguagem pode ser ideosyncratic, os seres humanos falíveis, mas eles não são que estúpido.Dito isto, quais são exemplos de efeitos colaterais justificados dentro de um
if
? Por exemplo, suponha que você seja legalmente obrigado a registrar todo e qualquer acesso à propriedadeP
de uma entidadeE
para fins de auditoria. (Imagine que você está trabalhando em uma planta de enriquecimento de urânio e há controles legais muito rígidos sobre o que seu código pode fazer e como deve fazê-lo.) Então qualquer umif
que verifique essa propriedade causará o efeito colateral do log de auditoria sendo estendido.Essa é uma preocupação transversal bastante clara, não afeta muito o seu raciocínio sobre o estado do programa, e você pode implementá-lo para que fique completamente invisível e não distraia quando você revisa a linha com o
if
(oculto). afastado no acessador, ou ainda melhor via AOP). Eu diria que é um caso bastante claro de um efeito colateral que não é uma preocupação. Situações semelhantes podem ser imaginadas quando você apenas deseja contar execuções de ramificações para fins de criação de perfil, etc.Quanto mais essas circunstâncias atenuantes desaparecerem, mais estranho o construto se tornará. Se um tipo de loop específico (por exemplo,
if((c = getc()) == 'x') { quit(); }
é bem conhecido e aceito pela comunidade de idiomas, é muito menos problemático do que quando você o inventa espontaneamente, etc. Sua linha de exemplo fica aquém desse padrão, mas eu poderia imaginar muito, muito mais horríveis que eu nem vou digitar, são tão horríveis.fonte
Embora o código seja realmente fedorento, ele tem a vantagem de ser mais simples (e talvez mais rápido se você não tiver um bom compilador de otimização) do que o equivalente
if (a > 33 | b < 54) {b++; ...} else b++;
mas é claro que é possível otimizá-lo da seguinte forma (mas cuidado! este possui um comportamento diferente em caso de estouro!):
b++; if (a > 33 | b < 53) {...}
fonte