O que é Arquitetura de Software?

Publicado em 25 Nov 2021 por André Felipe

Ao desenvolver uma aplicação, um dos componentes mais importantes é a arquitetura de software, responsável por definir como ela será construída e organizada considerando três componentes essenciais: usuários, negócio e tecnologias. Uma aplicação desenvolvida sem considerar um desses componentes será uma aplicação mal desenvolvida, pois cada um possui necessidades distintas.

Por exemplo, um usuário possui como maior necessidade uma aplicação com maior facilidade de uso e com suporte as tarefas consideradas essenciais por ele. Já para o negócio, uma aplicação que permita uma maior produtividade e com bom retorno financeiro é considerado importante. Já considerando as tecnologias, escolhê-las visando atender as necessidades dos usuários e do negócio é importante. Algumas propriedades relevantes para a escolha das tecnologias são:

  • Simplicidade, capacidade de gerenciamento e de suporte e facilidade de ensino;
  • Tempo de desenvolvimento, custo, facilidade de manutenção, modificação e testagem;
  • Escalabilidade, portabilidade, segurança, desempenho, confiabilidade e disponibilidade.

Já algumas tecnologias que afetam essas propriedades são:

  • Linguagens de programação;
  • Frameworks;
  • Padrões de arquitetura;
  • Bancos de dados;
  • Tecnologias em nuvem;

Das tecnologias citadas acima, definir quais padrões de arquitetura utilizar é uma tarefa complexa e crítica, principalmente pela variedade de padrões de arquitetura que existem. Além disso, o arquiteto de software pode utilizar sua experiência e conhecimento técnico para desenvolver um padrão de arquitetura específico para uma determinada aplicação, conforme a necessidade. Os padrões de arquitetura mais utilizados são os descritos a seguir:

Em camadas

Um dos padrões mais utilizados. Nesse padrão, os módulos da aplicação são organizados em várias camadas, sendo que cada uma se comunica apenas com as adjacentes, de forma hierárquica.

As suas principais vantagens são a sua facilidade de manutenção, modificação e testagem, além de possuir menor tempo de desenvolvimento devido a sua simplicidade. Contudo, as suas vantagens diminuem quanto maior for o número de camadas.

No exemplo descrito na imagem abaixo, existem três camadas: API, lógica de negócio (business logic) e de acesso a dados (data access). Uma quarta camada (common), mantém os componentes comuns as três camadas.

image info

Portas e Adaptadores

Esse padrão visa isolar a lógica principal de negócio, de componentes que provêm dados e eventos, também conhecidos como adaptadores, como bibliotecas, e que costumam ser mutáveis no ciclo de vida de uma aplicação. Assim, se obtém uma maior facilidade de manutenção, modificação e testagem. Contudo, a confiabilidade e a segurança da aplicação é dependente de cada adaptador, sendo necessária maior atenção, principalmente em casos de bibliotecas de terceiros.

Os adaptadores são desenvolvidos separadamente e integrados a lógica principal de negócio através de portas, trechos de código responsáveis por integrar adaptadores e portas em tempo de execução.

No exemplo abaixo, temos três portas: eventos de broadcast, na cor amarela; sensores de entrada, na cor azul; e de log, na cor verde. Além disso, temos um conjunto de adaptadores: três para sensores de entrada e dois para os demais. Pelo fato da porta ser a mesma, a lógica principal de negócio consegue se comunicar da mesma forma, independente do adaptador

image info

Canos e filtros

Esse padrão se assemelha a uma linha de montagem de uma fábrica, sendo utilizada frequentemente em aplicações de análise e transformação de dados, bem como em aplicações com um fluxo de execução mais linear. Nele, cada componente, chamado de filtro, é responsável por realizar uma única operação ou transformação de dados. Após isso, os dados são repassados para o filtro seguinte, através de um cano, uma fila contendo os dados a serem processadas por esse filtro.

Algumas vantagens incluem a facilidade de manutenção e de reaproveitamento de código, porém a principal é o desempenho, pois cada filtro é implementado de forma independente, permitindo a sua execução em paralelo com outros filtros.

Já as suas desvantagens incluem a falta de interação com o usuário, caso não sejam feitas alterações no padrão; confiabilidade não garantida pelo padrão, embora possível de ser implementada; e implementações ruins das operações de cada um dos filtros podem impactar o desempenho geral da aplicação, pois executar muitos filtros em paralelo é custoso em processamento.

Abaixo temos um exemplo desse padrão, composto por seis filtros e canos interligando cada um deles.

image info

Orientado a serviços

Também conhecido como padrão de microsserviços, componentes independentes chamados de serviços, são desenvolvidos para manter funcionalidades específicas. Em tempo de execução, esses serviços são combinados, definindo assim o funcionamento da aplicação. Um serviço de descoberta é responsável por manter a comunicação entre os serviços, bem como o estado de cada um deles e as requisições que serão repassadas a eles.

As principais vantagens desse padrão são a reusabilidade, a interoperabilidade e a escalabilidade. Pelo fato das aplicações que utilizam esse padrão serem distribuídas, as suas desvantagens são as mesmas de aplicações distribuídas, como a disponibilidade, confiabilidade e o desempenho. Além disso, aplicações com esse padrão de arquitetura são difíceis de desenvolver e dependendo do número de serviços, difíceis de manter e testar.

No exemplo abaixo, temos dois serviços, Web UI e Ratings, que estão conectados a um serviço de descoberta, Eureka. A Web UI se comunica com o Eureka, que retorna as informações sobre o serviço Ratings, para que Web UI possa se comunicar diretamente com ele. Ratings tem acesso a um banco de dados e a um serviço que persiste arquivos de configuração, Archaius.

image info

Publish-Subscribe

Também conhecido por Pub-Sub, esse padrão se assemelha ao orientado a serviços em muitos aspectos. Nele, serviços podem assumir os papéis de publisher e de subscriber. Enquanto o primeiro é responsável por produzir mensagens, o segundo é responsável por consumi-las.

Nesse padrão, um sistema de mensageria é utilizado para realizar a troca de mensagens entre publishers e subscribers, através de filas. Alguns sistemas de mensageria existentes atualmente são: RabbitMQ, Redis, Amazon MQ, Apache ActiveMQ, IBM MQ, Google Cloud Pub/Sub e Azure Queue Storage.

Suas vantagens incluem extensibilidade, reusabilidade e testabilidade. Além disso, dependendo do sistema de mensageria, disponibilidade, confiabilidade e escalabilidade também são algumas vantagens. Como esse padrão também é distribuído, desempenho também é uma das desvantagens. Além disso, como toda a comunicação é centralizada nesse sistema de mensageria, escolhe-lo de forma inadequada ou alterá-lo pode comprometer a aplicação toda, pois ele se torna um ponto central de falha.

No exemplo abaixo, sete serviços, sendo três publishers, dois subscribers e dois ambos os papéis, se comunicam através de um sistema de mensageria, em roxo, que realiza a troca de mensagens entre eles.

image info

Dados Compartilhados

Nesse padrão, vários componentes acessam os dados armazenados num banco de dados compartilhado, sendo responsável por persistir as mensagens enviadas entre os componentes, da mesma forma que um sistema de mensageria faz.

Algumas das suas vantagens são a confiabilidade, segurança e privacidade. Com o banco de dados bem configurado e otimizado, provê escalabilidade e disponibilidade. Além disso, assim como no padrão publish-subscribe, como toda a comunicação é centralizada nesse banco de dados, escolhe-lo de forma inadequada ou alterá-lo pode comprometer a aplicação toda, pois ele se torna um ponto central de falha.

No exemplo a seguir, seis componentes manipulam dois bancos de dados compartilhados, realizando escrita e leitura de dados nele.

image info

Multinível

Semelhante ao em camadas, nesse padrão, serviços específicos com finalidade semelhante, como os utilizados no acesso a uma plataforma em nuvem ou a um banco de dados, por exemplo, são agrupados e organizados em estruturas de níveis em tempo de execução.

Algumas vantagens são a segurança, desempenho, disponibilidade, escalabilidade e a facilidade de manutenção e de modificar, além de um custo menor que outras arquiteturas distribuídas como a publish-subscribe, a orientada a serviços e a de dados compartilhados.

Contudo, assim como na arquitetura em camadas, o desempenho e a capacidade de manutenção diminuem quanto maior for o número de níveis, além da alta complexidade em aplica-la em aplicações grandes.

No exemplo abaixo, temos uma aplicação com cinco níveis, onde em cada nível, estão agrupados um conjunto de serviços.

image info

Centro da Competência

Nesse padrão, um grupo de especialistas, chamado de centro da competência, fica responsável por definir a arquitetura, bem como todo o conjunto de padrões, boas práticas, convenções e ferramentas que serão utilizadas na aplicação, além de prestar suporte a equipe de desenvolvimento, visando obter um menor tempo de desenvolvimento e melhor qualidade média da aplicação.

As suas principais vantagens são a segurança, escalabilidade, desempenho, confiabilidade e manutenção de código. Além disso, permite a melhoria do conhecimento técnico da equipe de desenvolvimento, de forma escalável e reutilizável.

Entretanto, como o centro da competência criou a estrutura e organização da aplicação, a saída de pessoal desse grupo pode reduzir as principais vantagens desse padrão com o tempo. Além disso, um centro da competência com profissionais fracos podem ter o efeito oposto.

Contribuição de código aberto

Esse padrão é frequentemente utilizado quando existem muitas dependências entre componentes ou quando existem especialistas em várias equipes de desenvolvimento. Nele, as próprias equipes de desenvolvimento ficam responsáveis por desenvolver os componentes da arquitetura, bem como revisar as alterações realizadas no código, com o objetivo de descentralizar a definição da arquitetura.

Para esse padrão funcionar, a equipe deve saber que eles são responsáveis por desenvolver esses componentes e a equipe deve ter conhecimento de onde eles se encaixam no contexto da aplicação, mais amplo. Também é necessário a criação de padrões e normas para facilitar o desenvolvimento.

Suas vantagens são a facilidade de manutenção e de reaproveitamento de código, além de um menor tempo de desenvolvimento. Contudo, em muitos casos, a tarefa de aprender como a aplicação está estruturada se torna tão complexa que aplicar esse padrão se torna impraticável. Além disso, pode ser necessário aplicar outras práticas de gestão aberta para que o uso desse padrão seja feito com sucesso.

Grande bola de lama

Esse padrão é resultante do uso de más práticas de desenvolvimento, bem como da falta de conhecimento para definir uma arquitetura ideal. Uma bola de lama não possui componentes ou relações bem definidas e muitas vezes desenvolvida de forma improvisada.

Sua única vantagem é o menor tempo de desenvolvimento, ao custo da integridade da aplicação a longo prazo, além de dificultar a manutenção de código e o desenvolvimento de novas funcionalidades.

Em alguns casos, bolas de lama são criadas estrategicamente para entregar algo funcional e que agrega valor no menor tempo possível, ao custo de criar deficiências técnicas na aplicação. Os perigos dessa abordagem estão na não correção dessas deficiências, que podem conter graves falhas de segurança, como também no uso dessa abordagem como padrão de desenvolvimento, ao invés de realizar um projeto de software adequado.

Nesse artigo, vimos que definir uma arquitetura de software é uma tarefa que exige o envolvimento de uma organização. Também vimos alguns critérios para escolha de tecnologias que serão utilizadas na aplicação e alguns exemplos de arquiteturas, suas vantagens, desvantagens e os seus desafios em aplicá-los no desenvolvimento.