---
title: "Acoplamento (programação de computadores)"
type: "antipattern"
slug: "coupling"
url: "http://localhost:3000/pt-br/antipatterns/coupling.md"
description: "Grau de interdependência entre módulos de software"
---
# Acoplamento (programação de computadores)

> Grau de interdependência entre módulos de software

Na [engenharia de software](https://en.wikipedia.org/wiki/Software%5Fengineering "Software engineering"), o **acoplamento** é o grau de interdependência entre [módulos](https://en.wikipedia.org/wiki/Modular%5Fprogramming "Modular programming") de software, uma medida de quão estreitamente conectadas estão duas rotinas ou módulos e da força dos relacionamentos entre módulos. O acoplamento não é binário, mas multidimensional.

O acoplamento costuma ser contrastado com a [coesão](https://en.wikipedia.org/wiki/Cohesion%5F%28computer%5Fscience%29 "Cohesion (computer science)"). O [baixo acoplamento](https://en.wikipedia.org/wiki/Loose%5Fcoupling "Loose coupling") frequentemente se correlaciona com alta coesão, e vice-versa. O baixo acoplamento costuma ser considerado um sinal de um [sistema de computação](https://en.wikipedia.org/wiki/Computer%5Fsystem "Computer system") bem estruturado e de um bom projeto e, quando combinado com alta coesão, contribui para os objetivos gerais de alta [legibilidade](https://en.wikipedia.org/wiki/Computer%5Fprogramming#Readability%5Fof%5Fsource%5Fcode "Computer programming") e [manutenibilidade](https://en.wikipedia.org/wiki/Maintainability "Maintainability").

## História

As [métricas de qualidade de software](https://en.wikipedia.org/wiki/Software%5Fmetric "Software metric") de acoplamento e coesão foram criadas por [Larry Constantine](https://en.wikipedia.org/wiki/Larry%5FConstantine "Larry Constantine") no final da década de 1960 como parte de um [projeto estruturado](https://en.wikipedia.org/wiki/Structured%5Fdesign "Structured design"), com base em características de “boas” práticas de programação que reduziam os custos de manutenção e modificação. O projeto estruturado, incluindo coesão e acoplamento, foi publicado no artigo _Stevens, Myers & Constantine_ (1974) e no livro _Yourdon & Constantine_ (1979), e este último tornou-se posteriormente terminologia padrão.

## Acoplamento versus coesão

Acoplamento e [coesão](https://en.wikipedia.org/wiki/Cohesion%5F%28computer%5Fscience%29 "Cohesion (computer science)") são termos que aparecem juntos com muita frequência. O acoplamento refere-se às interdependências entre módulos, enquanto a coesão descreve quão relacionadas estão as funções dentro de um único módulo. A baixa coesão implica que um determinado módulo executa tarefas que não são muito relacionadas entre si e, portanto, pode criar problemas à medida que o módulo cresce.

## Grau

O acoplamento pode ser "baixo" (também "[frouxo](https://en.wikipedia.org/wiki/Loose%5Fcoupling "Loose coupling")" e "fraco") ou "alto" (também "rígido" e "forte"). Alguns tipos de acoplamento, em ordem do mais alto ao mais baixo, são os seguintes:

### Programação procedural

Aqui, um módulo refere-se a uma sub-rotina de qualquer tipo, ou seja, um conjunto de uma ou mais instruções que tem um nome e, de preferência, seu próprio conjunto de nomes de variáveis.

Acoplamento de conteúdo (alto)

Diz-se que ocorre acoplamento de conteúdo quando um módulo usa o código de outro módulo, por exemplo um desvio. Isso viola o [ocultamento de informação](https://en.wikipedia.org/wiki/Information%5Fhiding "Information hiding") – um conceito básico de projeto de software.

Acoplamento comum

Diz-se que ocorre acoplamento comum quando vários módulos têm acesso aos mesmos dados globais. Mas isso pode levar à propagação descontrolada de erros e a efeitos colaterais imprevistos quando alterações são feitas.

Acoplamento externo

O acoplamento externo ocorre quando dois módulos compartilham um formato de dados imposto externamente, um [protocolo de comunicação](https://en.wikipedia.org/wiki/Communication%5Fprotocol "Communication protocol") ou uma interface de dispositivo. Isso está basicamente relacionado à comunicação com ferramentas e dispositivos externos.

Acoplamento de controle

O acoplamento de controle é um módulo controlando o fluxo de outro, passando-lhe informações sobre o que fazer (por exemplo, passando uma flag indicando o que fazer).

Acoplamento por estampa (acoplamento por estrutura de dados)

O acoplamento por estampa ocorre quando módulos compartilham uma [estrutura de dados](https://en.wikipedia.org/wiki/Data%5Fstructure "Data structure") composta e usam apenas partes dela, possivelmente partes diferentes (por exemplo, passar um registro inteiro para uma função que precisa de apenas um de seus campos).

Nessa situação, uma modificação em um campo de que um módulo não precisa pode levar à alteração da forma como o módulo lê o registro. Para ilustrar o conceito de acoplamento por estampa, considere um cenário envolvendo um [componente](https://en.wikipedia.org/wiki/Software%5Fcomponent "Software component") `UserProfile`. Esse componente foi projetado para retornar todas as informações do perfil do usuário em resposta a [requisições](https://en.wikipedia.org/wiki/HTTP "HTTP"), mesmo quando os [consumidores](https://en.wikipedia.org/wiki/User%5Fagent "User agent") precisam apenas de um [atributo](https://en.wikipedia.org/wiki/Attribute%5F%28computing%29 "Attribute (computing)") específico. Essa prática exemplifica o acoplamento por estampa, que pode causar problemas significativos de [largura de banda](https://en.wikipedia.org/wiki/Bandwidth%5F%28computing%29 "Bandwidth (computing)"), especialmente em escala. Quando qualquer atributo dentro do componente `UserProfile` muda, todos os consumidores que interagem com ele podem precisar passar por [testes](https://en.wikipedia.org/wiki/Software%5Ftesting "Software testing"), mesmo que não utilizem o atributo modificado.

Acoplamento de dados

O acoplamento de dados ocorre quando módulos compartilham dados por meio de, por exemplo, parâmetros. Cada dado é um elemento elementar, e esses são os únicos dados compartilhados (por exemplo, passar um inteiro para uma função que calcula uma raiz quadrada).

### Programação orientada a objetos

Acoplamento de subclasse

Descreve o relacionamento entre um filho e seu pai. O filho está conectado ao seu pai, mas o pai não está conectado ao filho.

Acoplamento temporal

É quando duas ações são agrupadas em um único módulo apenas porque acontecem de ocorrer ao mesmo tempo.

Em trabalhos recentes, vários outros conceitos de acoplamento foram investigados e usados como indicadores para diferentes princípios de modularização utilizados na prática.

#### Acoplamento dinâmico

O objetivo de definir e medir esse tipo de acoplamento é fornecer uma avaliação em tempo de execução de um [sistema de software](https://en.wikipedia.org/wiki/Software%5Fsystem "Software system"). Argumenta-se que as métricas de acoplamento estático perdem precisão ao lidar com um uso intensivo de vinculação dinâmica ou herança. Na tentativa de resolver esse problema, foram levadas em consideração medidas de acoplamento dinâmico.

#### Acoplamento semântico

Esse tipo de métrica de acoplamento considera as semelhanças conceituais entre entidades de software usando, por exemplo, comentários e identificadores, e baseando-se em técnicas como a [indexação semântica latente](https://en.wikipedia.org/wiki/Latent%5Fsemantic%5Findexing "Latent semantic indexing") (LSI).

#### Acoplamento lógico

A análise de acoplamento lógico (ou acoplamento evolutivo ou acoplamento de mudança) explora o histórico de versões de um sistema de software para encontrar padrões de mudança entre módulos ou classes: por exemplo, entidades que tendem a ser alteradas juntas ou sequências de alterações (uma alteração em uma classe A é sempre seguida por uma alteração em uma classe B).

## Dimensões do acoplamento

Segundo Gregor Hohpe, o acoplamento é multidimensional:

* Dependência de tecnologia
* Dependência de localização
* Dependência de topologia
* Dependência de formato e tipo de dados
* Dependência semântica
* Dependência de conversação
* Dependência de ordem
* Dependência temporal

## Desvantagens do acoplamento forte

Sistemas fortemente acoplados tendem a apresentar as seguintes características de desenvolvimento, que muitas vezes são vistas como desvantagens:

1. Uma alteração em um módulo geralmente força um [efeito cascata](https://en.wikipedia.org/wiki/Ripple%5Feffect "Ripple effect") de alterações em outros módulos.
2. A montagem dos módulos pode exigir mais esforço e/ou tempo devido ao aumento da dependência entre módulos.
3. Um módulo específico pode ser mais difícil de [reutilizar](https://en.wikipedia.org/wiki/Code%5Freuse "Code reuse") e/ou testar porque os módulos dependentes precisam ser incluídos.

## Problemas de desempenho

Seja com acoplamento frouxo ou forte, o desempenho de um sistema costuma ser reduzido pela criação, transmissão e tradução (por exemplo, marshaling) de mensagens e parâmetros e pela interpretação de mensagens (que pode ser uma referência a uma string, vetor ou estrutura de dados), o que exige menos sobrecarga do que criar uma mensagem complicada, como uma mensagem [SOAP](https://en.wikipedia.org/wiki/SOAP "SOAP"). Mensagens mais longas exigem mais CPU e memória para serem produzidas. Para otimizar o desempenho em tempo de execução, o comprimento da mensagem deve ser minimizado e o significado da mensagem deve ser maximizado.

Sobrecarga e desempenho de transmissão de mensagens

Como uma mensagem deve ser transmitida por completo para reter todo o seu significado, a transmissão de mensagens deve ser otimizada. Mensagens mais longas exigem mais CPU e memória para serem transmitidas e recebidas. Além disso, quando necessário, os receptores devem remontar uma mensagem ao seu estado original para recebê-la completamente. Portanto, para otimizar o desempenho em tempo de execução, o comprimento da mensagem deve ser minimizado e o significado da mensagem deve ser maximizado.

Sobrecarga e desempenho de tradução de mensagens

Os protocolos de mensagens e as próprias mensagens frequentemente contêm informações extras (ou seja, informações de pacote, estrutura, definição e linguagem). Por isso, o receptor muitas vezes precisa traduzir uma mensagem para uma forma mais refinada, removendo caracteres extras e informações de estrutura e/ou convertendo valores de um tipo para outro. Qualquer tipo de tradução aumenta a sobrecarga de CPU e/ou memória. Para otimizar o desempenho em tempo de execução, a forma e o conteúdo da mensagem devem ser reduzidos e refinados para maximizar seu significado e reduzir a tradução.

Sobrecarga e desempenho de interpretação de mensagens

Todas as mensagens devem ser interpretadas pelo receptor. Mensagens simples, como inteiros, podem não exigir processamento adicional para serem interpretadas. No entanto, mensagens complexas, como as mensagens [SOAP](https://en.wikipedia.org/wiki/SOAP "SOAP"), exigem um parser e um transformador de strings para que exibam os significados pretendidos. Para otimizar o desempenho em tempo de execução, as mensagens devem ser refinadas e reduzidas para minimizar a sobrecarga de interpretação.

## Soluções

Uma abordagem para diminuir o acoplamento é o [projeto funcional](https://en.wikipedia.org/wiki/Functional%5Fdesign "Functional design"), que busca limitar as responsabilidades dos módulos de acordo com a funcionalidade. O acoplamento aumenta entre duas classes `A` e `B` se:

* `A` tem um atributo que referencia (é do tipo) `B`.
* `A` utiliza serviços de um objeto `B`.
* `A` tem um método que referencia `B` (por meio do tipo de retorno ou de parâmetro).
* `A` é uma subclasse de (ou implementa) a classe `B`.

O baixo acoplamento refere-se a um relacionamento no qual um módulo interage com outro módulo por meio de uma interface simples e estável e não precisa se preocupar com a implementação interna do outro módulo (consulte [Ocultamento de informação](https://en.wikipedia.org/wiki/Information%5FHiding "Information Hiding")).

Sistemas como [CORBA](https://en.wikipedia.org/wiki/CORBA "CORBA") ou [COM](https://en.wikipedia.org/wiki/Component%5FObject%5FModel "Component Object Model") permitem que objetos se comuniquem entre si sem precisar saber nada sobre a implementação do outro objeto. Ambos os sistemas permitem inclusive que objetos se comuniquem com objetos escritos em outras linguagens.

## Acoplamento vs Conascência

O acoplamento descreve o grau e a natureza da dependência entre componentes de software, concentrando-se no que eles compartilham (por exemplo, dados, fluxo de controle, tecnologia) e em quão fortemente estão ligados. Ele avalia duas dimensões principais: a força, que mede quão difícil é alterar a dependência, e o escopo (ou visibilidade), que indica quão amplamente a dependência está exposta entre módulos ou fronteiras. Os tipos tradicionais de acoplamento normalmente incluem acoplamento de conteúdo, acoplamento comum, acoplamento de controle, acoplamento por estampa, acoplamento externo e acoplamento de dados.

A [conascência](https://en.wikipedia.org/wiki/Connascence "Connascence"), introduzida por Meilir Page-Jones, oferece um arcabouço sistemático para analisar e medir as dependências de acoplamento. Ela avalia as dependências com base em três dimensões: a força, que mede o esforço necessário para refatorar ou modificar a dependência; a localidade, que considera quão próximos, física ou logicamente, os componentes dependentes estão na [base de código](https://en.wikipedia.org/wiki/Codebase "Codebase"); e o grau, que mede quantos componentes são afetados pela dependência. A conascência pode ser categorizada em formas estática (detectável em tempo de compilação) e dinâmica (detectável em tempo de execução). A conascência estática refere-se a dependências de tempo de compilação, como assinaturas de métodos, enquanto a conascência dinâmica refere-se a dependências de tempo de execução, que podem se manifestar em formas como conascência de temporização, de valores ou de algoritmo.

Cada variação de acoplamento pode exibir vários tipos de conascência, um tipo específico ou, em casos raros, nenhum, dependendo de como a dependência é implementada. Os tipos comuns de conascência incluem conascência de nome, de tipo, de posição e de significado. Certos tipos de acoplamento alinham-se naturalmente a tipos específicos de conascência; por exemplo, o acoplamento de dados frequentemente envolve conascência de nome ou de tipo. No entanto, nem toda combinação de acoplamento e conascência é praticamente significativa. Dependências que se baseiam na ordem dos parâmetros em uma assinatura de método demonstram conascência de posição, que é frágil e difícil de refatorar porque reordenar os parâmetros quebra a interface. Em contraste, a conascência de nome, que se baseia em nomes de campos ou parâmetros, costuma ser mais resistente a mudanças. Os próprios tipos de conascência exibem uma hierarquia natural de força, sendo a conascência de nome normalmente considerada mais fraca do que a conascência de significado.

Dependências que cruzam fronteiras de módulos ou sistemas distribuídos normalmente têm custos de coordenação mais altos, aumentando a dificuldade de refatorar e propagar alterações por fronteiras distantes. Práticas modernas, como a [injeção de dependência](https://en.wikipedia.org/wiki/Dependency%5Finjection "Dependency injection") e a programação baseada em interfaces, são frequentemente empregadas para reduzir a força do acoplamento e melhorar a manutenibilidade das dependências.

Enquanto o acoplamento identifica o que é compartilhado entre componentes, a conascência avalia como essas dependências se comportam, como as alterações se propagam e quão difíceis são de refatorar. Força, localidade e grau estão inter-relacionados; dependências com alta força, amplo escopo e que cruzam fronteiras distantes são significativamente mais difíceis de refatorar e manter. Em conjunto, o acoplamento fornece uma visão geral de alto nível dos relacionamentos de dependência, enquanto a conascência oferece um arcabouço granular para analisar a força, a localidade, o grau e a resiliência à mudança das dependências, apoiando o projeto de sistemas robustos e fáceis de manter.

## Acoplamento de módulos

O acoplamento na Engenharia de Software descreve uma versão de métricas associadas a esse conceito.

Para acoplamento de fluxo de dados e de controle:

* d i {\\displaystyle d\_{i}} : número de parâmetros de dados de entrada
* c i {\\displaystyle c\_{i}} : número de parâmetros de controle de entrada
* d o {\\displaystyle d\_{o}} : número de parâmetros de dados de saída
* c o {\\displaystyle c\_{o}} : número de parâmetros de controle de saída

Para acoplamento global:

* g d {\\displaystyle g\_{d}} : número de variáveis globais usadas como dados
* g c {\\displaystyle g\_{c}} : número de variáveis globais usadas como controle

Para acoplamento ambiental:

* w {\\displaystyle w} : número de módulos chamados (fan-out)
* r {\\displaystyle r} : número de módulos que chamam o módulo em consideração (fan-in)

C o u p l i n g ( C ) \= 1 − 1 d i + 2 × c i + d o + 2 × c o + g d + 2 × g c + w + r {\\displaystyle \\mathrm {Coupling} (C)=1-{\\frac {1}{d\_{i}+2\\times c\_{i}+d\_{o}+2\\times c\_{o}+g\_{d}+2\\times g\_{c}+w+r}}}

`Coupling(C)` torna o valor maior quanto mais acoplado o módulo está. Esse número varia de aproximadamente 0,67 (baixo acoplamento) a 1,0 (altamente acoplado)

Por exemplo, se um módulo tem apenas um único parâmetro de dados de entrada e de saída

C \= 1 − 1 1 + 0 + 1 + 0 + 0 + 0 + 1 + 0 \= 1 − 1 3 \= 0.67 {\\displaystyle C=1-{\\frac {1}{1+0+1+0+0+0+1+0}}=1-{\\frac {1}{3}}=0.67}

Se um módulo tem 5 parâmetros de dados de entrada e de saída, um número igual de parâmetros de controle e acessa 10 itens de dados globais, com um fan-in de 3 e um fan-out de 4,

C \= 1 − 1 5 + 2 × 5 + 5 + 2 × 5 + 10 + 0 + 3 + 4 \= 0.98 {\\displaystyle C=1-{\\frac {1}{5+2\\times 5+5+2\\times 5+10+0+3+4}}=0.98}
