Construindo softwares resilientes

Coisas que todo Sênior deve saber

Construindo softwares resilientes

Post originalmente publicado em dev.to.

— Já ouviu falar de eXtreme Go Horse (XGH)?
— Não?! 🙄
— Mas você pratica XGH? 🤨
— Não?
— Ainda bem! 😀

XGH é uma piada que gosto muito. Espero que você não o pratique. Mas coloquei ele na roda por seu exato oposto. Um Sênior deve construir softwares estáveis. E para se construir software estáveis você tem que ir pro extremo oposto do XGH. Devemos construir software resilientes.

Sim, eu usei a palavra resiliente. Vamos ao significado?

Alt Text

Resiliência é a propriedade de um sistema suportar adversidade.

Construindo Resiliência

Nós como desenvolvedores resolvemos problemas automatizando coisas. Quando vemos um problema já pensamos no modo como ele deve ser resolvido.

Mas e se houver outra forma? E se seu usuário não entender a forma como deve ser feito o processo? E se houver um erro durante processo? E se necessitar uma configuração na máquina?

É nessas horas que seu software tem que ser Resiliente.

Verdadeiros Sêniors constroem sistemas resilientes. Mas não seja gnóstico, não é um post que vai te fazer construir sistemas resilientes, é resolvendo bugs! Tudo que posso fazer por você é te ensinar o caminho, você terá que trilhar ele sozinho.

Então vamos com algumas dicas:

1. Um Sênior pensa em todos os problemas que podem acontecer em um fluxo

Quando você vai escrever um código, você sempre tem premissas:

  1. Existe um arquivo de configuração.
  2. Há uma classe que implementa essa interface.
  3. O servidor está de pé.
  4. Etc…

E se uma premissas dessas não for verdadeira? Seu código irá funcionar? Ou pelo menos irá mostrar o erro correto?

Vamos para exemplos reais?

Eu tenho um projeto que estou desenvolvendo para ser um tipo de tester. Dá uma olhada lá:

Nele eu executo o testes em passos (Step), cada passo tem um plugin que implementa. Então para execução de um passo eu preciso:

  1. Achar o Plugin de Execução
  2. Executar o Passo
  3. Verificar os Assertions do Passo

Simples? Poderia ser implementado em 1 linha?

Mas temos dois problemas aqui que devem ser validados.

  1. Há um Plugin para implementar o Passo?
  2. Na definição do Passo, todos os parâmetros estão definidos?

Vê que temos mais dois problemas a verificar? E detalhe, esses problemas são um erro de definição do teste e não de execução do teste. Logo o motivo da falha deve ser diferente.

Ao se identificar um erro, exiba a mensagem de erro correta, que ajuda quem irá resolver esse erro.

2. Um Sênior desenvolve software que é resistente a desenvolvedores

Ok! Você desenvolveu o negócio lindamente. Está tudo funcionando perfeitamente, fez o deploy em produção. Resultado: usuários felizes! 😀

Fim? Pode ser que não, em algum momento esse software poderá ser atualizado. Pode ser necessários corrigir os bugs que ainda não foram encontrados, ou poderá ser adicionada alguma feature. Qualquer alteração, em qualquer lugar, tem o potencial de alterar a lógica do seu software. Como podemos validar que tudo está funcionando corretamente?

Não vou vender TDD como uma bala de prata, esse não é o problema que TDD resolve. Depois falo de TDD. Eu gosto de TDD por isso repito TDD… Continuamente… TDD

Um Sênior de verdade constrói software resiliente a desenvolvedores. Mas como fazer isso?

Você deveria se preocupar com algumas coisas:

  1. Qual a cobertura de testes do sistema?
  2. Os testes foram feitos só pra passar pela cobertura de testes e agradar o arquiteto? Ou os testes estão realmente validando o output?
  3. Os testes são executados no processo de build?

Caso você tenha respondido não para qualquer uma das perguntas abaixo, seu software não é resiliente a desenvolvedores. E você não pode confiar em si mesmo a ponto de pensar que você conseguirá resolver todos os problemas no futuro.

Quando resolvemos um bug, ou adicionamos uma feature nova, temos um pensamento viciado. Apenas pensamos em um fluxo, e nos esquecemos de outros. É normal e esperado isso. Você é um engenheiro e não Deus.

Como eu resolvo isso? Eu crio testes unitários com todos os pressupostos.

É um habito meu começar meu desenvolvimento com alguns pressupostos desses, mas eles não fazem parte do TDD, pois não são Baby Step. Mas eles dão uma clara visão do que vai falhar. Pode ser que em uma próxima feature um passo desses falhe, e o desenvolvedor irá decidir:

  1. Se corrige o problema
  2. Se corrige o teste
  3. Se remove o teste, caso ele não faça mais sentido.

3. Um Sênior investiga possíveis erros

— Então, esse teste falha em 50% dos casos. Mas caso falhe, roda de novo que dá certo.

Alt Text

Se você ouvir essa frase. Recrimine! Isso não pode acontecer.

Um possível erro intermitente em um teste pode ser um erro intermitente em produção. Pode ser custoso investigar antes do deploy? Pode! Mas será mais barato do que investigar depois do deploy, não?

Um Sênior de verdade sabe que pequenos problemas não podem passar sem investigação. Não pode buscar a solução fácil de ignorar ou remover o teste. Isso é fácil, mas para um sênior é porco (com todo respeito aos porcos).

Conclusão

Quase todo software necessita de resiliência. E um Sênior de Verdade sabe ver isso.

Ele consegue se precaver de várias situações:

  1. Erros esperados
  2. Erros inesperados
  3. Pessoas esperadas
  4. Pessoas inesperadas
  5. Aleatoriedades….

Não que ele deva ser um Deus em se tratando de desenvolvimento, mas tem que praticar a disciplina de promover a resiliência.

Esse é um caminho a ser trilhado….

Livros Recomendados

  1. O Projeto Fênix: um Romance Sobre TI, DevOps e Sobre Ajudar o seu Negócio a Vence
  2. Test Driven Development: By Example
  3. Código Limpo: Habilidades Práticas do Agile Software
Licença Creative Commons
Este obra está licenciado com uma Licença Creative Commons Atribuição-NãoComercial-CompartilhaIgual 4.0 Internacional .