Você encontrou um código que parece supérfluo e o compilador não percebe isso. O que você faz para ter certeza (ou o mais próximo possível) de que a exclusão desse código não causará regressão.
Duas idéias vêm à mente.
"Simplesmente" use dedução com base em se o código deve ou não ser executado. No entanto, às vezes, esse pode ser um trabalho complexo, demorado e levemente arriscado (sua avaliação está sujeita a erros), sem retorno comercial significativo.
Coloque o registro nessa seção de código e veja com que frequência ele é inserido na prática. Após execuções suficientes, você deve ter confiança razoável para remover o código.
Existem idéias melhores ou algo como uma abordagem canônica?
clean-code
Brad Thomas
fonte
fonte
Respostas:
No meu mundo de fantasia perfeito, onde tenho 100% de cobertura de teste de unidade, eu a excluí, executava meus testes de unidade e, quando nenhum teste fica vermelho, eu o comprometo.
Mas, infelizmente, tenho que acordar todas as manhãs e enfrentar a dura realidade em que muitos códigos não têm testes de unidade ou quando estão lá não podem ser confiáveis para realmente cobrir todos os possíveis casos extremos. Então, eu consideraria o risco / recompensa e chegaria à conclusão de que simplesmente não vale a pena:
fonte
Existem duas metades nesse processo. A primeira é confirmar que o código está realmente morto. O segundo é compreender os custos de estar errado e garantir que eles sejam adequadamente mitigados.
Muitas respostas aqui têm ótimas soluções para a primeira metade. Ferramentas como analisadores estáticos são ótimos para identificar código morto.
grep
pode ser seu amigo em alguns casos. Um passo incomum que geralmente tomo é tentar identificar qual era o objetivo original do código. É muito mais fácil argumentar que "X não é mais um recurso do nosso produto, e o segmento de código Y foi projetado para suportar o recurso X" do que dizer "Não vejo nenhuma finalidade para o segmento de código Y".A segunda metade é uma etapa fundamental para quebrar qualquer impasse sobre se você deve remover o código. Você precisa entender quais são as implicações de obter a resposta errada. Se as pessoas vão morrer se você errar a resposta, preste atenção! Talvez seja um bom momento para aceitar que o código do cruft se desenvolva com o tempo e, em vez disso, tente não escrever mais. Se as pessoas não vão morrer, pergunte a si mesmo como os seus usuários estão perdoando. Você pode enviar um hotfix a eles se você quebrou alguma coisa e mantém as relações com os clientes? Você tem uma equipe de perguntas e respostas paga para encontrar problemas como este? Esse tipo de pergunta é essencial para entender como você deve ter certeza antes de pressionar a tecla Delete.
Nos comentários, rmun apontou uma excelente redação do conceito de entender o objetivo original do código antes de removê-lo. A citação agora é conhecida como Cerca de Chesterton . Embora seja muito grande para ser citado diretamente em um comentário, acho que merece ser citado corretamente aqui:
fonte
Também costumo
grep
usar o nome da função / classe no código, o que pode oferecer alguns benefícios adicionais que um analisador de código pode não oferecer, como se o nome fosse mencionado em um comentário ou em um arquivo de documentação ou em um script, por exemplo. Eu corro grep nos arquivos na árvore de origem e armazeno o resultado em um arquivo; geralmente o resultado fornece informações condensadas: nome / caminho do arquivo, número da linha e a linha onde o nome é encontrado, o que pode fornecer pistas sobre onde a função / classe é chamada ou mencionada sem qualquer significado semântico (em contraste com um analisador de código ) e independentemente das extensões de arquivo. Definitivamente não é a solução definitiva, mas uma boa adição a uma análise.fonte
$object->$variableMethod($arg1, $arg2);
grep
o eg. A função que abrange a seção de código pode fornecer pistas sobre como a função é usada e, portanto, seu conteúdo?fonte
Além das respostas existentes mencionadas, você também pode remover iterativamente o código em várias versões.
Na versão inicial, você poderia fazer um aviso de descontinuação com o bloco de código ainda funcionando. Na versão seguinte, você pode remover o bloco de código, mas deixar uma mensagem de erro informando aos usuários que o recurso está obsoleto e não está mais disponível. Na versão final, você removeria o bloco de código e qualquer mensagem.
Isso pode ajudar a identificar funcionalidades imprevistas sem aviso aos usuários finais. Na melhor das hipóteses, o código realmente não faz nada e tudo o que acontece é que o código desnecessário é mantido em várias versões antes de ser removido.
fonte
Muitas pessoas estão sugerindo que a coisa "segura" a fazer é deixar o código dentro, se você não puder provar que ele não é usado.
Mas o código não é um ativo, é um passivo.
A menos que você possa explicar por que é importante e apontar para seus testes, a alternativa "mais segura" pode muito bem ser excluí-la.
Se você ainda não tiver certeza, pelo menos, certifique-se de adicionar testes para exercitar o código zumbi.
fonte
Você pode usar as alternâncias de recursos para alterar o caminho de execução do seu software para ignorar completamente o código em questão.
Dessa forma, você pode implantar com segurança suas alterações com o código não em uso e desativar. Se você notar algumas falhas importantes relacionadas ao código, ative a alternância novamente e investigue o caminho possível para ele.
Essa abordagem deve fornecer confiança se você não encontrar problemas por um período prolongado, bem como a capacidade de reativá-la ao vivo sem uma implantação. No entanto, uma maneira ainda melhor seria também aplicar extra log e cobertura de teste na área em questão, o que fornecerá mais evidências, quer sejam usadas ou não.
Leia mais sobre alternâncias aqui: https://martinfowler.com/articles/feature-toggles.html
fonte
Análise estática, é claro ... e o bom é que você não precisa de nenhuma ferramenta nova; seu compilador possui todas as ferramentas de análise estática necessárias.
Apenas mude o nome do método (por exemplo, mude
DoSomething
paraDoSomethingX
) e execute uma compilação.Se sua construção for bem-sucedida, o método, obviamente, não está sendo usado por nada. Seguro para excluir.
Se sua compilação falhar, isole a linha de código que a chama e verifique quais
if
instruções cercam a chamada para determinar como acioná-la. Se você não encontrar nenhum caso de uso de dados possível que o acione, poderá excluí-lo com segurança.Se você estiver realmente preocupado em excluí-lo, considere manter o código, mas marcá-lo com um ObsoleteAttribute (ou o equivalente no seu idioma). Libere-o assim para uma versão e remova o código depois que nenhum problema for encontrado.
fonte
fonte
Removendo código inacessível
Em uma linguagem com princípios estatísticos, você sempre deve saber se o código é realmente acessível ou não: remova-o, compile-o, se não houver erro, ele não foi alcançável.
Infelizmente, nem todos os idiomas são estaticamente tipificados e nem todos os idiomas estaticamente tipificados são baseados em princípios. As coisas que podem dar errado incluem (1) reflexão e (2) sobrecarga sem princípios.
Se você usar uma linguagem dinâmica ou uma linguagem com reflexão suficientemente poderosa para que o código sob análise possa ser acessado em tempo de execução via reflexão, não será possível confiar no compilador. Essas linguagens incluem Python, Ruby ou Java.
Se você usar um idioma com sobrecarga sem princípios, a simples remoção de uma sobrecarga pode simplesmente mudar a resolução de sobrecarga para outra sobrecarga silenciosamente. Alguns idiomas permitem programar um aviso / erro em tempo de compilação associado ao uso do código, caso contrário, você não pode confiar no compilador. Essas linguagens incluem Java (use
@Deprecated
) ou C ++ (use[[deprecated]]
or= delete
).Portanto, a menos que você tenha muita sorte de trabalhar com linguagens estritas (Rust vem à mente), você pode realmente estar se atirando no pé confiando no compilador. E, infelizmente, os conjuntos de testes geralmente são incompletos, portanto também não ajudam muito mais.
Siga a próxima seção ...
Removendo código potencialmente não utilizado
Mais provavelmente, o código é realmente referenciado, no entanto, você suspeita que, na prática, as ramificações do código que fazem referência a ele nunca sejam obtidas.
Nesse caso, independentemente do idioma, o código é demonstrável alcançável e apenas a instrumentação em tempo de execução pode ser usada.
No passado, usei com sucesso uma abordagem em três fases para remover esse código:
O que é um ciclo? É o ciclo de uso do código. Por exemplo, para uma aplicação financeira, eu esperaria um curto ciclo mensal (com salários sendo pagos no final do mês) e um longo ciclo anual. Nesse caso, é necessário aguardar pelo menos um ano para verificar se nenhum aviso foi emitido para o inventário de final de ano poderia usar caminhos de código que, de outra forma, nunca seriam usados.
Felizmente, a maioria dos aplicativos tem ciclos mais curtos.
Eu aconselho a colocar um comentário TODO, com uma data, informando quando avançar para a próxima etapa. E um lembrete no seu calendário.
fonte
[[deprecated]]
para identificar sites que chamam essa versão; então você pode inspecioná-los para ver se o comportamento deles mudará. Como alternativa, defina sua sobrecarga como= delete
- nesse caso, você precisará converter explicitamente argumentos para usar uma das outras versões.Remover o código da produção é como limpar a casa. No momento em que você joga fora um objeto do sótão, sua esposa o mata no dia seguinte por jogar fora o presente de boas-vindas do terceiro sobrinho de sua bisavó de seu vizinho que morreu em 1923.
Sério, após análise superficial usando várias ferramentas que todos já mencionaram e depois de usar a abordagem de depreciação por etapas já mencionada, lembre-se de que você pode ter saído da empresa quando a remoção real ocorrer. Deixar o código permanecer e ter sua execução registrada e garantir que quaisquer alertas de sua execução sejam definitivamente comunicados a você (ou a seus sucessores e designados) são essenciais.
Se você não seguir essa abordagem, provavelmente será morto por sua esposa. Se você mantiver o código (como toda lembrança), poderá descansar sua consciência no fato de que a lei de Moore vem em seu socorro e o custo do espaço em disco inútil usado pelo código que parece uma "pedra no meu sapato" reduz todos os ano e você não corre o risco de se tornar o centro de várias fofocas e olhares estranhos nos corredores.
PS: Para esclarecer em resposta a um comentário .. A pergunta original é "Como você exclui com segurança ..", é claro, o Controle de Versão é assumido na minha resposta. Assim como cavar o lixo para encontrar o valioso, é assumido. Nenhum organismo com qualquer sentido joga fora o código e o controle de versão deve fazer parte do rigor de todos os desenvolvedores.
O problema é sobre código que pode ser supérfluo. Nunca podemos saber que um pedaço de código é supérfluo, a menos que possamos garantir que 100% dos caminhos de execução não o alcancem. E supõe-se que este seja um software suficientemente grande para que essa garantia seja quase impossível. E, a menos que eu leia a pergunta incorretamente, a única vez que todo esse segmento de conversa é relevante é nos casos durante a produção em que o código removido pode ser chamado e, portanto, temos um problema de tempo de execução / produção. O controle de versão não salva ninguém por trás de falhas de produção; portanto, o comentário sobre "Controle de versão" não é relevante para a pergunta ou o ponto original, ou seja, é preterido adequadamente por um período de tempo extremamente longo se você realmente precisar, caso contrário, não
IMHO, o comentário é supérfluo e é um candidato à remoção.
fonte
Talvez o compilador faz notar que, ele simplesmente não fazer um barulho.
Execute uma compilação com otimizações completas do compilador, voltadas para o tamanho. Em seguida, exclua o código suspeito e execute a compilação novamente.
Compare os binários. Se forem idênticos, o compilador notou e excluiu o código silenciosamente. Você pode excluí-lo da fonte com segurança.
Se os binários são diferentes ... então é inconclusivo. Poderia ser alguma outra mudança. Alguns compiladores incluem até a data e hora da compilação no binário (e talvez ele possa ser configurado fora!)
fonte
Na verdade, recentemente me deparei com essa situação exata, com um método chamado "deleteFoo". Em nenhum lugar de toda a base de código foi encontrada essa sequência além da declaração do método, mas eu sabiamente escrevi uma linha de log na parte superior do método.
PHP:
Acontece que o código foi usado! Alguns métodos AJAX chamam "method: delete, elem = Foo", que é concatenado e chamado com call_user_func_array () .
Em caso de dúvida, faça log! Se você passou um tempo suficiente sem ver o log preenchido, considere remover o código. Mas mesmo que você remova o código, deixe o log no local e um comentário com a data para facilitar a localização do commit no Git para quem precisa mantê-lo!
fonte
Use
grep
ou quaisquer ferramentas disponíveis primeiro, você pode encontrar referências ao código. (Originalmente não é minha instrução / conselho.)Em seguida, decida se você deseja arriscar remover o código ou se minha sugestão pode ser usada:
Você pode modificar a função / bloco de código para escrever que ele foi usado em um arquivo de log. Se nenhuma dessas mensagens for "sempre" registrada no arquivo de log, provavelmente você poderá remover o código de log.
Dois problemas:
Obtendo o log de outros usuários. Talvez você possa definir um sinalizador global que trava o programa na saída e solicita ao usuário que envie o log de erros.
Rastreando o chamador. Em algumas linguagens de alto nível (por exemplo, Python), você pode facilmente obter um rastreio. Mas em idiomas compilados, você precisará salvar o endereço de retorno no log e forçar um dump principal na saída (ponto 1).
Em C, isso deve ser bastante simples: use um bloco condicional (por exemplo, #ifdef ... #endif) para usá-lo apenas quando você souber que funcionará (e tiver testado isso) e simplesmente leia o endereço de retorno da pilha (pode ou não exigir linguagem assembly em linha).
Salvar os argumentos no arquivo de log pode ou não ser útil.
fonte
Se você souber qual é o código ao redor, teste-o para ver se ele quebra. Essa é a maneira mais simples e econômica de refatorar um pedaço de código no qual você está trabalhando e deve ser feito de qualquer maneira, como uma questão de desenvolver qualquer alteração no código em que você está trabalhando.
Se, por outro lado, você estiver refatorando um pedaço de código em que não sabe o que ele faz, não o remova . Entenda-o primeiro e depois refatorá-lo se você determinar que é seguro (e somente se você puder determinar que a refatoração seria um uso adequado do seu tempo).
Agora, pode haver algumas circunstâncias (eu sei que me deparei com isso) em que o código que está 'morto' não está realmente conectado a nada . Como bibliotecas de código desenvolvidas por um contratado que nunca foram implementadas em nenhum lugar porque ficaram obsoletas imediatamente após a entrega do aplicativo (por que sim, tenho um exemplo específico em mente, como você sabia?).
Pessoalmente, acabei removendo todo esse código, mas é um risco enorme que eu não recomendo assumir levianamente - dependendo de quanto código essa alteração possa potencialmente impactar (porque sempre há o potencial de que você tenha esquecido alguma coisa). deve ser extraordinariamente cuidadoso e executar testes de unidade agressivos para determinar se a remoção desse código antigo antigo quebrará seu aplicativo.
Agora, tudo isso dito, provavelmente não vale a pena gastar tempo ou sanidade mental para tentar remover um código como esse. A menos que esteja se tornando um problema sério com seu aplicativo (por exemplo, não sendo possível concluir as verificações de segurança por causa do inchaço do aplicativo ... por que sim, eu ainda tenho um exemplo em mente), não recomendaria, a menos que você chegue uma situação em que o código realmente começou a apodrecer de maneira impactante.
Então, resumindo - se você souber o que o código faz, teste-o primeiro. Se não o fizer, provavelmente poderá deixá-lo em paz. Se você sabe que não pode deixar para lá, dedique seu tempo para testar a mudança de forma agressiva antes de implementá-la.
fonte
Minha abordagem, que eu sempre assumi como padrão do setor nesse caso, estranhamente não foi mencionada até agora:
Obtenha um segundo par de olhos.
Existem diferentes tipos de "código não utilizado" e, em alguns casos, a exclusão é apropriada; em outros casos, você deve refatorá-lo; em outros casos, você foge o mais longe possível e nunca olha para trás. Você precisa descobrir qual é e, para isso, é melhor emparelhar com um segundo experiente! - desenvolvedor, alguém familiarizado com a base de código. Isso reduz significativamente o risco de erro desnecessário e permite que você faça as melhorias necessárias para manter a base de código em um estado sustentável. E se você não fizer isso, em algum momento você ficará sem desenvolvedores familiarizados com a base de código.
Também vi a abordagem de registro - para ser mais exato, vi o código de registro: ainda mais código morto que foi deixado lá por 10 anos. A abordagem de registro é bastante decente se você estiver falando sobre remover recursos inteiros, mas não se estiver apenas removendo um pequeno pedaço de código morto.
fonte
A resposta simples para sua pergunta é que você não pode excluir com segurança o código que não entende, o que inclui não entender como ele é chamado. Haverá algum risco.
Você terá que julgar a melhor forma de mitigar esse risco inevitável. Outros mencionaram o log. É claro que o log pode provar que é usado, mas não pode provar que não é. Como o maior problema com o código morto é que ele é mantido, você pode adicionar um comentário dizendo que se suspeita de código morto e não fazer nenhuma manutenção nele.
Se o código estiver sob controle de origem, você sempre poderá descobrir quando foi adicionado e determinar como foi chamado na época.
Por fim, você entende, deixa em paz ou se arrisca.
fonte
Caso o desenvolvedor do código em questão ainda esteja disponível, revise a remoção do código com ele . Além disso, ler comentários no código .
Você obterá a explicação adequada, por que esse código foi adicionado e para qual função ele serve. Pode ser facilmente suporte para o caso de uso específico, ou talvez você não tenha experiência suficiente para avaliar se realmente não é necessário. Em casos extremos, pode-se remover todas as instruções livres de um programa C e deixar de notar algo errado (pode levar alguns minutos para ficar sem memória).
É realmente uma cultura ruim quando o autor do código fica ao seu lado, mas você não vê motivos para conversar, porque tem certeza de que ele apenas escreve um código ruim e o seu é tão perfeito. E, é claro, ele apenas escreve palavras aleatórias nos comentários, sem necessidade de perder tempo lendo.
Um dos motivos mais importantes para escrever um comentário no código é explicar por que ele foi implementado dessa maneira. Você pode discordar da solução, mas precisa levar o problema em consideração.
A discussão com o autor também pode revelar que o código é o remanescente histórico de algo removido ou nunca concluído, portanto, é seguro excluir.
fonte
Concordo plenamente com o primeiro ponto de Markus Lausberg: O código deve definitivamente ser analisado com a ajuda de ferramentas. Os cérebros dos macacos não são confiáveis com esse tipo de tarefa !!
A maioria das linguagens de programação padrão pode ser usada nos IDEs e todo IDE que vale a pena ser chamado que possui um recurso "encontrar para todos os usos", que é exatamente a ferramenta certa para esse tipo de situação. (Ctrl + Shift + G no Eclipse, por exemplo)
Obviamente: as ferramentas de análise estática não são perfeitas. É preciso estar ciente de situações mais complicadas nas quais a decisão de que o método em questão está sendo chamado ocorre apenas em tempo de execução e não mais cedo (chamadas via Reflection, chamadas para funções "eval" em linguagens de script etc.).
fonte
Duas possibilidades:
fonte