Em uma base de código herdada, como descubro rapidamente o que está sendo usado e o que não está?

21

Pediram-me para avaliar o que parece ser uma base de código herdada substancial, como precursora de um contrato mantendo essa base de código.

Esta não é a primeira vez que estive nessa situação. No presente caso, o código é para um site multijogador razoavelmente alto e bastante carregado, suportando pelo menos vários milhares de jogadores on-line ao mesmo tempo. Como muitos desses sites são, este é um mix de tecnologias de front e back-end.

A estrutura do site, vista de dentro para fora, é uma bagunça. Há pastas com o sufixo "_OLD" e "_DELETE" espalhadas por todo o lugar. Muitas das pastas parecem não ter nenhum objetivo ou têm nomes muito enigmáticos. Pode haver vários scripts antigos e não utilizados espalhados, mesmo em pastas com aparência legítima. Não apenas isso, mas há, sem dúvida, muitas seções de código desativadas, mesmo em scripts operacionais (uma preocupação muito menos premente).

Esta é uma transferência dos mantenedores históricos, de volta aos desenvolvedores / mantenedores originais do site. Como é compreensivelmente típico nesses tipos de cenários, o titular não quer nada com a transferência além do que é contratualmente e legalmente exigido deles para enviá-la ao mantenedor recém-eleito. Portanto, extrair informações da estrutura do site existente do titular está simplesmente fora de questão.

A única abordagem que vem à mente para entrar na base de código é começar na raiz do site e navegar lenta mas seguramente pelos scripts vinculados ... e provavelmente há centenas em uso e outras centenas que não. Como uma parte substancial do site está no Flash, isso é ainda menos direto, pois, principalmente em aplicativos Flash mais antigos, os links para outros scripts podem ser incorporados nos binários (.FLAs) e não nos arquivos de texto (.AS / ActionScript).

Então, eu estou querendo saber se alguém tem melhores sugestões sobre como abordar a avaliação da base de código como um todo para manutenção. Seria maravilhoso se houvesse alguma maneira de ver um gráfico da frequência de acesso a arquivos no sistema operacional do servidor da web (ao qual eu tenho acesso), pois isso pode oferecer algumas dicas sobre quais arquivos são mais críticos, mesmo que isso não ocorra. ser capaz de eliminar os arquivos que nunca são usados ​​(já que alguns arquivos podem ser usados ​​apenas uma vez por ano).

Engenheiro
fonte
7
Não sei o suficiente sobre o flash, mas se você receber erros de compilação quando o código não estiver presente, poderá renomear pastas para ver se elas são referenciadas.
Oded
Solução maligna: exclua-os e aguarde os relatórios de erros / bugs. (Apenas certifique-se que é recuperável!)
Izkata
1
@ Nick Você poderia esclarecer se está sendo pago pela avaliação como parte da próxima fase do contrato em que ainda precisa fazer uma licitação? Sua resposta não mudará a pergunta "existe uma ferramenta", mas alguns de nós poderiam elaborar respostas re: processos que seriam mais adequados à sua situação (por exemplo, evitar que você se ferre, etc).
jcmeloni
@jcmeloni Não, não estou sendo pago pela avaliação. Mas na minha experiência , e pelas pequenas coisas que aprendi nos últimos dias, eles não têm mais ninguém na mesa no momento. Meu conjunto de habilidades é bastante incomum, por isso estou ainda mais à vontade porque eles não têm mais ninguém competindo por isso, com base na citação. A cotação real em questão é do futuro cliente para o cliente dele, que planeja recontratar o contrato. Realmente do meu fim, pretendo ajudá- los a fornecer a referida citação. HTH.
Engenheiro de
@Oded Rename é definitivamente mais fácil do que a exclusão por tentativa e erro! Bom pensamento lá. Essa é mais uma ferramenta na caixa.
Engenheiro de

Respostas:

32

Como o que você está sendo solicitado a fazer é fornecer informações para que seu cliente escreva uma proposta apropriada para o outro cliente (código do proprietário do pesadelo) para qualquer trabalho nesse código, eu continuarei um membro e diga que você não fará nenhum teste ou refatoração completos ou qualquer coisa nesse sentido neste momento. Você provavelmente tem um tempo muito curto para obter uma estimativa aproximada. Minha resposta é baseada na minha experiência na mesma situação e, se minha interpretação estiver incorreta, desconsidere tudo o que se segue.

  • Use uma ferramenta de spidering para ter uma idéia de quais páginas existem e o que é de entrada. Mesmo uma ferramenta básica de verificação de links - não uma ferramenta específica "para fins de auditoria" - será útil nesse sentido.
  • Faça uma planilha básica de auditoria / inventário. Isso pode ser tão simples quanto uma lista de arquivos e seu horário da última modificação, organizados por diretório. Isso ajudará você a ter uma noção do escopo e, quando chegar a diretórios como _OLD e _DELETE, poderá observar que: a) sua avaliação se baseia em coisas que não estão nesses diretórios; b) na presença desses diretórios e no potencial de pesadelos com cruft / oculto atestam problemas mais profundos que devem ser considerados na oferta do seu cliente , de alguma forma. Você não precisa gastar um bilhão de anos enumerando os possíveis problemas em _OLD ou _DELETE; as informações serão inseridas no eventual lance.
  • Como você está revisando o que parece ser um aplicativo totalmente baseado na Web, até as ferramentas padrão do analisador de logs serão seus amigos. Você poderá adicionar à planilha algum sentido de "isso está entre os 10 principais scripts acessados" ou algo parecido. Mesmo que os scripts sejam incorporados em arquivos Flash e, portanto, não sejam possíveis de serem encontrados, há uma alta probabilidade de serem acessados ​​via POST ou GET e aparecerão nos logs do servidor. Se você souber que possui 10 scripts altamente acessados, e não 100 (ou vice-versa), isso lhe dará uma boa idéia de como o trabalho de manutenção provavelmente será.

Mesmo em um site complicado, o que descrevi acima é algo que você pode fazer em um dia ou dia e meio. Como a resposta que você vai dar ao seu cliente é algo como "isso vai ser uma tremenda dor no traseiro, e aqui estão algumas razões pelas quais você estará apenas colocando batom em um porco, então lance de acordo "ou" qualquer pessoa razoável lance para não manter, mas para começar de novo, então você deve fazer lances de acordo "ou até" isso não é tão ruim assim, mas haverá um fluxo consistente de trabalho em qualquer período de tempo, portanto faça lances de acordo " , o ponto é que eles farão o lance e, portanto, você não precisa ser tão preciso quanto seria se estivesse sendo contratado diretamente para fazer uma auditoria completa da arquitetura e do conteúdo.

jcmeloni
fonte
2
+1 Esta é uma resposta fantástica. Onde está aquele botão +5 chegou ...
Engineer
1
TL; DR: não se mande por uma toca de coelho até precisar. :)
jcmeloni
4

Eu recomendo fortemente refatorar o código fonte existente (em vez de reescrever) usando os padrões encontrados no livro " Trabalhando efetivamente com o código legado ".

O livro detalha vários mecanismos para cobrir eficientemente o código legado em testes de unidade, para que você possa começar a refatorar o código com segurança. O livro está dividido em partes, um descrevendo a filosofia por trás da abordagem e, em seguida, vários capítulos que resolvem problemas específicos, como "Leva uma eternidade para fazer uma mudança", "Não tenho muito tempo e preciso alterá-la" e "Não consigo colocar esta classe em um equipamento de teste". Cada um desses capítulos possui técnicas detalhadas e comprovadas que ajudam você a aprender como aplicar as melhores práticas de teste a problemas do mundo real.

A leitura do livro me deixou com uma sensação muito real de que "não estamos sozinhos" ... muitos de nós, ou talvez todos, estamos trabalhando com bases de código complexas que se tornaram difíceis de gerenciar. As técnicas listadas no livro me deram muita esperança e eu pessoalmente pude aplicá-las quase que imediatamente.

O post de Joel Spolsky faz um ótimo trabalho ao explicar por que é melhor manter uma base de código existente e funcionando, em vez de começar do zero. Eu escolhi uma citação do artigo que resume, mas é uma leitura fantástica.

"Há uma razão sutil que os programadores sempre querem jogar fora o código e começar de novo. A razão é que eles acham que o código antigo é uma bagunça. E aqui está a observação interessante: eles provavelmente estão errados. A razão pela qual eles acham que o código antigo código é uma bagunça é por causa de uma lei fundamental da programação:

É mais difícil ler o código do que escrevê-lo. ". - http://www.joelonsoftware.com/articles/fog0000000069.html

Kyle Hodgson
fonte
4
+1. Em resposta ao comentário de Joel, "Não deve ser assim." Porque não vejo o problema como inerente. Eu vejo isso como sendo parcialmente o fato de que muitas pessoas escrevem código de má qualidade e não se importam, enquanto muitas outras escrevem código razoavelmente bom, mas seguem o conceito de "código de auto-documentação" ... que é simples: BS: Pode-se lisonjear o estilo de codificação de alguém, tudo o que você deseja em privacidade, mas quando se trata de bases de código públicas, apenas gera comentários como se não houvesse amanhã. Não dói. E, finalmente, há pessoas que precisam fazer as coisas funcionarem em bases de código herdadas, com um orçamento apertado.
Engenheiro de
2

Em uma base de código Java típica, considerarei o uso de ferramentas como PMD, FindBugs ou Sonar e tentarei entender o relatório de ferramentas (código morto, código não documentado, código duplicado etc.)

Com base nos relatórios, tentarei encontrar as diferentes camadas do aplicativo / site (camada de negócios, banco de dados, SQL, etc.)

Se as camadas forem acopladas (html no servlet, sql no código java), começarei primeiro dissociando cada uma dessas etapas, que devem ser consideradas isoladas e você poderá confirmar no final de cada uma (iniciando uma ramificação e fazendo a mesclagem) .

Abderrazak BOUADMA
fonte
1
Obrigado. Embora sua resposta seja um pouco específica de Java, é interessante ver sua abordagem em camadas ... descascando a cebola, por assim dizer. Algo para pensar sobre.
Engenheiro
1

Pela sua descrição, parece que esse código atingiu o estado inalterável, o que significa que a melhor abordagem provavelmente é uma reescrita completa. Os desenvolvedores teriam salários muito menores se houvesse ferramentas de qualidade que funcionassem para manter uma base de código confusa e sustentável. É possível analisar e limpar o código desnecessário antigo das pastas, mas é uma tarefa manual e você provavelmente não obterá tudo de qualquer maneira sem quantidades excessivas de tempo. Estou supondo aqui, mas aposto que o código de trabalho em si é tão confuso quanto a estrutura do arquivo, o que significa que mesmo quando você consegue ajustar a base de código para o código de trabalho ativo, ainda será um pesadelo para atualizar ou corrigir qualquer coisa.

Eu enfatizaria que o esforço necessário para obter o código existente em um estado de manutenção seria igual ou superior ao esforço para iniciar novamente uma reescrita. parte de manter algo é saber quando "levá-lo para trás do galpão e atirar nele".

Ryathal
fonte
Normalmente, eu estaria 100% com você na abordagem de jogar e reescrever. Mas, neste caso (e pelo menos por enquanto), devo ser pago apenas pelo trabalho de manutenção do site, em vez de uma revisão mais extensa que levaria várias semanas. Além disso, mesmo que eu quisesse agora, não poderia continuar fazendo isso e manter os outros contratos em andamento, pois minha disponibilidade semanal para isso é explicitamente limitada - meu contrato principal deve ser cumprido de Mínimo semanal de 40 horas.
Engenheiro de
1
Não concordo com atirar e reescrever! De joelonsoftware.com/articles/fog0000000069.html ... "Há uma razão sutil que os programadores sempre querem jogar fora o código e começar de novo. A razão é que eles acham que o código antigo é uma bagunça. E aqui está a observação interessante : eles provavelmente estão errados. A razão pela qual eles acham que o código antigo está uma bagunça é por causa de uma lei fundamental da programação: é mais difícil ler o código do que escrevê-lo. " Em vez disso, eu recomendo fortemente refatoração: amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/...
Kyle Hodgson
1
@KyleHodgson às vezes o código é realmente uma bagunça, e quando você está no ponto em que é uma bagunça encontrar o código antes de lê-lo, é hora de começar de novo.
Ryathal 26/01/12
Sim, eu não acho que seja tão claro assim, embora esse livro pareça valer a pena ser lido. Depende muito do tamanho / complexidade da base de código e dos corpos quentes disponíveis para fazer o trabalho.
Engenheiro de
1

Um rastreador da web pode ajudar a determinar quais URLs estão acessíveis. Especialmente se for inteligente o suficiente para extrair links do Flash ou JavaScript. Depois de ter uma lista de páginas da web, consulte-as e liste os arquivos a que se referem. Tudo o que sobrar após esse processo deve ser considerado código morto.

Mike Baranczak
fonte
1
Discordo totalmente da sua última frase. O rastreador só pode descobrir quais páginas estão vinculadas como um gráfico direcionado com um ou vários pontos de partida. Mas, como falamos de um site, também existem as chamadas "páginas de destino", que apontam para outras páginas, mas não há links apontando para elas. Além disso, pode haver partes antigas da interface administrativa que também estão desconectadas de outras páginas. Atualmente, tenho um projeto desse tipo.
Script #:
0

Nota: Eu enfatizei o uso do banco de dados, enquanto você perguntava sobre o uso do próprio código. A resposta ainda se aplica a ambos os casos em todos os pontos que mencionei.

Você já respondeu em parte sua própria pergunta no último parágrafo: veja o que é acessado enquanto o aplicativo está em execução.

  1. Você pode criar um perfil do banco de dados e solicitar ao criador de perfil que registre todas as consultas por um dia. Ele fornecerá uma visão geral dos objetos de banco de dados mais usados, mas não informará quais nunca foram usados. Além disso, você ainda deve ter cuidado com os resultados: por exemplo, uma tabela pode ser usada exclusivamente por meio de procedimentos armazenados, mas quando você examinar as consultas do criador de perfil, parecerá que a tabela não foi usada.

  2. Revisar o código-fonte, pesquisar consultas é mais útil e, após coletar todas as consultas, você pode entender bem o uso do banco de dados, não em termos de frequência (é aqui que um criador de perfis é útil), mas em termos de uso / não tabelas usadas. Infelizmente, para uma base de código mal gravada / não mantida por anos, pode ser extremamente difícil e propensa a erros , especialmente se as consultas forem construídas dinamicamente (imagine um método que, em a select, use um parâmetro como o nome da tabela; como você pode possivelmente saiba quais são os possíveis valores do parâmetro apenas olhando o código-fonte?).

  3. A análise estática e alguns compiladores também podem revelar código morto, mas ainda não fornecem a resposta desejada.

  4. A análise dos próprios dados ou dos metadados do banco de dados pode revelar algumas informações interessantes. Por exemplo, seria fácil para afirmar que a tabela LogonAudit(uniqueidentifier LogonAuditId, datetime LogonEvent, ...)não é usado por mais tempo se ele contém 10 000 registos por dia para os anos de 2006 a 2009, e há registros de setembro de 18 th , 2009. O mesmo não é verdade para um tabela que contém os dados recuados para serem principalmente somente leitura.

Esses quatro pontos juntos fornecerão a lista de tabelas usadas. Os restantes são usados ​​ou não. Você pode fazer afirmações e testá-las, mas sem uma boa cobertura de testes de unidade, não seria fácil. Qualquer maneira "fácil" também falharia. Por exemplo, se você possui uma products_delme_not_usedtabela, pode afirmar que a tabela não é usada e verificar "products_delme_not_used" no seu código. Isso é otimista: não é incomum encontrar o candidato do DailyWTF assim em uma antiga base de código:

// Warning: WTF code below. Read with caution, never reuse it, and don't trust
// the comments.

private IEnumerable<Product> GetProducts()
{
    // Get all the products.
    return this.GetEntities<Product>("PRODUCT");
}

private IEnumerable<T> GetEntities<T>(string tableName)
{
    // Everyone knows that SQL is case sensitive.
    tableName = tableName.ToLower();

    if (tableName == "user" || tableName == "product")
    {
        // Those tables were renamed recently in the database. Don't have time
        // to refactor the code to change the names everywhere.
        // TODO: refactor the code and remove this `if` block.
        tableName += "s";
    }

    if (this.IsDelme(tableName))
    {
        // We have some tables which are marked for deletion but are still
        // used, so we adjust their name.
        tableName = this.Delme(tableName);
    }

    return this.DoSelectQuery<T>("select top 200 * from " + tableName);
}

private bool IsDelme(string name)
{
    // Find if the table is among candidates for removal.
    List<string> names = this.Query<string>("select Names from DelmeTables");
    return names.Contains(name);
}

private string Delme(string name)
{
    // Return the new name for a table renamed for deletion.
    return string.Join("_", new [] { name, "delme", "not", "used" });
}

Você pode descobrir que esse código realmente usa products_delme_not_usedtabela?

Se eu fosse Você eu faria:

  1. Mantenha todos os objetos de banco de dados no lugar,
  2. Refatorar todo o aplicativo (se vale a pena),
  3. Documente (durante a refatoração) do aplicativo e, especificamente, o uso do banco de dados.

Ao concluir as duas últimas etapas, você provavelmente terá uma melhor compreensão do uso do banco de dados, o que ajudará a descobrir os nomes das tabelas que não são mais usadas e poderá removê-las com mais ou menos segurança.

Arseni Mourzenko
fonte
0

Parece-me que você precisa obter informações suficientes para criar uma cotação, então vou me concentrar nesse esforço.

Eu tentaria determinar quantos casos de uso estão envolvidos neste site. Isso geralmente dá uma idéia de quão grande e complicado é o site e quanto tempo leva para recriar ou manter o site / aplicativo.

Sim, é verdade que às vezes o código não é mais usado e fará com que o aplicativo pareça um pouco maior do que realmente é, mas acho que isso não afetará os números em mais de 20%, no máximo , então eu não me preocuparia com essa parte.

Observar o código fonte, as páginas da web e as tabelas do banco de dados deve ajudá-lo a descobrir isso.

Você também pode considerar a possibilidade de limitar o número de horas por mês que gastará neste projeto pela taxa pré-determinada para se proteger.

Quanto a descobrir o que está sendo usado e não usado, realmente não existe uma maneira fácil. As ferramentas de análise de código podem ajudar, mas como você está lidando com um problema tão misto, não acho que exista uma única ferramenta que possa ajudar. Para cada área específica, você provavelmente encontrará uma ferramenta de análise de código que pode ajudar.

Sarel Botha
fonte