Caixa de ferramentas da Arquitetura de Software [Parte-2]
Published: 2024-04-11 14:33:39

Continuando o texto que escrevi semana passada sobre o livro "Caixa de Ferramentas da Arquitetura de Software" hoje vou escrever sobre a terceira parte do livro que é focado na confiabilidade da aplicação.

Se você não leu o primeiro post, você pode encontra-lo aqui:
https://dev.to/ezambomsantana/caixa-de-ferramentas-da-arquitetura-de-software-parte-1-2i7a

No post de hoje vou falar sobre a confiabilidade em uma aplicação, que é talvez um dos requisitos não funcionais mais importantes na Engenharia de Software, já que ele indica que a aplicação executa corretamente os requisitos funcionais para que ela foi projetado de forma confiável.

Mas o que isso quer dizer? Primeiro que os requisitos estão implementados corretamente, se o usuário fizer uma operação ela vai executar exatamente o que ele esperava. 

Segundo, que a aplicação estará sempre disponível, você já deve ter visto um sistema indisponível, e sabe o quanto isso é frustrante. 

Por último, sabendo que por melhor que a aplicação seja, ela pode falhar, e se falhar, será possível recupera-la sem efeitos colaterais.

Para garantir a confiabilidade da aplicação temos que pensar em todas as fases do software, iniciando do projeto e indo até a execução da aplicação. No processo de desenvolvimento temos que garantir que a aplicação cumpra os seus requisitos e que eles foram bem testados. 

No código, é necessário garantir que ele trate exceções e que a aplicação continue a funcionar mesmo em situações adversas, como um alto número de requisições por exemplo. Na infraestrutura precisamos garantir que a aplicação se recupere de possíveis falhas e também que a troca de versões não cause grandes momentos de indisponibilidade da aplicação.

Vamos discutir um pouco mais a fundo como podemos aumentar a confiabilidade das aplicações em cada um dos estágios de uma aplicação.

### Confiabilidade no Desenvolvimento

Para aumentar a confiabilidade da aplicação devemos começar a trabalhar ainda no processo de desenvolvimento, existem várias práticas nesse processo que ajudam a aumentar bastante a confiabilidade. 

Um exemplo é a revisão de código, essa prática ajuda muito em evitar problemas como mal entendimento das regras de negócio ou exceções que um desenvolvedor não pensou. O velho ditado que duas cabeças pensam melhor que um vale bastante na programação (como em praticamente qualquer outra coisa).

Além da revisão outra prática que ajuda bastante é o desenvolvimento de testes automatizados. No mundo ideal, teríamos tempo para testar a aplicação inteira novamente a cada subida pra produção, mas sabemos que não é isso que acontece, pois isso levaria muito tempo. 

Assim, a única forma de ter segurança que uma mudança no código não teve efeitos inesperados é ter uma grande cobertura de testes automatizados.

Existem várias ferramentas que podem ser usadas nessa fase do desenvolvimento de software. Algumas comuns são um bom sistema de controle de versão, como o Git, frameworks de teste como o JUnit e Mockito para Java e ferramentas que fazem análise de código e de cobertura de testes como o Sonar.

### Confiabilidade no Código

Pensando no código, existem várias implementações para aumentar a confiabilidade no código, uma indispensável é o tratamento de exceções, para garantir que erros inesperados não estourem na cara dos usuários. Por isso tratar exceções, e se possível se recuperar delas é essencial.

Outra implementação importante em qualquer aplicação que tenha uma alta carga de trabalho é o rate limit (ou limitação de carga). Essa implementação evita um sobrecarga no servidor, e também pode ajudar a mitigar ataques do tipo DDoS, e caso um usuário passe do seu limite de requisições, o servidor pode retornar um erro 429 (Too Many Requests).

Definir timeouts para chamadas a recursos externos também é uma prática importante. As vezes é melhor falhar logo do que ficar esperando por um tempo indeterminado ou muito grande. Lembrando que na maioria dos servidores, se uma thread está parada esperando uma resposta, ela não consegue atender outras requisições, desperdiçando recursos. 

Também relacionado a recursos externos, também vale a pena mencionar os Circuit Breakers que verifica se o recurso que a aplicação está acessando está enfrentando problemas (demora na respostas ou muitos erros) e caso sim pode interromper momentaneamente as chamadas para esse recurso.

### Confiabilidade na Infraestrutura

Pensando na infraestrutura, o passo mais obvio para garantir a confiabilidade é ter mais de uma instância rodando a aplicação. Isso pode ser feito usando um balanceador de carga (Load Balancer - LB) que vai distribuir as requisições entre duas ou mais instâncias de uma aplicação, ou em uma ferramenta de gerenciamento de conteineres, como o Kubernetes.

Esse ideia de instâncias pode existir em vários níveis. Por exemplo, podem existir duas instâncias em um mesmo servidor, isso já é melhor do que nada, mas ainda pode ser insuficiente, pois se o servidor cair, as duas instâncias ficarão fora do ar. Em um provedor de cloud, é possível ter duas ou mais instâncias em diferentes áreas geográficas, o que diminui bastante a probabilidade de falhas totais.

Obviamente que para isso a aplicação deve estar preparada. Um exemplo é que para permitir a execução de mais de uma instância, a aplicação não deve ter nada local, por exemplo, um token de autenticação não pode ser mantido diretamente na aplicação, senão um token só valerão naquela instância, para isso pode ser usado um cache distribuído como o Redis.

Outro ponto bastante importante na infraestrutura é garantir a recuperabilidade da aplicação, isto é, a capacidade da aplicação se recuperar de problemas (já que problemas são inevitaveis). Um exemplo disso é se um servidor (ou VM) reiniciar automaticamente, a aplicação voltará a funcionar automaticamente ou precisará de uma intervenção humana? 

Outro exemplo de recuperabilidade são os backups, eles são essenciais para o caso de perda de dados seja possível recuperar a aplicação para um ponto não tão distante do atual. Uma dica sobre backups, nunca os guarde na mesma máquina onde a aplicação está sendo executada.

Por fim, um último requisito indispensável para a confiabilidade da aplicação é o seu monitoramento. Isso importante tanto para a aplicação quanto para a infraestrutura. Existem várias ferramentas que podem ser usadas para isso como o Prometheus, Grafana e o Dotadog.


Se tiver interesse no livro, você pode encontrar diretamente no site da Casa do Código:

https://www.casadocodigo.com.br/products/livro-caixa-de-ferramentas-da-arquitetura-de-software

ou na Amazon:

https://www.amazon.com.br/Caixa-ferramentas-Arquitetura-Software-aplica%C3%A7%C3%B5es-ebook/dp/B0CYJV5P11/ref=rvi_d_sccl_1/147-7357894-3056112