Estilos de Arquitetura e Separação de Responsabilidades para um Design Ágil
Autor: Wagner Santos | Publicado: 2012-02-01T13:58:00-02:00

Com a grande demanda de profissionais por parte das empresas, muitos deles acabam sendo&nbsp;contratados sem ter o devido conhecimento sobre boas práticas de desenvolvimento de software,&nbsp;infraestrutura de desenvolvimento, protocolos de comunicação, sistemas gerenciadores de banco de&nbsp;dados e muitas vezes até conhecimento básico sobre sistemas operacionais.

Além disso, dentro das&nbsp;empresas existe uma demanda cada vez maior por projetos de software de alta complexidade, com&nbsp;prazos de entrega na maioria das vezes fora da realidade. O que faz com que muitos projetos sejam&nbsp;entregues sem testes, com falhas de implementação, qualidade duvidosa e muitas vezes sem atender&nbsp;ao negócio do cliente.

Como consequência, após implantado, o sistema passa a apresentar sérios problemas como&nbsp;degradação da performance, perda de dados, cálculos incorretos, entre outros problemas, trazendo&nbsp;grandes prejuízos à empresa e fazendo com que os usuários percam a confiança no sistema e por&nbsp;fim os próprios desenvolvedores.

Direcionado para este cenário, o presente artigo visa demonstrar boas práticas de desenvolvimento&nbsp;de software e explicar os princípios fundamentais para se criar um bom design. Veremos também a&nbsp;aplicação de alguns padrões de projeto pouco difundidos, mas que são de extrema importância no dia a dia do desenvolvedor.

Estilos de Arquitetura

Quando vamos planejar o desenvolvimento de um software, geralmente um dos primeiros itens que o arquiteto de software começa a analisar é qual o melhor estilo de arquitetura que se aplica ao
contexto do projeto. Neste ponto ele leva em consideração diversos fatores, como os requisitos do software, custo, infraestrutura e conhecimento técnico da equipe.

Entender o estilo arquitetural adotado para o desenvolvimento traz diversos benefícios para os desenvolvedores e para a empresa como um todo, entre eles: fornecer uma linguagem comum entre os desenvolvedores e os demais envolvidos no projeto.

Por exemplo, quando o estilo de arquitetura é SOA, os desenvolvedores podem até conversar com pessoas de outras áreas, que não possuem&nbsp;conhecimento técnico (como detalhes da linguagem de programação, servidores de aplicação, etc.), sobre o método envolvido na automação dos processos de negócio, que as mesmas entenderão sobre o que é um serviço, governança e, dependendo do usuário, até termos mais específicos, como escalabilidade.

A Tabela 1 apresenta um resumo dos principais estilos de arquitetura.

            

                
Estilo de Arquitetura

                
Descrição

            

                Client-Server
                Também conhecida como arquitetura de duas camadas. Este tipo de arquitetura descreve a interação entre um ou mais clientes e um servidor, através de uma conexão de rede. A aplicação mais comum para esse tipo de arquitetura é um Banco de Dados no lado do servidor com a lógica da aplicação representada em Stored Procedures, e o lado do Cliente representado por aplicações conhecidas como Fat-Clients (Clientes Pesados), que muitas vezes contêm a lógica de negócio embutida no front-end. Como exemplo, podemos citar aplicações desenvolvidas com Delphi, Visual Basic, Oracle Forms, entre outros.
            

                Arquitetura baseada em Componentes
                Quando utilizamos uma arquitetura baseada em componentes, decompomos o design da aplicação em componentes lógicos com um fraco acoplamento, de forma que cada um deles seja individual e reutilizável, com uma localização transparente e interface de comunicação bem definida. Uma das grandes vantagens desse tipo de arquitetura é que ela promove a reusabilidade dos componentes e facilita a manutenção da aplicação.
            

                Domain Driven Design
                De acordo com o próprio criador, Eric Evans, DDD não é uma tecnologia e nem uma metodologia. DDD é um estilo de arquitetura orientado a objetos, focado em modelar o domínio do negócio e a lógica do domínio com o uso de técnicas, práticas e padrões de projeto.
            

                Arquitetura em Camadas
                Esse é o estilo de arquitetura mais conhecido e mais utilizado para o desenvolvimento de aplicações. Ele permite a separação dos módulos do sistema em camadas (layers) diferentes. As principais vantagens desse estilo são a facilidade de manutenção, o aumento da extensibilidade, reusabilidade e escalabilidade.
            

                3-Tiers/N-Tiers
                Esse estilo segrega as funcionalidades em segmentos separados de maneira similar ao estilo da arquitetura em camadas, mas com cada segmento alocado em camadas físicas (tiers) separadas, conforme veremos em detalhes no tópico “Arquitetura Distribuída”.
&nbsp;Ele é ideal quando o projeto demanda escalabilidade. Para isso, as camadas lógicas (layers) da aplicação são alocadas em máquinas diferentes.
&nbsp;Geralmente, ao mapear as camadas lógicas (layers) para as físicas (tiers), podemos criar um cluster ou um farm na mesma camada física para aumentar a performance e a confiabilidade da aplicação.
            

                Arquitetura Orientada a Serviços(SOA)
                SOA já deixou de ser apenas uma palavra no meio de TI para se tornar um modelo consagrado adotado em muitas empresas. Uma arquitetura orientada a serviços nada mais é do que uma aplicação que expõe e consome as funcionalidades do sistema como serviços por meio de contratos e mensagens.
&nbsp;Algumas das características de uma Arquitetura Orientada a Serviços são: a independência da Plataforma, comunicação baseada em serviços entre os componentes de software, integração de múltiplas funcionalidades em um único componente de interface do usuário e a exposição dos serviços por meio de repositórios ou catálogos.
            

                Arquitetura Orientada a Objetos
                Ao aplicar esse estilo, o sistema é dividido em objetos individuais, reutilizáveis e autossuficientes. Cada objeto contém os dados e o comportamento pelos quais é responsável.
                    Uma arquitetura orientada a objetos geralmente busca espelhar objetos do mundo real de modo a tornar simples a modelagem da aplicação.

Tabela 1. Estilos de Arquitetura.

Cluster: É um conjunto de computadores interligados que trabalham em conjunto como se fosse um único computador. Estes computadores são utilizados para suportar aplicações que têm necessidade de alta disponibilidade e alta capacidade de processamento.
Farm: Um Servidor Farm, também conhecido como Data Center, é um conjunto de servidores mantido (geralmente) por uma empresa para atender as necessidades computacionais da corporação, como o processamento de grandes volumes de informação, atender aos sistemas corporativos e prover servidores de contingência no caso de um problema no computador principal.
Repositório: Um Repositório é um local onde todos os clientes de um domínio específico publicam seus serviços, de maneira que todos os usuários passam a conhecer os serviços disponíveis e como acessá-los.
Para tanto, um repositório deve ter uma interface bem definida para publicação dos serviços, funções para localização, controle e maneira uniforme de acesso.

Uma vez que o estilo de arquitetura é definido, o passo seguinte é definir como as funcionalidades do sistema serão divididas, de forma a manter em conjunto os componentes relacionados (alta
coesão), e fazer com que estes possuam o mínimo de conhecimento sobre os outros componentes (baixo acoplamento). Para alcançar o baixo acoplamento e uma alta coesão é importante entender o conceito de Separação de Responsabilidades.

Separação de Responsabilidades (Separation of Concerns)

O termo Separação de Responsabilidades foi criado pelo pai do algoritmo de caminho mínimo, o cientista Edsger W. Dijkstra em 1974, e tem como objetivo dividir a aplicação em funcionalidade distintas com a menor similaridade possível entre elas. Para aplicar com sucesso este princípio, o mais importante é minimizar os pontos de interação para obter alta coesão e baixo acoplamento entre os componentes do sistema. Para tanto, é recomendado, primeiro dividir suas responsabilidades e organizá-las em elementos bem definidos, sem repetição de código ou de funcionalidade.

O tipo de separação de conceito mais difundido é o da separação horizontal, onde dividimos a aplicação em camadas lógicas de funcionalidades, como por exemplo, o protocolo TCP/IP (modelo OSI), que é separado pelas camadas de aplicação, transporte, rede, enlace e física. Neste modelo, cada camada tem sua própria responsabilidade e não precisa conhecer as camadas adjacentes. Voltando ao nosso mundo, em uma aplicação Java EE, as camadas mais conhecidas são a de Apresentação, Serviço, Domínio e Infraestrutura, como ilustra a Figura 1.





Figura 1. Separação Horizontal de Conceitos (Camadas lógicas de uma aplicação).

Podemos também aplicar o tipo de separação vertical, onde dividimos a aplicação em módulos ou funcionalidades que são relacionadas a um subsistema ou grupo de operações dentro de um sistema.
Veja um exemplo na Figura 2.




Figura 2. Separação Vertical de Conceitos.

Separar as funcionalidades de uma aplicação em módulos deixa claro as responsabilidades e dependências de cada funcionalidade, o que ajuda na execução dos testes e na manutenção do
software. Na Figura 2 fazemos um agrupamento por módulos; neste caso a separação foi feita pelos módulos de RH, Contábil e Marketing.

Além disso, podemos utilizar o conceito de separação vertical em conjunto com o conceito de separação horizontal. Veja um exemplo na Figura 3.




Figura 3. Aplicação da Separação de Conceitos Vertical e Horizontal.

Um papel importante da separação de conceitos é o da separação de comportamento, que envolve a divisão dos processos do sistema em unidades lógicas de código reutilizáveis e gerenciáveis. Ao organizar o comportamento, alcançamos os seguintes benefícios:

Eliminamos a duplicação de funcionalidades;
Minimizamos as dependências externas;
Maximizamos o potencial para reuso;
Restringimos o escopo do trabalho para os limites de cada módulo.

Como vimos, é importante entender a separação de conceitos pois ao modelarmos uma aplicação devemos ter conhecimento das responsabilidades de cada um de seus componentes. Além disso, devemos ter uma ideia de como será feita esta separação e como será feita a distribuição destes componentes na arquitetura disponível pelo cliente.

Para tanto, é preciso levar em consideração&nbsp;outros fatores, como infraestrutura e recursos disponíveis, conforme veremos a seguir, no próximo artigo da série.

Referências

Excelente artigo sobre separação de responsabilidades
http://www.aspiringcraftsman.com/2008/01/art-of-separation-of-concerns/

Biografia de Edsger Dijkstra.
http://pt.wikipedia.org/wiki/Edsger_Dijkstra

Guia de Arquitetura de Aplicações da Microsoft.
http://www.codeplex.com/AppArchGuide