O código legado

O código legadoSe você é programador, provavelmente já se deparou com o código-fonte de um sistema antigo que você mesmo desenvolveu e pensou: “Caramba, que código feio! Hoje eu faria bem melhor!”, não é? Bom, isso é natural. Na mesma proporção que adquirimos mais experiência em programação, também começamos a utilizar conceitos, práticas e técnicas mais eficientes no código-fonte. Mas e aquele código antigo, é abandonado?

 

Ninguém nasce sabendo programar. Programação é algo que se aprende com muito estudo e com conhecimento empírico baseado em experiências anteriores.
Experiências anteriores… bem lembrado!
Qual foi a sua primeira experiência com programação? Talvez um sistema de controle de estoque, locadora, farmácia, algo parecido?

O primeiro sistema que eu desenvolvi foi para uma farmácia na minha cidade natal, utilizando Delphi 6 e banco de dados Interbase. Nessa época, eu conhecia o essencial de programação, mas ainda não dominava técnicas avançadas, como orientação a objetos, refatoração, subrotinas e parametrização.
Pois bem, o sistema funcionou, atendeu as necessidades do usuário e ficou lá por um bom tempo sem exigências de manutenção.

Eis que, quando eu estava no terceiro ano da faculdade, o dono da farmácia entrou em contato solicitando uma alteração no sistema. A princípio, fiquei surpreso em saber que eles ainda o utilizavam, rsrs. Pois bem, o primeiro desafio foi encontrar o código-fonte no meu computador, já que haviam-se passado três anos desde que o desenvolvi. Quando eu finalmente encontrei os arquivos e abri o projeto no Delphi… nossa, que código primário! Haha!
Achei engraçado a forma como eu programava e também da complexidade desnecessária que criei naquele software. Eu facilmente poderia desenvolver um sistema bem melhor reduzindo metade das linhas de código existentes naquele sistema. E foi o que eu fiz!

Claro, isso foi viável porque o sistema era pequeno, com apenas cadastros, consultas e alguns relatórios. Porém, e se o software fosse de médio ou grande porte? Não podemos simplesmente começar o desenvolvimento “do zero” por causa desses códigos antigos. Basicamente, a solução é atualizá-los para que fiquem no mesmo nível dos códigos atuais.

Bom, agora sim chegamos ao assunto do artigo!
Esse código antigo, mesmo que funcional, recebe o nome de “código legado“. Trata-se de um código-fonte que não está incorreto, mas não aprecia as melhores práticas de desenvolvimento de software. Se você encontrar um código legado, provavelmente vai se deparar com vários blocos que podem ser simplificados ou aprimorados utilizando melhores técnicas de programação. A diferença é a organização e a disposição técnica do código, além de interferir diretamente no desempenho da aplicação.

Para ajudar na compreensão, analise o código abaixo:

var
  listaValores: TStringList;
  soma: real;
begin
  listaValores := TStringList.Create;
 
  listaValores.Add(Edit1.Text);
  listaValores.Add(Edit2.Text);
  listaValores.Add(Edit3.Text);
  listaValores.Add(Edit4.Text);
  listaValores.Add(Edit5.Text);
 
  soma := StrToFloat(listaValores[0]);
  soma := soma + StrToFloat(listaValores[1]);
  soma := soma + StrToFloat(listaValores[2]);
  soma := soma + StrToFloat(listaValores[3]);
  soma := soma + StrToFloat(listaValores[4]);
 
  ShowMessage('Soma: ' + FloatToStr(soma));
end;

Apesar de funcionar perfeitamente e atender o propósito (que é apresentar a soma de 5 valores), é fato de que este código pode ser melhorado.
Após aplicar melhores técnicas, observe a diferença:

var
  listaValores: TStringList;
  soma: real;
  i: integer;
begin
  listaValores := TStringList.Create;
 
  for i := 1 to 5 do
    listaValores.Add(TEdit(FindComponent('Edit' + IntToStr(i))).Text);
 
  for i := 0 to 4 do
    soma := soma + StrToFloat(listaValores[i]);
 
  ShowMessage('Soma: ' + FloatToStr(soma));
end;

E poderíamos simplificar ainda mais, embora o código abaixo já fique mais suscetível a falhas e pode dificultar a leitura por outro desenvolvedor:

var
  soma: real;
  i: integer;
begin
  for i := 1 to 5 do
    soma := soma + StrToFloat(TEdit(FindComponent('Edit' + IntToStr(i))).Text);
 
  ShowMessage('Soma: ' + FloatToStr(soma));
end;

Resultado: conseguimos reduzir 21 linhas para 9, sem perder a funcionalidade proposta!

No entanto, este processo não é tão simples assim. O problema está no tempo para “limpar” o código legado. Nem toda empresa de desenvolvimento de software dispõe de tempo para essa atividade, principalmente quando é um software de grande porte que apresenta demandas constantes de manutenção. A limpeza do código envolve mais do que simplesmente substituir métodos. É necessário realizar testes e verificar se a alteração do código-fonte não irá gerar impactos em outros módulos do sistema. E há quem o diga: isso acontece muito!

Por exemplo, suponha que você trabalhou na refatoração no módulo de estoque de produtos, movendo rotinas duplicadas para funções parametrizadas e criando classes para agrupar atributos em comum. Ao término dessa refatoração, você reduziu as linhas de código em 40%. Ótimo, não é?
Porém, tenha em mente que outras unidades do seu sistema utilizam este módulo, como a entrada e saída de produtos. Se uma dessas unidades utiliza uma variável, método ou campo que foi refatorado, provavelmente a compilação apresentará erros. É claro, as ferramentas de desenvolvimento geralmente apontam erros de sintaxe e de referência caso o objeto não seja encontrado. Já a semântica, entretantonão é validada por essas ferramentas, visto que se trata mais de uma questão voltada para o domínio da aplicação. Neste caso, é imprescindível a execução de roteiros de testes e/ou testes automatizados das unidades que tenham alguma relação com o módulo alterado.

Observe que essa atividade realmente demanda um tempo extra e não deve ser dispersa entre os desenvolvedores. Uma forma que pode ajudar essa atividade é o conceito de ciclo de iterações do software presente nas metodologias ágeis. Empresas que utilizam o Scrum no gerenciamento de equipes podem realizar essa refatoração com base na alocação de tempo dentro das Sprints. Em outras palavras, a empresa pode alocar uma porcentagem dos desenvolvedores para trabalhar na refatoração e testes dentro do ciclo da versão, de modo que não afete as atividades de evolução e manutenção. Se isso não for viável, o Scrum Master pode reservar um tempo de todos os desenvolvedores exclusivamente para a refatoração, como, por exemplo, a última hora do expediente. Em uma carga horária de 8 horas por dia, é como se os desenvolvedores trabalhassem 7 horas na manutenção e 1 hora na limpeza do código legado, no qual este tempo possa ser ajustado conforme a demanda de trabalho.

Algumas empresas preferem terceirizar o processo de refatoração para não comprometer o tempo dos desenvolvedores internos. Essa opção demanda mais tempo, uma vez que a terceirização precisa, primeiro, conhecer a regra de negócio do cliente.
Além disso, é muito importante que o profissional responsável (seja interno ou externo) tenha sólidos conhecimentos em programação, principalmente orientação a objetos, princípios SOLID, Design Patterns, TDD e Clean Code. Apesar de demandar muito aprendizado, na realidade as técnicas mencionadas estão estritamente ligadas uma à outra.

Certa vez acompanhei a refatoração de uma unidade de código utilizando o Design Pattern Observer. Houve uma redução notável no tamanho do código-fonte, mesmo criando unidades de código adicionais para a implementação do padrão. O responsável pela refatoração fez bom uso de tipos enumeradores, arrays e interfaces além das técnicas tradicionais de orientação a objeto, como o encapsulamento e polimorfismo. Na verdade, essa refatoração foi o piloto de um novo conceito de codificação na empresa, e os resultados foram bem satisfatórios.

Enfim, volto a repetir novamente: mesmo que a refatoração e a limpeza do código legado sejam importantes, estes devem ser alinhados e codificados por profissionais que já tenham uma experiência extensa com programação, e mais, em um prazo bem definido. De nada adianta refatorar um código que trará mais complexidade (e, consequentemente mais manutenção) do que a estruturação do software.

 

Obrigado pela visita, leitores!
Até a próxima!


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

7 comentários

  1. o grande problema de pegar programa (grande, complexo e mal feito) dos outros é q naquela hora nos pensamos…. esta funcionando mexer pra q? kkkk
    claro q da ate pra dar uma melhorada mas tem coisa q da um desanimo, rsrs

  2. Trabalho em uma empresa onde “herdei” dois sistemas, desenvolvidos por dois programadores diferentes e em linguagem diferentes… pense!!!
    O gerente sempre fala em “enxugar” o código dos dois sistemas e eu sempre falo que é melhor fazer do zero, em uma única linguagem. Daí, ele engaveta o projeto devido o tempo necessário e depois de um tempo volta a falar em “enxugar” os sistemas…
    Em ambos os casos, eu acho melhor fazer do zero por que já é difícil dar manutenção em código dos outros, quanto mais “enxugar”.

    1. Olá, Chagas! Realmente, trabalhar com sistemas desenvolvidos em diferentes linguagens dificulta a manutenção e a evolução do software, principalmente quando é preciso mantê-los integrados. O maior empecilho está no tempo para unificá-los em uma única linguagem, já que a maior parte da demanda de manutenção terá que ser interrompida. Mesmo assim, acho importante a empresa investir nessa padronização.

  3. André, que texto ótimo!! Sempre estou em busca de novos conhecimentos, e ultimamente estou vendo sobre Solid, Design Pattern e etc. Meu códigos antigos dão vergonha! AUHAuhAuhauh Incrível como os conceitos novos possibilitam escrever código melhor e mais bem organizado, além de ser até mais fácil de desenvolver =) O texto, apesar de ter sido escrito no ano passado, ainda é muito atual. Parabéns!

    1. Olá, Vitor! Parabéns pela sua iniciativa em buscar novos conhecimentos relacionados à técnicas de programação! Isso certamente irá lhe trazer grandes vantagens nos seus projetos, além do sentimento de profissionalismo! Obrigado pelo comentário!
      Abraço!

  4. @Conde, de fato a questão de pegar um grande software legado é um dilema muito grande para os maiores desenvolvedores do mercado, a premissa “se está funcionando, pra que mexer?” realmente ainda é um peso considerável na decisão de refatorar ou não. Porém deve-se pensar o seguinte: “Se eu não arrumar agora, futuros desenvolvedores irão passar pelo mesmo problema que eu” que no caso é mal entendimento da funcionalidade e postergação de soluções de problemas, basicamente um XGH (procure por esse termo no google, tem uma página que trata os pontos mais críticos da prática).
    De qualquer forma, recomendo altamente a leitura dos títulos “O Código Limpo” e “O Codificador Limpo” de Robert C. Martin e também “Refatoração para Padrões” do Joshua Kerievsky.

    1. Fala, grande Marcos!
      Sei que a mensagem não foi diretamente pra mim, mas gostei bastante do comentário! Na verdade, todos os seus comentários agregam bastante aos artigos! 🙂
      Marcão, como nós já trabalhamos juntos, sabemos o peso no qual você se refere. A postergação, ao meu ver, é sinônimo de empurrar o problema para o próximo desenvolvedor que passar pelo código. Nessas circunstâncias, desenvolvimento sustentável passa longe…

      Abraço!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.