Simplificando a manutenção de seus projetos Front-End
Comumente os projetos front-end pelos lugares onde passei costumavam ser projetos grandes, com diversos fluxos de negócio dentro de uma única aplicação chamada “Portal” ou “CMS”. Estes projetos são complexos, e torna muito difícil qualquer atualização ou até mesmo a evolução tecnológica da aplicação (sabemos que no universo front-end a evolução acontece constantemente).
Hoje sabemos que existe a necessidade de construir aplicações front-end em larga escala que sejam fáceis de manter e que nos permita inovar dentro deste mesmo projeto. 🤔😥
Vamos imaginar o seguinte cenário abaixo:
— Seu time começa a desenvolver uma plataforma de e-commerce grande e você junto ao time decide utilizar um determinado framework para agilizar o desenvolvimento da plataforma, porém, passa-se algum tempo é lançada uma nova versão do framework e pra ajudar é uma versão de breaking change 😥
Pensando em uma aplicação monolítica você possui apenas duas alternativas, não atualizar o framework ou refatorar todos os pontos onde aquela determinada atualização afeta no projeto.
Em alguns casos dependendo do projeto, você não pode refatorar o sistema, pois não possui tempo hábil para executar esta demanda, o que acaba gerando um débito técnico grande no projeto, pois, dado que não é possível refatorar, você irá fazer a outra metade do projeto incluindo novos débitos técnicos. 😥
Para resolver este problema, levamos os projetos front-end para um modelo bem próximo ao dos micro serviços, criando várias aplicações e utilizando o conceito de composição, começamos a compor nossas aplicações tornando-a como se fosse uma única aplicação. 🤔
Para fazer isso, primeiro de tudo precisávamos entender como separar nossas aplicações, nos baseamos no conceito de bounded context.
Bounded Context
Bounded context é um padrão central no DDD (Domain-Driven Design), o foco do DDD esta na sessão de design estratégico que trata de grandes modelos e times. O DDD lida com grandes modelos dividindo-os em diferentes contextos limitados e sendo explícito sobre suas inter-relações.
O bounded context possui conceitos não relacionados (como um ticket de suporte existente apenas em um contexto de suporte ao cliente), mas também compartilham conceitos como produtos e clientes.
O DDD segue descrevendo diversas de maneiras pelas quais você tem relações entre os contextos limitados.
Vou utilizar como referência nosso portal da Easynvest, para podermos enxergar os diversos contextos.
— Autenticação/Autorização do usuário e recuperação de senha, já é autoexplicativo, compreende o login, esqueci minha senha e nova senha, credenciais do usuário, controle de acesso, permissões de operação, etc.
— Cadastro do usuário, compreende todo fluxo de preenchimento de informações cadastrais até a criação da conta do cliente, para que o cliente fique dentro das normativas de compliance.
— Prateleiras de produtos financeiros, compreende a exibição dos produtos fornecidos pela Easynvest— Tesouro Direto, CDB, LC, LF, LCI, LCA, Fundos de investimento e Ações
Para saber mais sobre os produtos, você pode clicar neste link ou baixar o aplicativo aqui.
— Acompanhamento dos produtos que foram comprados, o que chamamos de “custódia”, compreende a exibição dos títulos financeiros que foram adquiridos pelo cliente, nos mostra sua rentabilidade nos últimos 30 dias e o valor do rendimento em cada produto.
— Atualização de dados cadastrais do usuário, compreende dados profissionais, pessoais, residenciais, renda financeira, etc.
— Financeiro, compreende Movimentação financeira, Extrato, Imposto de Renda, etc.
Dentro de cada um destes seis contextos existem outros N contextos para atender as regras de negócio.
Ao me juntar com o time tínhamos duas opções:
1- Nós poderíamos criar uma única aplicação, que teria todas as interfaces exibidas acima (o que é comumente feito), porém, teríamos muitos problemas para evoluir a plataforma.
2- Fazer uma aplicação para cada contexto de negócio, desta forma teríamos diversas aplicações relativamente pequenas, o que tornaria mais simples a manutenção, a evolução das aplicações e o refactoring.
Optamos pela segunda opção!
Ok, agora iríamos construir N aplicações e, com certeza, apareceriam outros problemas. Os dois principais problemas que identificamos foram:
1- Como as aplicações se comunicariam?
Será que eu precisarei fazer um login para cada aplicação? Afinal o usuário precisa estar autenticado para consumir os serviços back-end!
2- Como criar componentes reutilizáveis para todas estas aplicações e que sejam fáceis para que todos os times possam utilizar?
Para resolver o problema de comunicação pensamos em uma aplicação que ficará responsável por fazer o proxy reverso para todos as outras aplicações exemplo:
A imagem acima nos mostra que os usuários chegam até o site da Easynvest através da AWS utilizando um serviço de balanceamento, no nosso o ELB que logo em seguida manda a carga para um nosso cluster Kubernetes que por sua vez orquestra os containers dentro do cluster.
O container BOOTSTRAP é o responsável por fazer o proxy reverso para as demais aplicações, ou seja, quando um usuário digita na barra de endereço do navegador a url https://www.easynvest.com.br/autenticacao é a bootstrap quem sabe pra qual container irá redirecionar o usuário, neste caso ele irá para o container de autenticação.
A bootstrap também tem uma outra função muito importante que é fazer o proxy reverso para as APIs do back-end, no nosso caso os serviços de back-end não estão no mesmo cluster.
Percebam que até o momento não falamos sobre as tecnologias que serão utilizadas no front end, pois isso não é muito relevante, cada aplicação pode ser criada com uma tecnologia diferente e todas elas podem conviver juntas.
No nosso caso na Easynvest, nosso site era escrito em ASP.MVC e front-end em Angularjs, já o portal em sua grande maioria é escrito utilizando React.
As aplicações podem ser escritas uma em React, outra em Elm, outra em Vue, outra em Angular, esta decisão vai depender do problema que queremos resolver.
Observação: esta abordagem chega muito próximo ao conceito de micro frontend citado neste site https://micro-frontends.org, no nosso caso não estamos falando de diversas tecnologia convivendo juntas em uma mesma aplicação, mas, são aplicações diferentes.
O conceito de micro frontend chega ao nível de features diferentes na mesma aplicação escrita em diferentes linguagens convivendo juntas até mesmo na mesma view como a imagem abaixo:
Não sabemos se queremos chegar a esse nível, estamos estudando para continuar propondo as soluções mais eficientes.
Conclusão
Seguindo esta abordagem:
- Agnóstico a tecnologia.
- Isolamento claro do time, o que facilita o entendimento do negócio.
- Cada time é responsável pelo seu contexto de negócio, exemplo: Time de cadastro, Time de vendas, etc.
- Aplicações relativamente pequenas, o que torna a manutenção mais simples e ágil.
- Qualquer integrante novo no time com pouco tempo pode se adaptar rapidamente ao projeto.
- Deploys independentes, não corremos o risco de afetar outra aplicação, o que da mais segurança e confiabilidade ao publicar uma nova feature ou um hotfix, bugfix, etc.
- Facilita a evolução da plataforma.
- Motiva o time a buscar cada dia mais inovação e novas formas de resolver os problemas do negócio.
- O time se sente mais motivado o que reduz a busca por oportunidades de inovação no mercado, pois você possui flexibilidade para inovar.
- A plataforma fica em um processo de constante atualização e evolução.