Aplicações Monolíticas VS Aplicações Modulares
Se você está começando nessa carreira de desenvolvedor de software, em algum momento você já deve ter ouvido falar sobre aplicações monolíticas (back-end e front-end junto) e aplicações modulares (que separam em projetos diferentes tudo o que é back-end do que é front-end).
Pois bem, começando lá atrás, desde os primordios do desenvolvimento web, todas as aplicações eram construídas (se não todas) de forma monolítica.
E dái você pode me perguntar, o que vem a ser uma aplicação monolítica?
O que são aplicações monolíticas?
Uma aplicação monolítica é aquela em que todo código-fonte da sua aplicação é desenvolvido, criado e mantido como uma única unidade.
Isso significa dizer que tanto as funcionalidades caracterizadas como back-end e front-end, coexistem dentro de um único projeto (dentro de uma pasta do projeto).
É claro que dentro dessas aplicações existem toda uma arquitetura que garante uma organização melhor do seu código, fazendo com que as funcionalidades atreladas ao back-end fiquem agrupadas em um canto, e as funcionalidades do front-end em outro.
É o que acontece quando usamos a estrutura MVC (Modal-View-Controller), onde os Modals que representam a lógica do negócio ficam separados das Views (representa o front-end) e também dos controllers (fazem a intermediação entre o modal e as views).
Ou seja, códigos HTML, CSS e Javascript (Server Side) que representam o front-end, ficam todos agrupados em uma pasta chamada Views.
Já os códigos que representam a lógica da aplicação (Classes, Funções, Serviços...) ficam separados dentro de outras pastas como Modals (ou Services).
Onde todas essas pasta existem dentro de uma mesma pasta principal, que no caso é a pasta do seu projeto.
Para exemplificar melhor, vou pegar como exemplo uma aplicação que postei recentemente no meu GitHub chamada de Evental.
Essa aplicação foi feita em PHP junto com o Framework Laravel, que em sua forma padrão é frequentemente usado para criar aplicações web monolíticas.
Observe que dentro da pasta do projeto, os Controllers existem dentro de Evental > app > Http > Controllers. Os Models existem dentro da pasta Evental > app > Models, e por fim temos as Views que podem ser encontradas em Evental > resources > views.
Além disso, todos os assets, como ícones, estilos css, arquivos javascript, imagens, vídeos... existem dentro de public > assets.
Apesar de tudo isso estar "junto e misturado" dentro de um mesmo projeto (pasta Evental), mesmo assim conseguimos organizar o que é back-end do que é front-end.
Isso é uma aplicação monolítica 😄
Vale ressaltar que aplicações monolíticas não se limitam a apenas aplicações web, como também aplicações desktop e mobile.
O que são aplicações modulares?
Já as aplicações modulares, são aquelas em que todo o código-fonte da aplicação é organizado em módulos independentes e interconectados, em vez de agrupamentos como é o caso das aplicações monolíticas.
Ou seja, uma aplicação modular é aquela em que o front-end é totalmente separado do back-end da aplicação, de forma que o back-end se transforma em uma API que é consumida pelo front-end.
Ainda não entendeu? Então vamos dar uma olhada em um outro projeto que construi recentemente chamado de ChickenSteen.
A ChickenSteen é um sistema de reservas de restaurantes, onde foi desenvolvido em conjunto com PHP, usando o conceito de aplicações modulares.
Se você deu uma olhada no readme do repositório, deve ter notado que o portal do sistema depende de um outro projeto chamado de API da ChickenSteen.
Que por sua vez foi feito em PHP usando o Framework Laravel.
Com isso, nós temos um único sistema principal (ChickenSteen) que tem sua lógica de negócios totalmente separado da parte visual do site. Ou seja, o back-end é separado do front-end.
Onde o FRONT-END é responsável apenas por lidar com o usuário e trafegar as informações para o BACK-END, onde este, por sua vez, fica responsável por lidar apenas pela lógica de negócios.
Geralmente aplicações front-end modulares, podem ser feitas apenas com HTML, CSS e Javascript (como foi o caso da ChickenSteen) como também podem ser feitas utilizando algum framework como Angular, Vue, ReactJS, Svelte e entre outras, o que facilita bastante o tempo de desenvolvimento.
Isso é uma aplicação Modular 😄
E não acaba por aí, da mesma forma que separamos o back-end do front-end, você poderia usar o conceito de microserviços de modo a criar diversos back-ends que seriam consumidos pelo mesmo front-end, como por exemplo:
- Uma API que só vai receber e tratar os contatos recebidos pela página de contato,
- Uma API que só vai enviar e-mails para o cliente/estabelecimento após uma reserva,
- Uma API que só vai cuidar das reservas, e por aí vai...
Isso é uma aplicação modular que faz uso do conceito de microserviços 😄
Aplicações modulares podem ser instaladas em diferentes servidores, imagine que o front-end da sua aplicação esta instalado no servidor A, e que o back-end está instalado no servidor B, incrível não?
Prós e Contras em Aplicações Monolíticas e Modulares
Como tudo nessa vida tem seus prós e contras, em aplicações monolíticas e modulares isso não poderia ser diferente.
Vejamos cada um deles 🙂
Prós e Contras no uso de aplicações monolíticas
A começar pela simplicidade dessas aplicações, onde inicialmente elas são mais fáceis e rápidas de se desenvolver, especialmente quando se trata de aplicações menores e que não possuem um nível alto de complexidade.
Vamos supor que você precise desenvolver uma aplicação simples de gerenciamento de tarefas (algo muito similar ao que eu construi na Evental) na qual só você, ou um grupo pequeno de pessoas irão usar.
Partindo do presuposto de que essa aplicação não vai ser escalável, ao mesmo tempo que só será usada por um número relativamente pequeno de pessoas, onde raramente receberá manutenção e atualização, podemos cria-la facilmente dentro de uma aplicação monolítica, seguindo o padrão MVC.
Pois é mais rápido e mais simples fazer dessa forma, dada as circustâncias em que o projeto foi criado.
Um outro ponto positivo se dá na facilidade do desenvolvimento, uma vez que toda a lógica existe dentro de um só lugar, o que facilita a compreensão e a colaboração entre os desenvolvedores.
Já em quesito de escalabilidade, aplicações monolíticas são feitas verticalmente (escalabilidade vertical), ou seja, você aumenta os recursos do servidor (coloca mais memoria, adiciona mais processamento...) a medida em que a sua aplicação necessita de mais recursos.
Mas como nem tudo são flores, segue a lista dos contras:
Um dos pontos negativos principais atrelado a aplicações monolítcas, deve-se ao fato do seu acoplamento forte, o que torna futuras atualizações mais complexas e arriscadas, uma vez que tudo coexiste dentro de uma "grande pizza", dificultando sua manutenção.
Em segundo lugar, temos o tempo de inicialização prejudicado e relativamente mais longo que em aplicações modulares, pois todos os componentes precisam ser carregados, mesmo que apenas uma parte da aplicação seja usada.
Prós e Contras no uso de aplicações modulares
Graças ao desacoplamento das funcionalidades, elas acabam se tornando independentes uma das outras, o que significa que cada parte da sua aplicação pode ser desenvolvida, testada e mantida separadamente por uma equipe multidisciplinar de desenvolvedores.
E não preciso nem falar que o ganho de escalabilidade é muito maior, não é verdade?
Pois pensa comigo... se cada parte da sua aplicação é separada, você pode muito bem adicionar mais processamento na aplicação (módulo) que requer mais processamento.
Um outro ponto importante, se dá na sua reutilização de código, onde os códigos podem ser reutilizados em diferentes partes da aplicação ou em outras aplicações.
Por exemplo, anteriormente citamos a construção de uma possível API de envio de e-mails para a ChickenSteen. Supondo que no futuro precisássemos criar um outro projeto que fizesse o uso de envio de e-mails, nós não precisaríamos replicar o código, bastando apenas apontar para uma API que já existe.
Se isso fosse feito numa aplicação monolítica, precisariamos duplicar a funcionalidade de envio de e-mail para o projeto seguinte.
Por fim, nós temos a flexbilidade atrelada a manutenção da aplicação, o que nos permite que novos módulos sejam adicionados ou existentes sejam modificados sem impactar outras partes da aplicação.
Falando agora sobre contras em aplicações modulares, em primeiro lugar nós temos uma certa complexidade inicial, pois o fato de termos que separar a aplicação em partes menores, requer mais trabalho em configurar esses serviços e conecta-los uns aos outros, o que representa uma barreira inicial muito grande.
Além disso, podemos nos deparar com problemas relacionados a sobrecarga dessas aplicações, uma vez que a modularidade pode levar a uma excessiva subdivisão da aplicação em módulos pequenos, o que pode aumentar a complexidade geral e dificultar a compreensão do sistema como um todo.
Quando devemos usar aplicações monolíticas e quando optar por modulares?
Diversos desenvolvedores possuem dúvidas relacionadas a essa questão. Onde muitos deles acabam optando pela criação de aplicações modulares, simplesmente por estarem por estar "em alta", mesmo quando isso não é necessário.
Visando responder essas perguntas acompanhe os tópicos abaixo.
Quando fazer o uso de aplicações monolíticas?
Essas aplicações podem ser uma escolha adequada em varias situações, especialmente aquelas onde a simplicidade, rapidez de desenvolvimento e custo-benefício são mais importantes do que a escalabilidade e a flexibilidade a longo prazo.
Startups, Pequenas e Médias Empresas: Quando temos uma empresa menor com recursos limitados, uma aplicação monolítica pode ser a escolha ideal, principalmente quando estamos criando um MVP (Minimum Viable Product) ou quando temos um projeto que ainda não sabemos se ele vai dar certo.
Quando temos aplicações internas: Uma aplicação que só é usada internamente por membros da empresa, ou quem sabe pela pessoa que criou o projeto (onde só ela vai usar), pode ser desenvolvida usando aplicações monolíticas devido à sua simplicidade e rapidez de desenvolvimento.
Portanto, se você tem uma ferramenta de gestão interna, um blog simples, um sistema de gerenciamento de conteúdo (CMS) onde só você vai usar, e-commerces e lojas virtuais de pequena escala, onde tudo isso está sendo mantido por uma equipe pequena de desenvolvedores, todas essas aplicações podem ser criadas de forma monolítica.
Beleza, e a partir de qual ponto eu devo considerar o uso de aplicações modulares?
Quando fazer o uso de aplicações modulares?
Existem situações bem específicas quando devemos optar pela criação de aplicações módulares especialmente quando há uma necessidade de escalabilidade, flexibilidade e manutenibilidade a longo prazo.
Quando a equipe está crescendo: quando temos uma equipe de desenvolvedores que anda trabalhando em diferentes partes da aplicação de forma simultânea, uma arquitetura modular pode facilitar a colaboração e evitar conflitos de código.
Complexidade crescente: à medida em que a sua aplicação vai recebendo novas atualizações e funcionalidades, ela acaba se tornando mais complexa, nesse caso, uma arquitetura modular te ajuda a manter o código mais coeso e organizado, o que ajuda na manutenção do mesmo.
Melhor escalabilidade: aplicações modulares são mais fáceis de serem escaladas, uma vez que você pode optar por escalar uma parte da aplicação e não um todo.
Possibilidade de se trabalhar com muitas tecnoligias diferentes: Quando temos uma aplicação monolítica costumamos ficar presos em uma gama limitante de tecnologias, mas quando temos algo modular, podemos ter um front-end feito em ReactJS, outro em AngularJS, e diversos back-ends feitos em NodeJS, PHP, C#, Python... onde todos se comunicam por meio de requisições HTTP ou filas de mensageria.
Geralmente aplicações modulares costumam custar mais barato para a empresa a longo prazo do que aplicações monolíticas, pois você acaba direcionamento os custos de escalabilidade para os modulos que realmente precisam ser escaláveis (de mais processamento), em vez de precisar escalar a aplicação como um todo só por conta de uma funcionalidade que requer mais processamento, por exemplo.
Perguntas & Respostas: Criar uma aplicação monolítica ou modular?
1) Estou criando uma startup (que ainda não sei se vai dar certo)
R:. Como se trata de uma aplicação que pode ter futuro ou não, o ideal é seguir o caminho de maior custo benefício (Aplicação Monolítica), pois saem mais barato e são mais simples de serem criadas.
2) Estou criando um sistema na qual somente eu irei usar
R:. Ao menos que esse sistema esteja sendo criado com o objetivo de se aprender a criar aplicações modulares, optar por uma aplicação monolítica é o ideal. Ao menos que o sistema em que esteja criando seja muito complexo.
3) Estou criando um sistema onde uma pequena equipe vai usa-lo
R:. Sistemas como pequenos CRMs, gestão de processos, gerenciadores de conteúdo são muito bem vindos em aplicações monolítcas. Mas a medida em que novas funcionalidades vão sendo inseridas e mais pessoas vão utilizando, é hora de pensar em aplicações modulares.
4) Fui convidado para trabalhar em uma empresa de grande porte e preciso decidir se sigo na construção de uma aplicação monolítica ou modular
R:. Empresas de grande porte (milionárias) costumam atender uma grande game de clientes de forma simultânea, além disso, a equipe de funcionarios (incluíndo desenvolvedores) costuma ser gande. E como de praxe empresas assim, preferem seguir as melhores técnicas e práticas do mercado, logo é inevitável o uso de aplicações modulares, uma vez que, elas se tornam mais baratas a longo prazo com relação as monolíticas.
Segurança: Aplicações Monolíticas e Aplicações Modulares
Quando falamos sobre segurança, temos que estar atentos ao fato de que aplicações monolíticas costumam ser relativamente mais seguras do que aplicações modulares (principalmente se tratando de aplicações front-end).
Para exemplificar isso, vamos imaginar que estamos criando um sistema que só quem está logado na plataforma, terá acesso a palavra-passe para entrar na festa do clube do bolinha.
Considerando que essa plataforma foi feita em duas arquiteturas diferentes, uma monolítica e outra modular (onde o front-end está separado do back-end).
Na aplicação monolítica (feita em PHP) teriamos a seguinte lógica:
Já na aplicação modular (feita em ReactJS) temos a lógica:
Ache o erro!
Apesar da senha do clube do bolinha estar sendo armazenada diretamente no front-end em ambas as aplicação (o que é errado, pois ela deveria vir de um banco de dados, ou de um back-end por meio de uma requisição no front-end).
A aplicação monolitica ainda assim, consegue deixar essa senha mais segura, pois o back-end é executado antes do front-end ser mostrado ao usuário.
De modo que, mesmo que um usuário mal intencionado tente acessar a página Home, ele nunca vai chegar no front-end que mostra a senha, pois a única coisa que ele vai receber é um redirect para o login.
Isso aconteceu pois o PHP é executado primeiro do lado do servidor, onde somente a resposta da requisição é enviada de volta ao navegador do usuário.
E como a resposta será sempre um redirect, um usuário deslogado nunca sequer verá o HTML do arquivo tela-home-bolinha-senha.php
(ao menos que ele esteja logado).
Já no ReactJS o funcionamento é diferente, uma vez que toda a lógica da aplicação está a merce do navegador, sendo assim, qualquer usuário com o minimo de conhecimento em Javascript, poderia acessar o console do navegador, e desativar a verificação relacionada a constante do usuarioLogado
, o que o faria ser levado para a tela aonde a senha está sendo mostrada.
Isso aconteceu pois o ReactJS usa Javascript que por sua vez é server side, o que faz com que toda a lógica esteja exposta para o usuário final.
Logo, a senha do clube do bolinha não está tão segura quanto no PHP. Mas isso não significa que o PHP é melhor que ReactJS nem nada do tipo.
Eu usei este exemplo para exemplificar que quando estamos trabalhando com aplicações modulares (especialmente as front-end) qualquer informação sensível SEMPRE deve vir do back-end da aplicação, e NUNCA ser armazenada no front-end.
Isso significa que diferente de uma aplicação monolítica, na aplicação modular (front-end) devemos ter um certo nível de cuidado, onde quem dita as regras é SEMPRE o back-end, e o front-end só EXECUTA aquilo de acordo com os dados que ele recebe.
Sendo assim:
Autenticação deve ser feita no back-end: A autenticação de usuários deve ser realizada sempre no back-end, onde as credenciais do usuário são verificadas e os tokens de acesso são gerados. O front-end pode até solicitar a autenticação, mas o processo real deve ser tratado no back-end para garantir segurança e consistência.
Sempre verifique se o usuário tem permissão para tal ação: Mesmo o usuário logado no Front-End, é de vital importância verificar se ele pode executar determinada ação quando uma requisição chega no back-end.
Informações sensíveis devem vir do back-end: Informações sensíveis, como senhas, chaves de API, dados confidenciais do usuário, urls de vídeos internos... devem ser manipuladas exclusivamente pelo back-end. O front-end não deve ter acesso direto a essas informações e deve confiar no back-end para fornecê-las de forma segura, conforme necessário.
Ocultação de informações confidenciais: Qualquer informação ou URL que deva ser oculta do usuário final não deve ser diretamente acessível pelo front-end. O back-end deve controlar o acesso a essas informações e fornecê-las ao front-end apenas quando apropriado.
Validação de entrada: A validação de entrada e a prevenção de ataques de injeção (como SQL injection e XSS) devem ser realizadas também no back-end para garantir que os dados recebidos (e pré-tratados) do front-end sejam seguros e confiáveis.
Nunca confie nos dados enviados pelo front-end: principalmente quando estamos enviando formulários em que por exemplo: é checado se o campo login possui entre 5 a 60 caracteres. Lembre-se de refazer essas validações no back-end também.
Segurança da comunicação: A comunicação entre o front-end e o back-end deve ser segura, utilizando protocolos como HTTPS para criptografar os dados em trânsito e garantir que eles não sejam interceptados ou modificados por terceiros. Saiba como garantir ainda mais a segurança da sua aplicação com essas dicas.
Como aumentar a segurança da sua aplicação modular (front-end)?
Vamos supor que em uma aplicação front-end feita em ReactJS, eu dou a possibilidade para que meu usuário consiga editar as informações do seu proprio perfil.
Sabendo que essa operação deve ser realizada pelo back-end, quais os passos mais seguros de se implementar essa lógica?
Pois bem, considerando que seu usuário já esteja logado e que os tokens de acesso estão armazenados de forma segura no front-end, existem alguns pontos importantes a serem considerados:
Autenticação do usuário: Antes de qualquer operação de edição de dados, o back-end deve verificar se o usuário está autenticado e tem uma sessão válida. Isso garante que apenas usuários autenticados possam acessar e modificar informações.
Autorização do usuário: Além de verificar a autenticação, o back-end também deve verificar se o usuário tem permissão para editar a informação específica. Isso pode envolver verificar se o usuário possui os privilégios adequados ou se é o proprietário dos dados que está tentando editar.
Validação dos dados: O back-end deve validar os dados enviados pelo front-end para garantir que estejam corretos e seguros. Isso inclui verificar se os dados estão no formato esperado, se não estão corrompidos ou maliciosos e se atendem a quaisquer restrições de negócios ou de segurança.
Auditoria e registro: É uma boa prática manter um registro de todas as operações de modificação de dados realizadas pela aplicação, incluindo detalhes sobre o usuário que fez a modificação, os dados que foram modificados e o momento em que ocorreu a modificação. Isso pode ajudar na resolução de problemas e na investigação de atividades suspeitas.
Conclusão
No fim das contas, criar aplicações monolíticas é como colocar todos os ovos numa mesma cesta, ou seja, a medida em que a aplicação vai crescendo, precisamos aumentar o espaço da cesta como um todo.
já aplicações modulares é como dividir esses ovos em diferentes cestas, onde a cesta que possui mais ovos é a que deve possuir mais espaço.