O código antigo deve ser atualizado para usar construções de linguagem mais recentes, ou as construções obsoletas devem ficar presas?

15

Eu quero fazer alguns aprimoramentos em algum código ainda funcional que foi escrito há muito tempo, antes que a linguagem de programação em que ele é escrito crescesse em recursos. Em teoria, todo o projeto usa a versão atualizada da linguagem; no entanto, este módulo específico (e, na verdade, muitos outros módulos) ainda são escritos no dialeto mais antigo.

Eu deveria:

  • Não toque nas partes do código que não preciso tocar, mas escrevo meu patch fazendo uso dos novos recursos de idioma que facilitam a gravação do patch, mas não são usados em situações análogas em nenhum outro lugar do módulo? (Essa é a solução que eu escolho intuitivamente).
  • Ignore o fato de que anos se passaram e reflita o estilo que é usado no resto do código enquanto escrevo meu patch, me comportando efetivamente como se estivesse fazendo a mesma tarefa muitos anos antes? (Esta solução eu intuitivamente considero boba, mas dada a quantidade de barulho que todo mundo que fala sobre "código bom" faz com que você mantenha a consistência a todo custo, talvez seja isso que eu devo fazer.)
  • Atualize todo o módulo para usar as construções e convenções de linguagem mais recentes? (Esta é provavelmente a melhor solução, mas pode exigir muito tempo e energia que poderia ser melhor gasto em uma tarefa diferente.)
por gaazkam 25.03.2017 / 00:17
fonte

5 respostas

10

É impossível dar uma resposta definitiva a esta pergunta, porque depende muito das particularidades da situação.

A consistência no estilo da base de código é importante porque ajuda a tornar o código mais fácil de entender, o que é um dos aspectos mais importantes da sustentabilidade.
Você não seria o primeiro programador que foi amaldiçoado ao inferno por tornar o código difícil de entender, misturando estilos diferentes. Pode até ser você mesmo que amaldiçoa daqui a alguns anos.

Por outro lado, o uso de novas construções de linguagem que não existiam quando o código foi escrito pela primeira vez não implica automaticamente que você esteja reduzindo a capacidade de manutenção ou mesmo que esteja quebrando o estilo do código. Tudo depende dos recursos específicos do idioma que você deseja usar e da familiaridade do time com o estilo antigo do código e os novos recursos.

Como exemplo, geralmente não seria aconselhável começar a introduzir conceitos de programação funcional como map / reduce em uma base de código que é completamente em estilo OO, mas poderia funcionar para adicionar uma função lambda aqui e ali a um programa que não não use nada assim antes.

    
por 25.03.2017 / 10:38
fonte
5

Em grande medida, o código e a aparência dele são irrelevantes . O que o código faz é o que importa.

Se você puder garantir que mudar / reescrever o código não mudará o código, então você pode refazer o código para o conteúdo do seu coração. Essa "garantia" é um conjunto exaustivo de testes unitários que você pode executar antes e depois de suas alterações, sem diferença perceptível.

Se você não puder garantir essa estabilidade (você não fez esses testes), então deixe-a bem sozinha.

Ninguém vai agradecer por "quebrar" um software crítico para os negócios, mesmo que você esteja tentando "melhorar". "Trabalhar" supera "melhor" o tempo todo.

Claro, não há nada que impeça você de criar um conjunto de testes desse tipo preparação para esse tipo de exercício ...

    
por 28.03.2017 / 12:30
fonte
3

Quase tudo pode ser analisado em termos de custos e benefícios, e acho que isso se aplica aqui.

Os benefícios óbvios da primeira opção são que ela minimiza o trabalho a curto prazo e minimiza as chances de quebrar alguma coisa reescrevendo o código de trabalho. O custo óbvio é que isso introduz inconsistência na base de código. Quando você está fazendo alguma operação X, ela é feita de uma maneira em algumas partes do código e de uma maneira diferente em uma parte diferente do código.

Para a segunda abordagem, você já observou o benefício óbvio: consistência. O custo óbvio é que você tem que curvar sua mente para trabalhar de maneiras que você pode ter abandonado anos atrás, e o código permanece consistentemente ilegível.

Para a terceira abordagem, o custo óbvio é simplesmente ter que fazer muito mais trabalho. Um custo menos óbvio é que você pode quebrar coisas que estavam funcionando. Isso é particularmente provável se (como é frequentemente o caso) o código antigo tiver testes inadequados para garantir que continue funcionando corretamente. O benefício óbvio é que (supondo que você faça isso com sucesso) você tem um novo código brilhante e bonito. Juntamente com o uso de novas construções de linguagem, você tem a chance de refatorar a base de código, que quase sempre dará melhorias em si mesmo, mesmo se você ainda usou a linguagem exatamente como ela foi escrita - adicione novas construções que fazem a linguagem trabalho mais fácil, e pode muito bem ser uma grande vitória.

Um outro ponto importante: no momento, parece que este módulo teve manutenção mínima por um longo tempo (embora o projeto como um todo esteja sendo mantido). Isso tende a indicar que é muito bem escrito e relativamente livre de bugs - caso contrário, provavelmente teria sofrido mais manutenção nesse ínterim.

Isso leva a outra pergunta: qual é a origem da mudança que você está fazendo agora? Se você está consertando um pequeno bug em um módulo que ainda atende bem aos seus requisitos, isso tenderia a indicar que o tempo e o esforço para refatorar todo o módulo provavelmente serão em grande parte desperdiçados - quando alguém precisar mexer com de novo, eles podem estar mais ou menos na mesma posição em que você está agora, mantendo um código que não atende às expectativas "modernas".

Também é possível, no entanto, que os requisitos mudaram e você está trabalhando no código para atender a esses novos requisitos. Nesse caso, há boas chances de que suas primeiras tentativas não atendam aos requisitos atuais. Há também uma chance substancialmente maior de que os requisitos passem por algumas rodadas de revisão antes de se estabilizarem novamente. Isso significa que é muito mais provável que você esteja fazendo um trabalho significativo neste módulo no prazo (relativamente) próximo, e muito mais propenso a fazer alterações em todo o restante do módulo, não apenas na única área sobre a qual você sabe agora. Nesse caso, é muito mais provável que refatorar o módulo inteiro tenha benefícios tangíveis a curto prazo que justifiquem o trabalho extra.

Se os requisitos foram alterados, talvez seja necessário analisar o tipo de mudança envolvido e o que está gerando essa alteração. Por exemplo, vamos supor que você estava modificando o Git para substituir o uso do SHA-1 pelo SHA-256. Esta é uma mudança nos requisitos, mas o escopo é claramente definido e bastante restrito. Depois de ter feito isso, armazenar e usar o SHA-256 corretamente, é improvável que você encontre outras alterações que afetem o restante da base de código.

Na outra direção, mesmo quando ela começa pequena e discreta, uma alteração em uma interface do usuário tende a aumentar, então o que começou como "adicionar uma nova caixa de seleção a essa tela" termina mais como: "alterar esta UI fixa para suportar modelos definidos pelo usuário, campos personalizados, esquemas de cores personalizados, etc. "

Para o primeiro exemplo, provavelmente faz mais sentido minimizar as mudanças e errar do lado da consistência. Para o último, a refatoração completa é muito mais provável de pagar.

    
por 27.03.2017 / 20:44
fonte
1

gostaria de ir para você primeira opção. Quando eu codifico eu sigo a regra para deixá-la em um estado melhor, então foi.

Assim, o novo código segue as práticas recomendadas, mas não tocarei em código que não esteja relacionado aos problemas em que estou trabalhando. Se você fizer isso bem, seu novo código deve ser mais legível e passível de manutenção do que o código antigo. Eu descobri que a manutenção total fica melhor, porque se você continuar assim, o código que você precisa tocar para o seu trabalho é cada vez mais o código "melhor". O que leva a uma resolução mais rápida de problemas.

    
por 28.03.2017 / 12:43
fonte
1

A resposta, como tantas outras coisas, é depende . Se houver grandes vantagens em atualizar as construções antigas, como a manutenção a longo prazo amplamente melhorada (evitando callbacks infernais, por exemplo), então vá em frente. Se não há grande vantagem, a consistência é provavelmente sua amiga

Além disso, convém evitar incorporar dois estilos na mesma função mais do que você deseja evitar em duas funções separadas.

Resumindo: sua decisão final deve se basear em uma análise de 'custo' / 'benefício' do seu caso particular.

    
por 28.03.2017 / 12:52
fonte