Basta ler a pergunta sobre o Big Rewrites e lembrei-me de uma pergunta que eu queria responder.
Eu tenho um projeto horrível passado para mim, escrito em Java antigo, usando o Struts 1.0, tabelas com relacionamentos inconsistentes ou nenhum relacionamento e até mesmo tabelas sem chaves ou campos primários que deveriam ser chaves primárias, mas não são únicas. De alguma forma, a maior parte do aplicativo "simplesmente funciona". A maioria das páginas é reutilizada (código colado e copiado) e codificada. Todo mundo que já trabalhou no projeto o amaldiçoou de uma forma ou de outra.
Agora, há muito que eu pensava em propor à gerência superior uma reescrita total desse aplicativo horrendo. Estou lentamente tentando me divertir, mas realmente sinto que isso merece alguns recursos dedicados para que isso aconteça. Depois de ler os artigos sobre grandes reescritas, estou pensando melhor. E isso não é bom quando quero convencer meus superiores a apoiar minha reescrita. (Eu trabalho em uma empresa bastante pequena para que a proposta tenha a possibilidade de ser aprovada)
TL; DR Quando uma grande reescrita é a resposta e quais argumentos você pode usar para apoiá-la?
fonte
Respostas:
Desculpe, isso vai demorar, mas é baseado na experiência pessoal como arquiteto e desenvolvedor em vários projetos de reescrita.
As seguintes condições devem levar em consideração algum tipo de reescrita. Vou falar sobre como decidir qual deles será feito depois disso.
Essas coisas são bastante evidentes. Quando decidir sobre uma reescrita completa versus uma reconstrução incremental é mais subjetivo e, portanto, mais cobrado politicamente. O que posso dizer com convicção é que afirmar categoricamente que nunca é uma boa ideia está errado.
Se um sistema puder ser reprojetado de forma incremental e você tiver o apoio total do patrocínio do projeto para isso, deverá fazê-lo. Aqui está o problema, no entanto. Muitos sistemas não podem ser redesenhados de forma incremental. Aqui estão algumas das razões que encontrei que impedem isso (tanto técnica quanto política).
Lembre-se de que o custo total da reformulação incremental é sempre maior do que uma reescrita completa, mas o impacto na organização geralmente é menor. Na minha opinião, se você pode justificar uma reescrita e tiver desenvolvedores de superstar, faça-o.
Só faça isso se tiver certeza de que existe vontade política de fazê-lo até o fim. Isso significa a adesão de executivos e usuários finais. Sem ele, você irá falhar. Estou assumindo que é por isso que Joel diz que é uma má ideia. A entrada de executivos e usuários finais parece um unicórnio de duas cabeças para muitos arquitetos. Você precisa vendê-lo de forma agressiva e fazer campanha por sua continuação continuamente até que esteja completo. Isso é difícil, e você está falando sobre apostar em sua reputação em algo que alguns não desejam que seja bem-sucedido.
Algumas estratégias para o sucesso:
fonte
Eu participei de duas grandes reescritas. Primeiro foi um pequeno projeto. O segundo foi o principal produto de uma empresa de software.
Existem várias armadilhas:
Reescritas raramente são a resposta real. Você pode refatorar grande parte do código sem perder nada e sem muito risco.
Reescrever pode ser a resposta se:
Mas eu recomendo fortemente a abordagem lenta usando refatoração. É menos arriscado e você mantém seus clientes felizes.
fonte
É hora de reescrever quando:
O custo de reescrever o aplicativo + manter o aplicativo reescrito é menor que o custo de manutenção do sistema atual ao longo do tempo.
Alguns fatores que tornam a manutenção da atual mais cara:
//Here be dragons.
comentário está em todo o seu código.fonte
Se você precisar de uma alteração fundamental na arquitetura do projeto, talvez seja hora de começar de novo.
Mesmo com isso, haverá potencialmente grandes faixas de código que ainda valem a pena ser reutilizadas em seu novo projeto.
Preste atenção ao aviso justo. Um projeto atual terá suas regras de negócios testadas e refinadas com inúmeras horas de uso real, algo que não será verdadeiro para um projeto iniciado do zero.
Duvido que um período de tempo ou sensação de intestino seja uma medida apropriada de uma medida tão drástica. Você deve ter razões claras , defensáveis e bem compreendidas para participar deste curso de ação.
fonte
Embora eu concorde com a resposta de Kramii e a opinião de Joel, há momentos em que é apropriado reescrever. Em aplicativos de longa duração (estou falando de 10 a 20 anos ou mais), a manutenção se torna cada vez mais cara ao longo do tempo. Isso ocorre porque o código se torna cada vez mais espaguete, pois a arquitetura original é sacrificada por patches de manutenção rápida. Além disso, os desenvolvedores de tecnologias mais antigas se tornam mais raros e mais caros. Finalmente, o hardware começa a envelhecer e fica cada vez mais difícil encontrar novos hardwares, sistemas operacionais, estruturas etc. para executar o aplicativo antigo. Além disso, as empresas evoluem e, muito provavelmente, um sistema mais antigo não atenderá às necessidades de negócios da organização, assim como um sistema totalmente novo.
Portanto, é necessário ponderar todo o custo de manutenção em andamento, bem como os benefícios potenciais de um novo sistema para os negócios, contra o custo de reescrever a coisa do zero. Seja muito pessimista em suas estimativas sobre o custo de uma reescrita. Quase sempre custa mais e leva mais tempo do que você imagina.
fonte
Pare! Reescrever quase nunca é a resposta. Mais frequentemente, refatorar é uma aposta melhor.
Claro, existem são momentos em que uma reescrita é justificada:
Para entender por que recomendo refatorar em vez de reescrever, considere o que está envolvido em uma reescrita. Você deve:
Entenda as nuances do que o aplicativo existente faz. Isso geralmente não é trivial quando você leva em consideração todas as regras sutis de negócios que ele encapsula, o ambiente (humano e técnico) em que opera e as vantagens e desvantagens da solução atual. Na maioria das vezes, o único local em que essas informações existem (se houver) é o código-fonte do aplicativo existente. É lamentável que uma das principais razões para a reescrita seja a dificuldade de entender e manter o código existente.
Reproduza essa funcionalidade (ou uma versão atualizada dela) em um novo aplicativo testado e confiável. O código existente pode não ser entendido pelos desenvolvedores, mas geralmente é bem entendido pelos usuários. Pode não atender às necessidades atuais dos negócios, mas eles podem pelo menos informar o que o aplicativo faz em várias circunstâncias.
As grandes vantagens da refatoração são as seguintes:
Lembre-se também de que, se você reescrever, é garantido que você introduzirá muitos novos bugs e bagunça na nova base de código.
fonte
Este gráfico pode ajudar, é uma função da qualidade da base de código e do valor comercial do aplicativo:
O gráfico pretende ser um guia sobre quando uma reengenharia de software legado é justificada e quando não é. Por exemplo, se o software tiver alto valor comercial e a qualidade do código for ruim, uma reengenharia será justificada.
fonte
Acho que estou na única situação na minha carreira em que a grande reescrita é a resposta:
Fusão da empresa, enorme sobreposição na funcionalidade dos sistemas. Muitos, muitos sistemas foram mesclados e aposentados, e outros ainda estão em processo.
Eu herdei um sistema da outra empresa que ainda vive. Ele possui uma enorme base de códigos, que costumava suportar vários departamentos muito semelhantes aos nossos, mas com um design e estruturas completamente diferentes. Resta apenas um setor comercial, que ganha dinheiro suficiente para manter essa coisa viva em um estado de zumbi. Toda a antiga experiência se foi, não há documentação. A carga de suporte é alta, com falhas a cada semana. Ele não foi incorporado aos sistemas de nossas empresas, porque nossa empresa nunca deu suporte a esse setor específico dos negócios, portanto, não temos a funcionalidade ou o conhecimento.
Parece que este é o único caso em que a reescrita é necessária. Parece que vou ter que descobrir esse gigante, extrair os bits de funcionalidade dedicados a esse negócio e reescrever as partes que precisam ser adicionadas aos nossos sistemas existentes. Feito isso, nossos sistemas existentes podem apoiar esse novo setor, e essa fera pode ser eliminada de sua miséria. Caso contrário, vou perder minha sanidade.
fonte
Trabalhei para uma pequena empresa de software que tinha alguns aplicativos DOS atualizados para lidar com o Y2K, reescritos como um aplicativo Windows de 16 bits e totalmente reescritos como um aplicativo de 32 bits com um recurso 'pequeno' adicional (utilizado apenas por um cliente) que impactou toda a estrutura.
Mover o código de 16 bits para 32 poderia ter sido feito em um mês por uma pessoa, mas NOOOOOOOOO, tivemos que reescrevê-lo para tornar o Sooooooooo muito melhor. Essa coisa poderia ser adaptada para outras indústrias, teria especificações completas e código psuedo antes mesmo de começar. As especificações foram criadas, mas demorou tanto tempo que nem houve tempo para escrever o código real. Foi lançado tarde, com mais bugs do que o de 16 bits 'iniciado' (foi na v.3.0 e, finalmente, ao ponto em que quase chegamos a uma semana sem que alguém relatasse um novo bug).
Você pensaria que reescrever o mesmo aplicativo de 3 a 4 vezes traria algumas melhorias, mas não acho que um front-end da GUI possa ser justificado tanto assim.
Este foi meu primeiro trabalho em TI como chefe de suporte técnico. Eu deveria escrever um livro sobre como não desenvolver software para distribuição. Obviamente, cometemos muitos erros, mas o fato de continuarmos reescrevendo aplicativos aumentou a incompetência.
fonte
Eu tive um caso muito parecido com o seu, mas o código nem estava usando Struts. Em vez disso, o que fiz foi direcionar as áreas que eram particularmente ruins e causar muitos problemas. Essa abordagem direcionada nos permitiu melhorar cada vez mais.
Durante um período de 2 anos, trabalhamos na refatoração de pedaços e peças juntamente com o trabalho de aprimoramento. Sempre trabalhamos uma tarefa de 'proteção' em um plano de projeto. Ao focar nas áreas específicas que não funcionaram bem, obtivemos o máximo de retorno. O material que funcionou, deixamos em paz. Também crítico é que este trabalho foi realizado no curso do desenvolvimento normal e foi lançado. O problema de uma grande reescrita é que você sai por um ano ou mais e, quando volta, tudo muda de qualquer maneira, e alguns dos erros desagradáveis são suavizados e você perde seu ROI.
Nós nunca reescrevemos a coisa toda. No entanto, paramos de usar essa plataforma para novos trabalhos e lançamos uma nova plataforma para um grande projeto novo. Isso foi aprovado e entregamos um ótimo produto em um período de tempo razoável.
fonte
Então, aqui estou eu sentado na minha mesa, comecei a reescrever o código dessa bagunça absoluta de um grande arquivo aspx, o banco de dados por trás dele, e a substituição da interface do MS Access para o MsSQL.
Este programa asp está cheio de coisas como
include(close.aspx)
que possui uma linha de código que fecha a última conexão de banco de dados aberta.Se precisarmos fazer uma pequena alteração, é como jogar cinco jogos simultâneos de kal-toh no modo pesadelo.
Fui contratado para replicar a funcionalidade e criar um produto que pudesse ser personalizável e vendável para outras pessoas do setor. O problema é que essa coisa foi escrita nos últimos 10 anos para preencher todas as necessidades de negócios (bem, eu diria cerca de cinco ou seis sigma delas).
Se não quiséssemos vender o produto, eles provavelmente não precisariam de uma reescrita, pois fazem a maior parte do que eles querem - talvez não com elegância, mas não era prudente gastar o dinheiro na criação de um bom código 'Faça a mesma coisa.'
fonte
Joel Spolsky tem um excelente artigo sobre isso: Coisas que você nunca deve fazer, Parte I
Do título que você pode dizer, é meio unilateral (ele fala sobre por que você nunca deve lançar código) IMO, há muita verdade, recentemente vi um vídeo do canal9 no 25º aniversário do Excel, onde alguns desenvolvedores disseram como ainda hoje, se você visse o código-fonte, verificaria a revisão e acabaria voltando ao código usado pelo Excel que foi escrito há 20 anos.
Você não pode ser 100% de certeza (quando até mesmo Netscape comete erros (de Joels artigo)), eu me senti como o artigo do Joel foi Deus enviou, porque eu posso ser pessimista e amor jogando fora pensamento código que eu sempre pode escrevê-lo melhor uma segunda tempo, mas só agora percebi que isso custa muito .
Para dar uma resposta concreta, eu apenas diria que você precisa fazer uma análise completa de custo x valor .
Meu mundo real: um aplicativo silverlight que estou desenvolvendo a v0.6 até agora tem uma confusão de chamadas assíncronas que tornam o código tão complicado. Desde que descobri as Extensões reativas esta semana, quero realmente reescrever a maior parte do código, mas agora o que digo a meu cliente? O programa funciona perfeitamente bem (com alguns vazamentos de memória), mas eles não se importam? Não posso dizer a eles: Oh, estou tomando mais 2-3 semanas porque quero refazer alguma coisa. No entanto, estou indo para ramificar o código e reescrever / jogar com ele no meu tempo livre .
Apenas meus 2 centavos ok !?
fonte
A solução existente não é escalável.
Estou olhando para você, MS Access.
fonte
Segundo Joel, grandes reescritas são o pior erro estratégico que uma empresa pode cometer:
Coisas que você nunca deve fazer, parte I
fonte
Nunca, refatorar sempre - a verdade é que se o código foi escrito por você - você não poderá fazer melhor.
A menos que você queira mudar a tecnologia, o código não possui nenhuma estrutura (eu o vi há muito tempo em algum site PHP, o autor simplesmente copia / cola spahgetti em vez de include / class / function) ou você assumiu algo de outra pessoa que muito mal escrito.
Tudo deve ser projetado como uma caixa preta. API simples e modular, o que há dentro ... isso é menos importante :) Se você tem espaguete, talvez seja possível fechá-lo dentro de uma caixa preta, para que não contamine um bom código.
fonte
Eu acho que o principal motivo que justifica as reescritas são as mudanças na plataforma. Por exemplo, se você tiver um aplicativo GUI da área de trabalho do Windows e o proprietário da empresa decidir que deseja que a próxima versão seja um aplicativo baseado na Web. Embora nem sempre, na minha experiência na maioria das vezes, isso exigirá uma reescrita, a menos que os desenvolvedores originais escrevam código muito modular e reutilizável (dificilmente acontece).
fonte
Existe a piada clássica sobre "se eu estivesse indo para o XI não começaria daqui".
Peguei um emprego uma vez, onde a principal motivação do empregador era trazer talentos a bordo para lançar uma reescrita há muito tempo atrasada de um aplicativo crítico para os negócios. A pergunta que não fiz foi: por que você acabou nessa situação em primeiro lugar? Deveria ter sido uma bandeira vermelha, se a causa foi
muita pressão para adicionar funcionalidade para manter e refatorar gradualmente a fera,
pouca capacidade no departamento,
muito pouco comprometimento dos clientes ou da gerência para trabalho incremental,
ou seja o que for, e isso causa apodrecimento até o problema atingir um nível intolerável.
Então, eu vou concordar com Joel em que uma reescrita maciça é provavelmente uma péssima idéia - a menos que você tenha evidências firmes de que todas as razões subjacentes às quais uma reescrita principal parece tão necessária foram tratadas , você provavelmente vai repetir o problema no devido tempo.
fonte
É a resposta quando a reescrita permite que a organização siga uma estratégia que ofereça uma vantagem competitiva ou que atenda melhor seus clientes de alguma maneira que a arquitetura atual não possa acomodar.
Em vez disso, as reescritas geralmente acontecem para aliviar as preocupações de gerenciamento:
A maioria dessas preocupações não se concretiza e, se o fizessem, poderiam ser tratadas. Esse último, no entanto, é o pior. É essencialmente: não temos um motivo.
Sim, como o carro, um sistema começará a mostrar sinais de desgaste. Isso pode ser aliviado pela manutenção de rotina. Você sabe o que eles dizem sobre como um pouco de manutenção preventiva percorre um longo caminho. Como investimento, a manutenção de rotina (ou seja, refatoração e padronização) quase sempre acarreta um custo menor do que uma reescrita.
No entanto, precisamos antecipar que uma reescrita será eventualmente necessária. Defina datas e planeje-o provisoriamente, mas à medida que a data se aproxima mais, é possível realizar outras metas estratégicas até que você tenha um motivo convincente como ...
Nos últimos anos, perdemos a oportunidade de ganhar grandes contas, porque não podíamos acomodar suas necessidades em tempo hábil ou caro. Nosso sistema será reescrito usando uma arquitetura extensível que permita que as personalizações sejam conectadas (e não codificadas como fazemos atualmente). Isso diminuirá drasticamente o tempo e o custo de acomodar clientes com necessidades especiais. Ganharemos mais contas e atenderemos melhor às necessidades de nossos clientes atuais.
fonte
Ao mudar para uma tecnologia completamente nova, é necessário fornecer a funcionalidade desejada.
"Completamente novo": se você planeja reescrever, mas usa a mesma plataforma, a refatoração e a reestruturação criteriosa são quase certamente a melhor solução. "Plataforma", como usada aqui, é um tanto vaga - considere incluir linguagem e talvez o sistema operacional (estendendo-se do Linux ao Windows ou vice-versa), mas provavelmente não a estrutura (por exemplo, substituindo o Struts pelo Spring).
"Necessário para fornecer a funcionalidade desejada": por volta de 2000, iniciei um projeto para reescrever um componente principal do servidor em Java a partir do C ++ para permitir o encadeamento pronto para uso, um cache de objetos e transações controladas pelo cliente. Naquela época, havia várias bibliotecas de encadeamento para C ++ que precisávamos suportar, e a habilitação de encadeamento grande parte do código do banco de dados exigiria uma reescrita quase total. Quanto às transações controladas pelo cliente ... não acontecerão com a arquitetura antiga.
Mesmo assim, não tenho certeza de que teria reescrito, exceto que tinha conhecimento detalhado do comportamento do sistema atual e era um código relativamente limpo que não havia desenvolvido muitas verrugas em seus 11 anos de vida.
fonte
Para decidir o ponto em que você deve recomeçar, você precisa descobrir onde o valor de continuar em seu projeto atual fica aquém do valor em recomeçar.
A razão pela qual isso é tão difícil é que você faça uma estimativa precisa da velocidade de desenvolvimento da equipe no novo projeto até que você realmente o inicie. Dito isto, se, usando uma estimativa MUITO conservadora de sua velocidade de desenvolvimento no novo projeto, estima-se que o projeto ofereça um retorno sobre o investimento valioso, você terá um caso de negócios para começar de novo.
fonte
Com minha métrica, você precisa atender a duas condições para justificar uma reescrita:
Mesmo assim, você deseja limitar o escopo de sua reescrita. Por exemplo, tínhamos algum software legado em uma empresa que foi escrita em C ++ com a mentalidade de um programador de C que não sabia sobre modularidade. O resultado final foi o código speghetti na forma de uma máquina de estados finitos que abrangia várias classes e DLLs. Tínhamos um novo requisito que era muito diferente das suposições embutidas no código e faria parte do valor agregado patenteado da empresa para seus clientes.
Depois de passar um tempo com o código implementando outros recursos, tive uma idéia muito boa de quanto tempo levaria para descobrir qual das várias instruções de chave eu precisaria alterar etc. Minha proposta era reescrever a seção de código que era a enorme máquina de estados finitos - levaria menos tempo do que estender o código existente. Consegui consolidar em uma DLL o que costumava ser três, e fornecer uma estrutura muito mais orientada a objetos que facilitaria muito a execução da nova funcionalidade crítica, além de facilitar a adição de novas funcionalidades.
Havia três outros aplicativos usando as bibliotecas que precisavam ser reescritos, então eu não queria ter que reescrever completamente esses programas. O escopo era limitado à biblioteca e o que era necessário para vincular a biblioteca ao software existente. Minhas estimativas não foram muito longe e o trabalho se pagou. Logo após o redesenho, fui encarregado de adicionar um novo recurso. O que teria me levado uma semana com a estrutura antiga levou apenas um dia com a nova estrutura.
fonte
O OP não indica o escopo do projeto, mas a pista principal que tomei foi "escrita em [idioma / dialeto] antigo usando [libs] antigas" que, para mim, são os principais drivers de uma reescrita. De fato, a maioria dos projetos em que tenho alguma longevidade significativa no mercado acaba percebendo que a atualização de compiladores / intérpretes / sistemas operacionais é uma tarefa importante para manter a base de código.
Em resumo, planejaria a reescrita em fases, priorizando primeiro a atualização nas bibliotecas. Pode ser que, ao longo do caminho, você possa se infiltrar em outras otimizações, mas o fato de planejar adiar algumas alterações para uma fase posterior pode ser uma ótima maneira de manter o cronograma e evitar "ficar preso".
fonte
Bem, eu posso imaginar cenários hipotéticos em que eu possa simplesmente jogar fora a base de código existente (situações hipotéticas em que as bolas de bucky têm peso e volume zero, onde ninguém se importa se perdermos semanas ou meses de produtividade enquanto lutamos para adicionar recursos e erros negligenciados corrige o sistema, e onde o sistema é tão trivial e odiado por uma organização que posso substituir a coisa toda e o exército de servidores pelo bloco de notas ++ e um netbook em dez minutos e aumentar a produtividade e a moral de todos.)
Para praticamente qualquer cenário do mundo real, eu recomendaria apenas a refatoração. ^ _ ^. Há muitos custos ocultos e imprevistos para reescrever quando os requisitos legais e de negócios não documentados começam a aparecer e o último minuto de hackers juntos no último minuto começa a acontecer.
== Refatoração no local para maior bem e outras coisas ==
Refatorando o código legado com a abordagem incremental antiga regular,
Ramificação por abstração
Princípio fechado aberto e uma camada comum de lógica / persistência comercial
Até certo ponto, talvez você consiga se livrar da camada de apresentação, negócios e persistência e escrevendo um novo aplicativo que seja totalmente compatível com a solução herdada ou, no mínimo, ainda possa lidar com os dados introduzidos pela solução herdada. Provavelmente, eu não recomendaria essa abordagem, mas às vezes é um compromisso razoável de tempo / cronograma / recursos / nova funcionalidade necessária.
fonte
Eu diria que existe uma terceira categoria no espaço Refactor vs Rewrite ... E isso está atualizando suas versões de idioma, compiladores e bibliotecas ... Às vezes, apenas a adoção de técnicas modernas de codificação traz um grande benefício.
Pegue o C #, por exemplo, o código v7 escreve muito mais limpo, mais seguro e mais conciso que o v2. Coisas como o Elvis e o operador coalescente nulo ajudam muito.
Alternar compiladores também pode dar vida nova a códigos mais antigos. Assim como as novas bibliotecas que podem facilitar as coisas para trabalhar e implementar ... A rede é um ótimo exemplo de um espectro de dificuldades de implementação.
Também - sistemas linux embutidos ... Pense em instalar novas ferramentas - mude para o git a partir do svn. ou adicione o Vi ao seu sistema, etc.
Nem sempre é necessário refatorar ou reescrever. Sua arquitetura provavelmente está precisando de melhorias, mas funciona ... talvez você só precise pensar em como seu código é escrito etc.
fonte
Acho que nunca vi pessoas reescrevendo um aplicativo herdado.
O que acontece é que as pessoas estão escrevendo aplicativos totalmente novos com uma arquitetura, tecnologias, etc. diferentes, que têm alguns recursos em comum com a geração anterior. E é chamado app 2.0, mas na verdade tem muito poucas coisas em comum com o original.
Mas isso não é realmente uma "reescrita" do original, no sentido de que você está tentando alcançar a paridade de recursos.
fonte