Artigo Java Magazine 76 - Baixo Acoplamento
No artigo, abordaremos os diversos tipos de acoplamento de forma tanto conceitual quanto aplicada (com exemplos concretos).
Atenção: esse artigo tem uma palestra complementar. Clique e assista!
Discutimos o conceito de baixo acoplamento, algo muito citado e enfatizado ultimamente – em especial ao se falar de OO e SOA – mas nem sempre claramente definido. Algumas fontes, ex.: Wikipédia, definem baixo acoplamento como “o grau de conhecimento direto que uma classe tem de outra”; mas esta definição é bastante limitada, pois podemos definir o acoplamento de uma série de outros artefatos de software além de classes. E podemos ver que, em todos eles, quanto mais baixo este acoplamento, melhor. No artigo, abordaremos os diversos tipos de acoplamento de forma tanto conceitual quanto aplicada (com exemplos concretos).
Para que serve:
Sistemas de software com baixo acoplamento são mais robustos por uma série de motivos. Podem ser alterados com um custo e risco menores; podem ser integrados com outros sistemas com menor esforço; podem ser compreendidos com maior facilidade. Desde a análise até os testes, passando por todos os artefatos de um sistema, baixo acoplamento é um dos objetivos que o desenvolvedor deve perseguir como forma indireta de atingir muitos outros objetivos.
Em que situação o tema é útil:
Este artigo é direcionado a todos os perfis de desenvolvedores: não só programadores, mas também analistas, arquitetos, testers... É de fundamental importância que a boa-prática do baixo acoplamento seja adotada de maneira vertical (em todas as etapas de um projeto). Um design de baixo acoplamento criado por um arquiteto expert em técnicas de SOA pode ser arruinado por um programador que não sabe evitar alto acoplamento nos níveis de código e infraestrutura; por outro lado, um excelente programador que sabe tudo sobre acoplamento dificilmente pode compensar decisões de projeto que “amarram” desnecessariamente componentes, padrões, schemas e outros artefatos de arquitetura.
Este artigo é dedicado a explorar o conceito de baixo acoplamento. O termo em sido muito divulgado, principalmente desde o aparecimento das tecnologias de web services e SOA, mas seu significado é bem mais amplo e atinge todos os aspectos do desenvolvimento de software, da análise até a programação. Podemos chamar o baixo acoplamento de um “meta-paradigma”, uma boa-prática de grande alcance que pode ser integrada como princípio fundamental de qualquer metodologia ou ferramenta de desenvolvimento.
Tentaremos explicar a importância do baixo acoplamento, mostrar como este conceito se aplica de forma concreta em diversos artefatos de um projeto de software, e oferecer diretrizes para incorporar esta boa prática ao seu trabalho.
O que é Acoplamento
A definição formal é simples: Acoplamento é o grau de dependência entre dois artefatos. Esta dependência é uma medida da quantidade de informações que um artefato deve possuir sobre o outro para que as colaborações necessárias entre ambos possam ocorrer. “Artefato” pode ser praticamente qualquer coisa que faz parte do projeto – uma classe, método, componente, pacote, tabela, protocolo de comunicação, sistema externo, ator (inclusive humano), documento, etc.
Para definições mais detalhadas, minha fonte favorita é esta wiki, que trata dos conceitos afins de acoplamento e coesão: c2.com/cgi/wiki?CouplingAndCohesion.
Exemplo: Acoplamento de APIs
Começando por um exemplo concreto de acoplamento de código, vou recorrer a um dos exemplos didáticos mais manjados, um sistema bancário. Temos um cliente web ou móvel, que deseja conectar-se ao banco e obter um extrato dos últimos 30 dias de movimento para uma conta. Isso pode ser implementado de várias formas, de acordo com a interface remota do sistema bancário.
Banco banco = ... // Algum tipo de lookup: JNDI, web service, etc.
Map<Integer, Agencia> agencias = banco.getAgencias();
Agencia ag = agencias.get(1234);
Map<Integer, Conta> contas = ag.getContas();
Conta conta = contas.get(999999);
List<Lancamento> = conta.getUltimosLancamentos(30);
Utilizei variáveis intermediárias (como agencias) apenas para expor a interface das classes utilizadas. Algumas variáveis poderiam ser eliminadas, por exemplo Agencia ag = banco.getAgencias().get(1234), mas isso não teria qualquer impacto sobre a discussão de acoplamento.
Este primeiro exemplo ilustra um nível de acoplamento alto entre o programa cliente e o sistema bancário, pois a API deste sistema expõe muitos detalhes internos: a existência de vários objetos (Banco, Agencia e Conta); os relacionamentos entre eles (“1 Banco tem N Agencias”), e mesmo as estruturas de dados usadas para manipular estes relacionamentos (como um Set<Integer, Agencia>). Cada elemento individual da interface do sistema bancário está destacado em negrito; isso oferece uma visão simples (ainda que grosseira) da quantidade de acoplamento.
Compare isso com um design de baixo acoplamento para o mesmo problema:
Banco banco = ... // Algum tipo de lookup: JNDI, web service, etc.
List<Lancamento> = banco.getUltimosLancamentos(1234, 999999, 30);
Nesta segunda versão, Banco implementa o design pattern Facade, expondo de forma direta todos os métodos úteis para clientes externos, como getUltimosLancamentos(). Cada método desses recebe todos os parâmetros necessários para o contexto da operação, como no caso, os códigos da agência e da conta – assim, não precisamos expor os objetos Agencia e Conta, nem seus relacionamentos.
A importância do Acoplamento Fraco
Devemos procurar reduzir o acoplamento entre artefatos do sistema, pelo motivo bem conhecido de facilitar a evolução independente de cada um destes artefatos. No exemplo, se mudarmos alguma coisa nos relacionamentos Banco/Agencia/Conta, a primeira versão do nosso código de consulta de extrato poderá precisar de alterações, mas a segunda versão não precisará. (O leitor poderá argumentar que isso é um benefício do design pattern "
[...] continue lendo...Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo