Bom, atualmente muito de nós engenheiros de software (em especial os mais iniciantes) preocupam-se com a tecnologia X ou Y a ser usada, qual provedor cloud usar ou qual design pattern devo usar nesse código. Mas, antes dessas perguntas, é extremamente necessário que todo engenheiro treine uma habilidade básica, inerente a própria engenharia: a habilidade de quebrar problemas e solucioná-los, em outras palavras, como realizar um bom troubleshooting?

Ao se esquecer dessa parte primordial, muitos engenheiros irão simplesmente navegar no mar da dúvida sem atacar o problema real. Tal como um médico que receita remédios ao seu paciente sem procurar a causa-raiz, um engenheiro de software sem compreender o problema real apenas nadará no mar de incertezas, muitas vezes aumentando o custo do projeto, sem saber exatamente se solucionou de fato ou não a dor.

Para isso, a mentalidade por trás dessa solução e investigação deve ser completamente analítica: paramos o “sangramento”, investigamos e por fim completamos o ciclo corrigindo o problema. Mas para isso, é necessário não só experiência e muitas vezes técnicas, as quais com o tempo se tornarão naturais no dia a dia. Sobre isso, falarei um pouco mais sobre as técnicas logo abaixo, onde dividirei esse artigo em cada parte do ciclo de solução.

Sumário

  1. Parar o sangramento
  2. Investigação
  3. Correção
  4. Conclusão

Parar o sangramento

Por mais que seja tentador falar que a correção do problema seja a fase mais importante, as vezes interromper imediatamente o efeito direto ou colateral causado por uma falha, na maioria das vezes, é a melhor saída inicial. Se você trabalha em algum sistema financeiro, sabe que uma falha pode custar muito, muito dinheiro. Quanto mais cedo parar o sangramento, mais feliz os stakeholders ficarão. Para isso, você pode utilizar o acrônimo O.Q.C:

  • O que mudou?

  • Quando mudou?

  • Como mudou?

Fazendo essas três perguntas, você conseguirá ter uma visão mais imediata do que mudou no seu sistema, seja um fator interno ou externo, e assim reverter essa situação ou contorná-la, diminuindo o impacto nos seus clientes.

Logs de aplicação, traces, change orders e documentações são sempre bem-vindos nessa hora, mas entenda que apenas ter essas informações não mudará muito, é necessário adicionar na fórmula a sua análise do problema.

Investigação

Essa fase é quando a primeira tempestade acabou, agora é hora de analisar o problema mais profundamente, procure reler o que aconteceu no incidente para relembrar de alguns detalhes e assim parta para a investigação. Nessa etapa, podemos ter algumas ferramentas que podem nos ajudar: reprodução e isolamento.

Se seu sistema permitir a capacidade de reprodução daquele cenário, ótimo, utilize-a exaustivamente. Tente reproduzir o máximo possível da condição daquele incidente, suba a aplicação localmente, coloque os mesmos dados de entrada e através dos breakpoints na sua IDE observe passo a passo da aplicação até chegar no erro esperado. Essa é uma técnica muito poderosa, mas que infelizmente muitos programadores não a utilizam frequentemente, seja por não conseguir simular completamente as condições (por questões de uma má arquitetura ou falta de ferramentas) ou por simplesmente desconhecerem sua utilização.

Outra possível técnica é isolar o problema. Comece pensando no seu sistema de fora para dentro. Será que foi alguma integração externa que causou isso? Alguma dependência de outro sistema? Será que foi algum tratamento de dado que falhou, alguma regra não prevista ou entrada de dado não prevista? Será que foi alguma comunicação entre os serviços que falhou? Será que o próprio serviço falhou?

Análise externa a interna de um sistema

Repare que nessa linha estamos sempre questionando nosso sistema de fora para dentro, avaliando se o ofensor é externo ou se de fato é interno. Se o sistema foi bem testado, a chance de ser um ofensor externo é grande, porém essa etapa também é importante para elucidarmos se o nosso sistema foi bem testado ou não.

Nos momentos em que percebemos que o ofensor é externo, sempre se lembre disso: não busque culpados, busque causas. Não é interessante para você ou para sua empresa que ao localizar que a falha veio por um sistema de outro setor que falhou, saia apontando o dedo em direção ao outro departamento. Não faça isso. Ao contrário, busque mostrar aos seus colegas a causa daquela falha no seu sistema e como eles podem fazer para ajustar. Será uma conversa muito mais proveitosa para ambos.

Correção

A fase final do ciclo na solução de um problema. É quando ao já termos parado o sangramento e investigarmos, procurarmos uma força de corrigir aquele problema já sabendo sua causa raiz, procure solucionar o problema não apenas para “tapar o buraco”, mas sim para entender como melhorar o código ou como evitar que isso ocorra novamente.

Após feito, teste o sistema exaustivamente, afinal nem você nem seus clientes querem que isso volte a ocorrer, implemente a correção e não esqueça de documentar o que foi feito. Assim você ou outros colegas no futuro saberão o que causou e como foi resolvido, se um problema similar aparecer, já terão um bom norte.

Conclusão

Resolver problemas não é fácil, mas é uma habilidade crucial de todo engenheiro. Se você se vê como um engenheiro de software ou deseja se tornar, talvez essa seja a melhor aptidão para masterizar. A linguagem X ou Y, os detalhes da tecnologia e arquiteturais, tudo isso é importante, mas tudo isso são ferramentas, e se você não souber qual é o problema a ser resolvido, de nada adianta ter o melhor martelo. Não adianta ter as melhores tintas e pincéis, se você sequer tem ideia do que quer pintar.

Inclusive, se você já pensou um pouco sobre o problema do excesso de engenharia (overengineering) dê uma lida neste artigo.