Por que variáveis ​​não utilizadas é um problema?

9

Eu estava limpando avisos de variáveis ​​não utilizadas um dia e comecei a refletir: qual é exatamente o problema deles?

De fato, alguns deles até ajudam na depuração (por exemplo, inspecionar detalhes da exceção ou verificar o valor de retorno antes de retornar).

Eu não conseguia encontrar um risco real de tê-los ..

Exemplos

Não quero dizer linhas que demoram a atenção de outros programadores, como:

int abc = 7;

Essa é uma redundância e distração óbvias. Quero dizer coisas como:

try {
    SomeMethod();
} catch (SomeException e) {
    // here e is unused, but during debug we can inspect exception details
    DoSomethingAboutIt();
}
Alcatrão
fonte
31
Você quer dizer além do fato de que o programador que vem depois de você terá que gastar tempo tentando descobrir por que eles estão lá?
Robert Harvey
1
Seus exemplos são inofensivos, mas nunca vi casos como o referido como "variáveis ​​não utilizadas". De onde vêm seus avisos?
precisa saber é o seguinte
9
Bem, retnão é usado.
Robert Harvey
4
Você escreveu " eu quero dizer coisas assim catch (SomeException e) " - você está fingindo que existem outros casos semelhantes. Esclareça-me, quais? Eu pergunto porque em C # ou C ++, tenho problemas para encontrar uma situação diferente para o seu caso.
Doc Brown

Respostas:

4

De acordo com o quadro que você forneceu, é difícil argumentar contra essas variáveis ​​em si:

try {
    SomeMethod();
} catch (SomeException e) {
// here e is unused, but during debug we can inspect exception details
DoSomethingAboutIt();
}

Veja isso por exemplo. Você está capturando uma exceção e (talvez) possui um código que lida com a exceção de maneira adequada. O fato de você não estar usando a instância real da exceção não faz mal, nem ao fluxo de código nem à capacidade de compreensão.

Mas o que me faz pensar é quando você escreve sobre a legitimação de "variáveis ​​não utilizadas"

De fato, alguns deles até ajudam na depuração

Esse não é o objetivo de escrever código: ter que depurá-lo mais tarde. Para evitar mal-entendidos, devo dizer que estou bem ciente de que muitas vezes você precisa corrigir seu código; e às vezes a depuração é a solução. Mas não deve ser o primeiro, o que vem à sua mente, ao escrever código, que você deixe "pontos de ancoragem", cujo único objetivo é facilitar a depuração.

SomeClass Func() {
    // ...stuff...
    var ret = FinalComputationResult(thing, foo, bar);
    // ret is unused, but while debugging allows checking return value.
    return ret;
}

Aqui depende de quão complexo stuffé e como isso está relacionado ao valor, que é retornado.

Como uma "regra de ouro", eu diria o seguinte:

Se ajudar a entender o objetivo do código, não há problema em gerar redundância em seu código

ou, em outras palavras:

Escreva seu código com redundância livre, conforme necessário, para entender mais tarde facilmente, o que o código está fazendo

Isso resulta em: Na maioria das vezes, você deve remover as variáveis ​​"debug" .

Thomas Junk
fonte
19

O maior problema é a clareza . Se o seu código tem um monte de lixo estranho nele, e eu estou mantendo o código, preciso descobrir o que tudo faz.

Essa variável é usada para alguma coisa? Talvez você execute operações nele, mas nunca use seu valor para alguma coisa. Simplesmente incrementar uma variável não significa que a variável serve a um propósito se você nunca a ler (retornar, inserir outra expressão, etc.).

No entanto: se uma variável tem um propósito e é nomeada adequadamente, ela não diminui o código como um todo.

Dados os exemplos da sua pergunta atualizada e algumas outras que pensei:

  • Ter uma função que chama outra função, armazena o resultado, registra-o e depois o retorna, é bastante curto e claro.

  • Dividir uma instrução com várias expressões em várias instruções (por exemplo, dividir um cálculo longo e complexo em várias instruções com várias variáveis ​​intermediárias) pode tornar o código mais claro, apesar de ser mais detalhado. Com menos informações para processar por vez, o cérebro pode entender mais facilmente o que está acontecendo.

  • Não usar exceções é perfeitamente adequado: a maioria dos idiomas exige que a exceção seja capturada, incluindo o fornecimento de um nome de variável a ser usado no catchbloco. Não há como contornar isso em muitas linguagens populares e os programadores estão acostumados.

Se eu precisar dedicar algum tempo a descobrir quais elementos de código têm um objetivo e quais estão apenas desperdiçando meu tempo, minha produtividade diminui. No entanto, se o código for bastante conciso e as variáveis ​​forem bem nomeadas, mesmo quando parecerem estranhas a princípio, isso reduzirá o risco de perder tempo desnecessário revisando o código para entendê-lo.

Código incorreto com variáveis ​​estranhas, blocos vazios e código morto é uma maneira de os desenvolvedores terem uma má reputação no escritório: "Eu estava corrigindo um bug no código do Snowman. Passei duas horas descobrindo o que essa função estava fazendo e trinta segundos consertando o bug! Boneco de neve é péssimo em programação! " Mas se o código serve a um propósito e é escrito de maneira clara, está perfeitamente correto.


fonte
9
+1 para "Snowman é péssimo em programação". Eu sempre suspeitei. Como você pode ser um bom programador quando seus dedos estão sempre derretendo?
Robert Harvey
Veja minha edição - não me refiro a meras variáveis ​​criadas do nada para nada, apenas aquelas que podem ajudar aqui e ali durante a depuração ou apenas geradas por uma dessas ferramentas automáticas, como blocos de captura.
Tar
1
@ Tar que altera toda a pergunta - edite a entrada.
Observe que na sua lista com marcadores de quando você faz isso, os dois primeiros tendem a não resultar em aviso (nunca vi um idioma que produzisse um aviso nesse caso). Para o terceiro caso, qualquer idioma que exija a exceção de receber um identificador não possui um aviso e qualquer que produza um aviso para ele não exige que ele tenha um identificador (novamente, com o qual estou familiarizado de qualquer forma).
Servy
2
Olhando para o histórico de revisões, não vejo nenhuma indicação de que a questão esteja mudando fundamentalmente. Quanto ao código do OP, os dois primeiros resultarão em um aviso em C # (que parece ser o idioma usado). O terceiro exemplo não resultaria em um aviso. Os comentários sobre a pergunta também indicam que eles são especificamente indicados nos avisos do compilador e, quando Robert apontou que o terceiro exemplo não produz um aviso, o autor admitiu que era um mau exemplo para a pergunta.
Servy
5

Variáveis ​​não utilizadas que não têm nenhum objetivo óbvio são um cheiro de código, na minha opinião. Na melhor das hipóteses, eles podem ser uma distração - eles aumentam o ruído geral no módulo.

O pior caso é que os codificadores subsequentes gastam tempo descobrindo o que deveria fazer e se perguntando se o código está completo. Faça um favor a si mesmo (e a todos os outros) e se livre.

Robbie Dee
fonte
1
O que é um "bug" na sua opinião? Variáveis ​​não utilizadas não produzem resultados inesperados e errôneos per se, que é o que a maioria das pessoas qualificaria como um bug.
Harris
5
Por que a variável não é usada? Muito provavelmente porque deveria ter sido usado, mas outra variável foi usada por engano. Você recebe um aviso do compilador e o corrige e corrige o bug ao mesmo tempo. O problema é que se você tem um programador indisciplinado que deixa uma bagunça por perto, não consegue encontrar onde esse tipo de aviso indica um bug e onde apenas indica um programador bagunçado.
gnasher729
@HarrisWeinstein Dado que testadores e desenvolvedores não conseguem nem concordar com o que é um bug na maioria das vezes, eu vou estacionar isso por enquanto. Basta dizer que é uma deficiência no código - e possivelmente no executável, pois ocupará espaço. É certo que não é o maior problema do mundo, mas lá em cima com erros de ortografia de caixa de comentários e código comentado. É uma crosta que não acrescenta nada, por isso deve ser removida. Código que parece bom inspira confiança. Penso que esta citação também é adequada e cobre bem o processo de refatoração.
Robbie Dee
Se você estiver usando uma linguagem dinâmica, atribuir um valor para some_varquando o restante do código usar someVarfor quase garantido como um bug. Isso pode não ser um problema em Java ou C, mas pode facilmente quebrar alguns Python.
precisa saber é o seguinte
1
@ThomasJunk Esse é provavelmente um termo melhor para isso - obrigado. Ajustarei minha resposta de acordo.
Robbie Dee
5

Variáveis ​​não utilizadas tornam a intenção do seu código pouco clara. Isso é ruim porque, apesar das aparências, o código é predominantemente escrito para as pessoas lerem, não para computadores .

Outros já apontaram que construir um valor e não usá-lo confunde outras pessoas que precisam ler e trabalhar com seu código. No entanto, a meu ver, o maior perigo é para si mesmo .

Uma variável não utilizada pode ser intencional ou pode ser um descuido apontando para um defeito. Por exemplo, você pode ter digitado um nome errado e armazenado um valor em um lugar quando pensou que o havia armazenado em outro. O programa resultante pode funcionar bem, mas silenciosamente fornece o resultado errado.

A análise do fluxo de dados pode ajudá-lo a encontrar esses erros e muitos outros. Portanto, vale a pena escrever seu código de forma que tudo que um analisador de fluxo de dados aponte como uma anomalia seja, de fato, um bug. A assistência automática na prevenção de erros é inestimável; muitas pessoas pensam "Oh, eu não preciso de assistência, nunca seria tão descuidado", mas até agora todos os que conheci que pensavam que estavam errados.

Kilian Foth
fonte
2

Existe um estilo de codificação que envolve atribuir deliberadamente qualquer coisa que tenha (ou possa se tornar) de interesse para uma variável com o objetivo específico de visualizá-la facilmente em um depurador. Isso é especialmente útil para código que se parece com:

return foo(bar(), baz(wot(12), wombat(&badger)));

Mesmo com nomes um pouco melhores para as funções, pode ser mais fácil descobrir o que está errado na chamada para foo quando escrito como:

auto awombat = wombat(&badger);
auto awot = wot(12);
auto abaz = baz(awot, abadger);
auto abar = bar();
auto afoo = foo(abar, abaz);
return afoo;

Ainda estou para trabalhar com pessoas que praticam isso como a configuração padrão, mas reescrever um pedaço de código que se recusa teimosamente a fazer algum sentido no formulário de atribuição única pode facilitar o trabalho do que está acontecendo no depurador. Sempre revertemos o código para o formato compacto "bonito" depois, mas me pergunto se isso foi um erro.

A alternativa é subir e descer a pilha e esperar que você não avance muito, ou usar depuradores reversíveis (angustiosamente raros).

Não é uma estratégia popular, mas como me ajudou a solucionar alguns erros absurdos, não acho que deva ser considerado intrinsecamente ruim.

Jon Chesterfield
fonte
Embora eu provavelmente não fosse tão longe quanto você, acho sua primeira forma "bonita" muito compacta.
Loren Pechtel
Exceto que não há uma única variável não utilizada no seu código.
Florian F
Do lado positivo, se você receber um aviso sobre variáveis ​​não utilizadas, saberia que em algum lugar dessa transformação você cometeu algum erro grave. O que seria fácil de consertar.
precisa saber é o seguinte
1

Para pessoas que incluem seu código de teste de unidade nos mesmos projetos ou módulos que seu código "real", um campo não utilizado , como um método de objeto, é um forte sinal de que seus testes de unidade não estão testando tudo. Isso aumenta a chance de um desenvolvedor tentar usar esse campo ou método atualmente não utilizado e encontrar um bug que não estava sendo detectado até então.

Uma variável não utilizada em uma sub-rotina ou método não trivial pode indicar que o programador pretendia usá-la, mas está usando outra variável por engano (por exemplo, após a limpeza após uma operação de copiar e colar).

Uma variável não utilizada em uma sub-rotina mais trivial é provavelmente a escória desnecessária, como outras pessoas responderam. Ocasionalmente, é usado em uma instrução de trilha de navegação que é comentada atualmente:

SomeObject tmp = someMethod();
// printDebugInfoAbout (tmp);

... fica claro para os olhos que é usado lá, e somente lá (ou seja, someMethodtem um efeito colateral importante), mas o IDE não sabe disso, e remover essa variável é mais um problema do que vale a pena. Eu uso provisoriamente supressores de aviso nesses casos.

Paul Brinkley
fonte
1
Gostaria de saber em que circunstâncias você gostaria que o código comentado fosse confirmado no seu repositório. Mas uma situação semelhante ocorre ao usar a compilação condicional (como ao usar a assertmacro em C ou C ++). Os avisos variáveis ​​não utilizados podem de fato ser um aborrecimento, e suprimi-los é a resposta mais razoável, se você me perguntar.
precisa saber é o seguinte
1
Eu editei minha resposta, adicionando um exemplo muito aproximado do que vi no passado. O bloco pode ser executado várias vezes e algo está coletando todas as informações de depuração em um log para análise ao rastrear um problema, mas a impressão é lenta e geralmente é desativada. Eu poderia substituir a primeira linha por someMethode perder informações sobre a tmporigem. Ou eu poderia confirmar uma versão limpa e esquecer que alguma versão anterior tinha essa trilha útil (e não possuía o código necessário adicionado nas versões posteriores). ... Eu busco uma solução ideal para isso há muito tempo.
Paul Brinkley
Eu vejo. Aparentemente, seu idioma de escolha não possui um pré-processador. ;-)
5gon12eder
Atualmente sim. :-) Embora seja justo, já vi esse mesmo tipo de coisa em C e C ++, e também não foi fácil livrar-se de variáveis ​​não utilizadas nesses casos (quase-apêndices?). ... O fato de meu último grande projeto C / C ++ ter sido realizado em um momento em que os IDEs não existiam (os avisos do compilador exigiam a execução de "gcc -pedantic") também não ajudaram.
Paul Brinkley
0

É fácil quando você escreve código para misturar duas variáveis. Você calcula uma variável B, mas usa uma variável A criada anteriormente.

Portanto, um possível motivo para uma variável não utilizada é que há um erro no seu código. É por isso que o compilador avisa. Se você "não faz" variáveis ​​não utilizadas, é até uma oferta inoperante.

Quando vir esse aviso, verifique seu código e corrija-o ou remova a variável incorreta. Se você não removê-lo, deixará de prestar atenção a esses avisos e poderá desativá-los completamente. Mas, eventualmente, você perderá uma tarde depurando o código por causa de um erro bobo.

Florian F
fonte