Desenvolvendo uma solução melhor, vindo da base de código existente [duplicata]

5

O código

Tenho software de uso diário por cliente de alto valor comercial, escrito em PHP e com aproximadamente 600 mil linhas de código.

O cliente há muito tempo precisa, quer e exige novos recursos e funcionalidades. A hora de fazê-lo é ontem . Então, basta escrever os novos recursos e implementar novas funcionalidades e entregá-las ao cliente, sim? Bem, não, aqui estão alguns problemas que vêm causando uma dor considerável aos desenvolvedores atuais:

A base de código existente é ... uma grande bola de lama .

Problemas notáveis:

    O código
  • é cabeludo - um único recurso permeia tudo, o código de rastreamento é penoso e a adição de um recurso pode afetar todo o restante
  • não há testes
  • mistura de código procedural e orientado a objetos montado em práticas de programação ruins
  • arquivos alcançando 6000 linhas de HTML, CSS, PHP, SQL, jQuery, JavaScript, comentários
  • completa desconsideração / inexistência do padrão MVC / separação de preocupações. O código é misturado
  • alguma lógica de negócios depende de coisas voláteis que não têm relação com o código (como metadados do banco de dados)
  • valores codificados, caminhos e falta de configurabilidade contribuem para a falta de segurança da arquitetura atual
  • grandes blocos repetidos de essencialmente o mesmo código contribuem para que recursos semelhantes funcionem de maneira ligeiramente diferente. A atualização de um não atualiza o outro
  • o código é lento, a falta de documentação, etc., etc. muitas outras coisas podem ser feitas melhor

Funciona ...

A coisa boa é que funciona ... A funcionalidade que está lá, é razoavelmente trabalhada para casos de negócios reais, mas ... indo para frente é doloroso.

O problema

É mais fácil agora (e mais rápido) adicionar um novo recurso usando o estilo de código existente, usando principalmente a abordagem cut-n-paste-n-modify, perpetuando a maldade, do que reescrevê-lo usando atualmente melhores práticas modernas existentes.

Solução?

Fala-se sobre reescrever tudo usando uma das estruturas atualmente líderes (ou seja, ZF2), mas isso significa ignorar as demandas do cliente, levar muito tempo para construir o software e, essencialmente, criar um novo software ( versão 0.0.1) para o cliente, com todos os bugs do novo software e falta de sensibilidade e funcionalidade do software maduro.

Outro pensamento é fazer algum desenvolvimento incremental. Ou seja, quando uma nova funcionalidade surge, escreva-a usando uma nova abordagem. No momento, isso está falhando pelo motivo indicado no título "O problema" acima.

Outra idéia é fazer uma lenta refatoração da base de código existente ... Pode funcionar na limpeza de coisas como o MVC e uma série de outras coisas, e isso levará muito tempo, e será essencialmente como desvendar um bagunçado firmemente enrolado bola de fios. Mas fazer isso não resolverá problemas como testes de unidade, injeção de dependência, princípios de estrutura moderna e assim por diante.

Então, no final, novos recursos estão chegando, código está sendo adicionado e a base de código existente não está melhorando. O que você sugere para fazer neste caso?

    
por Dennis 10.02.2014 / 23:03
fonte

3 respostas

3

But doing this will not address things like unit testing, dependency injection, modern framework principles, and so on.

Por que não? Você não precisa testar tudo - apenas o que você muda / refaz. E se você testar isso, você adicionará progressivamente mocks e DI.

Eu recomendo strongmente o livro de Michael Feather: Trabalhando efetivamente com o código legado , pois descreve bem esse problema e as soluções.

    
por 10.02.2014 / 23:57
fonte
2

Estou em uma situação semelhante, se bem em uma pilha de tecnologia completamente distinta, e no meu caso (e eu acho que também no seu) é bastante óbvio que toda uma reescrita do código de produção não é uma opção, devido limitações práticas. Isso faz mais sentido é levá-lo em pequenos passos. Quando você é obrigado a introduzir um novo recurso, você o faz de uma maneira mais gerenciável; quando você tem que modificar um módulo / classe / método / qualquer coisa existente, você aproveita a oportunidade e a refaz. Sempre tente terminar com um código melhor, se talvez à custa de reduzir um pouco a sua velocidade, a fim de obter alguma folga para pagar sua dívida. Além disso, se você puder introduzir silenciosamente uma estrutura que possa ser útil a longo prazo, enquanto coexistir com a lama atual, considere isso.

    
por 10.02.2014 / 23:27
fonte
0

A duplicação em si não é um problema - é uma maneira de obter resultados rápidos. Você só precisa lembrar que tem dívida tecnológica e aloca tempo para generalizar seu código no futuro.

O que você quer dizer com going forwards is painful - você está planejando algo grande ou são apenas recursos adicionais? Há apenas uma razão para reescrever tudo - o caso em que a arquitetura de sua aplicação atual não se ajusta ao seu desenvolvimento futuro.

Uma vez tive um projeto que desenvolvi por vários meses e não estava particularmente 'sujo'. Eu também fiz testes unitários. E, em seguida, o requisito mudou e levei mais dois meses para entender que preciso mudar a arquitetura. Depois que percebi, passei 3 semanas reescrevendo completamente esse serviço - era um desenvolvimento ativo, mas eu sabia o que fazer.

Eu acho que o seu caso é diferente - você só precisa gastar mais tempo com a limpeza. Comece com pequenas coisas. Durante a próxima correção de erros ou implementação de um novo recurso, não entre no desenvolvimento. Passe algum tempo limpando. Tome uma regra para melhorar um pouco qualquer código tocado por você. É claro que sem testes de unidade é arriscado - e você entenderá isso muito rapidamente, então da próxima vez você terá mais atenção para escrever testes de unidade.

Ao mesmo tempo, você precisa começar a pensar em design de alto nível para começar a generalizar e decompor o sistema. Estritamente falando, isso não é refatoração. As pessoas tendem a abusar desse termo.

    
por 11.02.2014 / 10:49
fonte