A importância de sistemas legados e como melhorar nosso relacionamento com eles

Como o Gabriel Lett Viviani comentou no artigo Como introduzir novas tecnologias no ambiente de trabalho, na Bionexo utilizamos diversas tecnologias novas para solucionar problemas diversos mais adequadamente. Porém, como muitas outras empresas, também temos importantes sistemas que são mais antigos.

Assim como qualquer outra empresa que é baseada em grande parte em tecnologia, as requisições não se sujeitam a restrições impostas por sistemas mais antigos, isto é, não deixamos de receber pedido de melhorias, correções de erros e adições de funcionalidade. Como qualquer outra empresa, a Bionexo precisa evoluir, afinal, a única certeza que temos sobre a grande maioria dos softwares, é que ele precisa mudar e se adaptar a novas realidades.

O que é um sistema legado?

O que você sente ao alterar um código? Você sente medo? Você sente angustia? Ou você tem uma boa confiança de que quando você cometer um erro, você terá um tipo de rede de proteção te ajudando?

Sentimentos são um termômetro muito bom, antes de qualquer coisa dê atenção a eles, ao menor sinal de perigo, ou quando você percebe que algo será mais complexo do que aparentemente deveria, pare e pense: Como chegamos até a este ponto?

Mesmo que você não tenha uma resposta concreta, você no mínimo perceberá que talvez tenha alguém que tenha passado por este mesmo problema e estas pessoas podem te ajudar.

Depois de algum tempo, meu maior medo quando eu altero um código é não ter a dimensão de como esta alteração vai impactar em uma outra parte do sistema que eu nem sequer sabia que existia — é, já quebrei a produção desta forma.

Por isto, minha definição de sistema legado é a definição do livro do autor Michael C. Feathers Working effectively with legacy code: código legado é um código sem testes automatizados.

Vou falar mais disto a seguir, mas os testes automatizados nos dão muito mais confiança. Quando existem testes para o seu código você tem uma garantia melhor de que mesmo um código que você não mexeu será testado, fazendo com que você possa focar no seu trabalho atual e ainda sim ter a segurança de que os impactos estão sob controle.

Lidando com os fatos de frente

Eu não quero aqui fazer uma defesa de sistemas legados, por sinal eu faço bastante força lendo livros, blog posts, conversando, refatorando e testando para que eu possa produzir melhores softwares.

Porém, sistemas legados como o descrito anteriormente, são extremamente comuns. Sempre quando vejo quem desenvolve software trabalhando em sistemas legados eu percebo uma frustração, medo e baixa auto-estima. Todos estes sentimentos realimentam um sistema legado, fazendo com que mudanças sejam penosas, a base de código vai se calcificando já que tudo é feito da forma que é possível e não de uma melhor a torná-lo melhor. Como consequência vemos organizações demorando a responder satisfatoriamente a novas demandas, correções demoram a ser entregues, e muitas vezes, quando são entregues, geram outros problemas colaterais, impedindo organizações de entregar o valor que realmente gostaria para quem depende destes sistemas.

Então, sob um ponto de vista mais pragmático, é necessário como desenvolvedores ter a certeza que precisamos investir tempo para por nossos sistemas legados pouco a pouco sob testes, refatorá-lo e adicionar nossas mudanças. As consequências são visíveis tanto a curto, médio e a longo prazo para a organização. Além disto, a estabilidade da plataforma e a velocidade de entrega também são impactadas.

Sobre um ponto de vista aparentemente menos pragmático, vem o desafio técnico de se aprender a lidar com softwares como estes, o que pode elevar o patamar técnico tanto de quem desenvolve software, quanto da organização. Que apesar de aparentemente (e de fato) envolver alguns riscos — que vou citar fontes que nos ajudam a mitigá-los — a contrapartida vem com todos os efeitos que citei sobre velocidade de entrega e estabilidade a longo prazo.

Por sorte, este não é um problema novo…

Sistema legado não é algo novo, com certeza, temos diversas referências de como lidar com eles, e mais importante: como não produzir novos sistemas legados.

Aqui vai uma pequena lista de quais ferramentas e referências disponíveis podem te ajudar.

Aprenda o valor de testes

Testes são parte essencial para o desenvolvimento de software. Como você garante que suas mudanças não afetam uma parte do sistema que você sequer sabia ou lembrava que existia? Como testar todos os fluxos manualmente de um grande sistema? É virtualmente impossível garantir isto fazendo testes manuais. Então automatize seus testes. Os testes te servirão como uma rede de proteção, na qual você pode assumir alguns riscos e se você cair a rede estará lá para você não se estabacar no chão— ao menos em muito mais casos do que com testes manuais.

Aprenda sobre testes de unidade (de preferência com TDD), testes de integração, aceitação, contrato, etc. Independentemente das plataformas que você trabalha, há diversas opções.

Para começar com testes eu sugiro o livro TDD by example do Kent Beck.

Aprenda a refatorar

No momento que temos testes, temos uma boa liberdade de olhar para nosso código e se perguntar: Será que eu realmente leio este código e consigo entender claramente a responsabilidade que este se propõe? Será que no meio da minha lógica de negócio há uma linguagem de banco de dados ou uma logica de apresentação?

Quando temos testes, mesmo que estes problemas existam, temos a oportunidade de refatorar, isto é, melhorar o meu código para representar mais adequadamente a responsabilidade dele, de modo a comunicar melhor a intenção e reduzindo o esforço cognitivo para outras pessoas entenderem.

Claro, este senso de como comunicar melhor desenvolvemos depois de refatorar mais e mais código, além de conhecimento de técnicas de refatoração e padrões de design de código.

Para melhorar nestes dois quesitos, eu sugiro dois livros. Um deles é o clássico Refactoring: improving design of existing code do Martin Fowler e outro livro que eu gosto muito é o Refactoring to patterns do Joshua Kerievisky.

Mas sistemas legados não são facilmente testáveis, como refatorar sem saber se vou quebrar?

Sim, este é de fato o maior desafio de um sistema legado: como lidar com um sistema que não foi construído para ser testável?

Felizmente, este assunto foi tratado muito bem pelo autor Michael C. Feathers no seu livro Working effectively with legacy code. Este livro descreve diversas técnicas de como lidar de forma pragmática e bastante segura quando tentamos por um sistema legado sobre controle.

Além deste ótimo livro, temos técnicas como estrangulamento, feature toggles, monitorações ou bibliotecas como scientist em ruby que podem nos ajudar a dar mais segurança a nossas mudanças.

Conclusão

Diversas organizações têm softwares importantes que sofrem diariamente para evoluírem, ou até mesmo para serem estáveis. Tentar torná-las mais saudáveis não é uma falta de pragmatismo, muito pelo contrário, é uma necessidade que permite o crescimento e desenvolvimento para atender melhor as pessoas que dependem destes sistemas, além de abrir um mundo de novas possibilidades.

Outra coisa que eu gostaria que estivesse claro aqui é que sistemas legados também são desafios técnicos interessantes, e grandes oportunidades para melhorar nossas habilidades de desenvolvedores e desenvolvedoras.