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();
}

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" .


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.


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.


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.


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.


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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.