• Nenhum resultado encontrado

B.4 Princípios e técnicas de design de software

B.4.1 Divisão e Conquista

Divisão e conquista é uma técnica para resolução de problemas que consiste em decom- por um problema em subproblemas menores e independentes a fim de resolvê-los separa- damente, para que, posteriormente, as soluções sejam combinadas e formem a solução do problema inicialmente proposto.

B.4 Princípios e técnicas de design de software 62 A estratégia é baseada na ideia de que atacar um problema complexo por diversas frentes é mais simples e factível de resolução do que tentar resolvê-lo completamente de uma só vez. A técnica de divisão e conquista possui três etapas bem definidas:

• Divisão: dividir o problema original em subproblemas menores;

• Conquista: resolver cada um dos subproblemas gerados na fase de divisão;

• Combinação: combinar as soluções de cada subproblema, compondo a solução para o problema inicial.

Em Ciência da Computação, essa estratégia é muito utilizada no projeto de algoritmos e, normalmente, é instanciada através do uso de recursão, uma vez que os problemas devem ser decompostos e as soluções dos subproblemas devem ser combinadas ao final da execução para compor a solução do problema inicial. Por exemplo, o algoritmo de ordenação mer-

gesort se utiliza dessa técnica para ordenar uma sequência de inteiros de maneira eficiente.

Esse algoritmo se baseia na idéia de que dadas duas sequências ordenadas, é fácil ordená-las em uma única sequência. Portanto, a estratégia do mergesort é particionar uma sequência em várias subsequências até que seja trivial ordená-las, isto é, sequências de dois elementos. Por fim, o algoritmo combina as sequências em uma só sequência ordenada.

No entanto, como este livro foi escrito com foco em arquitetura de software, nada mais apropriado do que trazermos exemplos em nível arquitetural dos assuntos que abordamos. A estratégia de divisão e conquista também é aplicada constantemente em decisões de mais alto nível no projeto de software. Por exemplo, a decisão de organizar uma aplicação web em camadas nada mais é que dividir um problema maior em diferentes níveis de abstração, onde cada camada será responsável por implementar um serviço mais básico e específico (apresentação, lógica de negócio e armazenamento).

Vários são os benefícios providos pela estratégia de divisão e conquista. No nosso exem- plo, a divisão da arquitetura em camadas propicia a implementação de cada camada sepa- radamente. Além disso, as camadas podem ser tratadas como componentes reusáveis de software, uma vez que implementam um serviço único e bem definido. Portanto, divisão e conquista também viabiliza o reuso de software.

B.4 Princípios e técnicas de design de software 63

B.4.2 Abstração

Abstração é um princípio essencial para se lidar com complexidade. Esse princípio reco- menda que um elemento que compõe o design deve ser representado apenas por suas ca- racterísticas essenciais, de forma que permita a distinção de outros elementos por parte do observador. Como resultado, temos a representação de um elemento do design mais simples, uma vez que detalhes desnecessários são descartados, facilitando então o entendimento, co- municação e avaliação.

O que poderemos observar é que a maioria das técnicas empregadas por designers ajudam na elevação do nível de abstração do design e, assim, baixam o nível de complexidade da solução.

B.4.3 Encapsulamento

Encapsulamento está relacionado à ocultação de detalhes de implementação de um elemento de um sistema aos que usarão esse elemento. Fazendo isso, o acoplamento entre os elementos é minimizado e sua contribuição para a complexidade do sistema é restringida às informações que eles expõem.

Encapsulamento pode ser obtido de diferentes maneiras: modularizando o sistema, se- parando suas preocupações, separando interfaces de implementações, ou separando políticas da execução de algoritmos.

B.4.4 Modularização

Modularização é a decomposição significativa do sistema em módulos. A modularização in- troduz partições bem-definidas e documentadas ao sistema ao decidir como estruturas lógicas do sistema serão divididas fisicamente. Podemos citar alguns benefícios da modularização:

• Facilita o entendimento, uma vez que cada módulo pode ser estudado separadamente;

• Facilita o desenvolvimento, uma vez que cada módulo pode ser projetado, implemen- tado e testado separadamente;

• Diminui o tempo de desenvolvimento, uma vez que módulos podem ser implementa- dos em paralelo, ou ainda reusados; e

B.4 Princípios e técnicas de design de software 64 • Promove a flexibilidade no produto, uma vez que um módulo pode ser substituído por

outro, desde que implemente as mesmas interfaces.

B.4.5 Separação de preocupações

A separação de preocupações está fortemente ligada ao princípio da modularização. De certa maneira, a separação de preocupações define a regra para definir os módulos de um sistema: preocupações diferentes ou não-relacionadas devem se restringir a módulos diferentes. As- sim, separando preocupações, obtemos benefícios semelhantes aos da modularização.

B.4.6 Acoplamento e coesão

Acoplamento e coesão são princípios usados para medir se módulos de um design foram bem divididos.

Acoplamento é a medida de interdependência entre módulos de software. Ou seja, quanto mais dependente um módulo A é da implementação do módulo B, maior é o acoplamento entre os módulos A e B. Alto acoplamento implica que (1) os módulos envolvidos serão mais difíceis de entender, uma vez que precisam ser entendidos em conjunto; (2) os módulos envolvidos serão mais difíceis de modificar, uma vez que as mudanças impactarão mais de um módulo; e (3) os módulos envolvidos serão mais difíceis de manter, uma vez que um problema num módulo se espalhará pelos módulos com quem está altamente acoplados.

Por outro lado, coesão é uma medida intramódulo. Ela é a medida da relação entre tarefas realizadas dentro de um mesmo módulo. As tarefas de um módulo podem estar relacionadas entre si por diferentes motivos. Esses motivos são usados para classificar os diferentes tipos de coesão:

Coesão funcional: as tarefas estão agrupadas por suas funções serem similares.

Coesão sequencial: as tarefas estão agrupadas por elas pertencerem à mesma sequência de

operações. Elas compartilham dados a cada etapa da sequência, mas não realizam uma operação completa quando executadas juntas.

Coesão comunicativa: as tarefas estão agrupadas porque usam os mesmos dados, mas não

B.4 Princípios e técnicas de design de software 65

Coesão temporal: as tarefas estão agrupadas por serem executadas no mesmo intervalo de

tempo.

Coesão procedural: as tarefas estão agrupadas porque elas devem ser executadas numa or-

dem específica.

Coesão lógica: as tarefas estão agrupadas por compartilharem uma mesma flag de controle,

que indicará qual tarefa será realizada durante a execução do sistema.

Coesão coincidente: as tarefas estão agrupadas sem qualquer critério.

Para alcançarmos bons designs, podemos ordenar os tipos de coesão dos mais desejáveis para os menos desejáveis: funcional, sequencial, comunicativa, temporal, procedural, lógica, e coincidente.