Qual é a diferença entre acoplamento solto e acoplamento apertado no paradigma orientado a objetos?

Respostas:

338

Acoplamento apertado é quando um grupo de classes é altamente dependente um do outro.

Esse cenário surge quando uma classe assume muitas responsabilidades ou quando uma preocupação é espalhada por muitas classes em vez de ter sua própria classe.

O acoplamento frouxo é alcançado por meio de um design que promove responsabilidade única e separação de preocupações.

Uma classe fracamente acoplada pode ser consumida e testada independentemente de outras classes (concretas).

As interfaces são uma ferramenta poderosa a ser usada para dissociar. As classes podem se comunicar por meio de interfaces, em vez de outras classes concretas, e qualquer classe pode estar do outro lado dessa comunicação simplesmente implementando a interface.

Exemplo de acoplamento apertado:

class CustomerRepository
{
    private readonly Database database;

    public CustomerRepository(Database database)
    {
        this.database = database;
    }

    public void Add(string CustomerName)
    {
        database.AddRow("Customer", CustomerName);
    }
}

class Database
{
    public void AddRow(string Table, string Value)
    {
    }
}

Exemplo de acoplamento solto:

class CustomerRepository
{
    private readonly IDatabase database;

    public CustomerRepository(IDatabase database)
    {
        this.database = database;
    }

    public void Add(string CustomerName)
    {
        database.AddRow("Customer", CustomerName);
    }
}

interface IDatabase
{
    void AddRow(string Table, string Value);
}

class Database implements IDatabase
{
    public void AddRow(string Table, string Value)
    {
    }
}

Outro exemplo aqui .

Jonathan
fonte
Até agora, o que você disse faz todo o sentido. Você pode explicar como o mecanismo de acoplamento pode se relacionar com o padrão Observer?
Jim
1
O padrão do observador é descrito aqui: en.wikipedia.org/wiki/Observer_pattern . Como a classe Subject pode manter uma lista de classes herdadas do 'Observer', sem realmente conhecer o tipo concreto dessas classes, essa é uma instância de acoplamento flexível. O Sujeito não depende de nenhum de seus Observadores ou de suas preocupações internas. Os observadores não dependem do Assunto ou de nenhuma de suas preocupações.
31410 Jonathan
4
As interfaces Java são ferramentas que podem ajudar nisso. No entanto, eles não são necessários. O conceito de programa para a interface e não a implementação significa programa para os métodos / atributos públicos (ou aqueles que devem ser usados ​​por chamadores externos quando os idiomas não suportam modificadores de acesso, como C). A interface deve honrar esse contrato implícito por não mudar. Em idiomas sem modificadores de acesso (como C), isso significa apenas o uso de interfaces / funções publicadas e não atingir as que se destinam a serem usadas internamente, uma vez que elas podem mudar conforme necessário para suportar as funções publicadas.
Bill Rosmus
3
@ Jonathanconway obrigado senhor, mas os dois códigos fazem a mesma coisa: qual é a diferença entre eles? ou seja, quais são as vantagens do acoplamento fraco?
BKSpurgeon
1
Eu já vi (basicamente) este exemplo antes. Na minha opinião, isso não importaria se houvesse muitos tipos de bancos de dados que seriam usados. Se você planeja ter apenas um, é tão ruim usar uma implementação diretamente; depois, se você precisar injetar tipos diferentes, refatorar o uso único do Banco de Dados para usar uma interface? Em vez de adicionar um monte de código da placa da caldeira que provavelmente não é necessário?
Carlos Bribiescas 8/08
178

Explicação sem QUALQUER código

Exemplo de resumo:

O chapéu é "fracamente acoplado" ao corpo. Isso significa que você pode tirar o chapéu facilmente sem fazer alterações na pessoa / corpo. Quando você pode fazer isso, então você tem "acoplamento solto". Veja abaixo a elaboração.

O chapéu é "fracamente acoplado" ao corpo.  Isso significa que você pode tirar facilmente o chapéu sem fazer alterações na pessoa / corpo.  Atribuição de imagem: https://pixabay.com/en/greeting-cylinder-chapeau-dignity-317250/

Acoplamento apertado (exemplo detalhado)

Pense na sua pele. Está preso ao seu corpo. Se encaixa como uma luva. Mas e se você quisesse mudar a cor da sua pele de branca para verde? Você pode imaginar o quão doloroso seria descascar sua pele, tingi-la e colá-la novamente etc? Mudar a pele é difícil porque está fortemente acoplado ao seu corpo. Você simplesmente não pode fazer alterações facilmente. Você teria que redesenhar fundamentalmente um ser humano para tornar isso possível.

  • Ponto-chave nº 1 : Em outras palavras, se você quiser mudar a pele, também precisará alterar o design do seu corpo , porque os dois estão unidos - eles estão firmemente acoplados.

Deus não era um bom programador orientado a objetos.

Acoplamento frouxo (exemplo detalhado)

Agora pense em se vestir de manhã. Você não gosta de azul? Sem problemas: você pode vestir uma camisa vermelha. Você pode fazer isso com facilidade e sem esforço, porque a camiseta não está realmente conectada ao seu corpo da mesma maneira que a sua pele. A camiseta não sabe nem se importa com o corpo . Em outras palavras, você pode trocar de roupa sem realmente mudar seu corpo.

  • Esse é o ponto principal # 2. Se você trocar de camisa, não será forçado a mudar de corpo - quando você puder fazer isso, terá um acoplamento solto. Quando você não pode fazer isso, tem um acoplamento apertado.

Esse é o conceito básico em poucas palavras.

Por que tudo isso é importante?

É importante porque o software muda o tempo todo. De um modo geral, você deseja modificar facilmente seu código, sem alterá-lo. Eu sei que isso soa como um oxímoro, mas por favor, tenha paciência comigo.

Exemplos práticos de acoplamento ao codificar

  • Exemplos de CSV / JSON / DB: se alguém deseja sua saída em um arquivo CSV, em vez de JSON etc., ou se você deseja mudar do MySQL para PostGreSQL, poderá fazer essas alterações com extrema facilidade no seu código, sem precisar reescrever a classe inteira etc. Em outras palavras, você não deseja associar firmemente seu aplicativo a uma implementação de banco de dados específica (por exemplo, Mysql) ou a uma saída específica (por exemplo, arquivos CSV). Porque, como é inevitável no software, as mudanças virão. Quando eles chegam, é muito mais fácil se as partes do seu código estão fracamente acopladas.

  • Exemplo de peças para carros: se alguém quiser o carro em preto , não será necessário reprojetar o carro inteiro para fazer isso. Um carro e suas peças de reposição seriam um exemplo perfeito de uma arquitetura fracamente acoplada. Se você deseja substituir o seu motor por um melhor, você pode simplesmente remover o seu motor sem muito esforço e trocá-lo por um melhor. Se o seu carro funcionar apenas com os motores Rolls Royce 1234 e sem outros motores - o seu carro estará fortemente acoplado a esse motor (Rolls Royce 1234). Seria melhor se você alterasse o design do seu carro para que ele funcionasse com qualquermotor, para que seja um pouco mais frouxamente acoplado aos seus componentes. Melhor ainda seria se o seu carro pudesse funcionar sem a necessidade de um motor! Alguma quantidade de acoplamento vai acontecer, mas você deve trabalhar para minimizá-lo o máximo possível. Por quê? Porque quando os requisitos mudam, ainda devemos poder fornecer software de boa qualidade, muito rapidamente e somos auxiliados nesse objetivo por acoplamentos soltos.

Resumo

Em resumo, o acoplamento flexível facilita a alteração do código. As respostas acima fornecem algum código que vale a pena ler neste momento.

Polimorfismo e princípios SOLID

Re: Comentários do @TimoHuovinen - o conceito de acoplamento solto anda de mãos dadas com os conceitos de polimorfismo. Se você entender a analogia básica das peças de uma camisa / carro, estará pronto para entender o polimorfismo. A melhor maneira, neste momento, é ler os exemplos de código fornecidos por meus colegas estimados nas outras respostas deste tópico. Se eu disser mais, você pode ficar sobrecarregado com muitas informações.

Atribuição de imagem .

BKSpurgeon
fonte
8
esta é uma explicação tão subestimada para novos programadores. Difícil de percorrer as grandes palavras alguns outros nosso colocando para fora, uma vez que você compreender os conceitos básicos, em seguida, é mais fácil ir para as grandes palavras lol
user2763557
6
Há algumas coisas que devem ser fortemente acopladas e outras pouco acopladas ao seu ambiente. O uso da pele não é uma analogia adequada para acoplamentos apertados. Se a pele é pensada como fortemente acoplada ao corpo, o mesmo ocorre com todas as outras partes. O corpo (como um todo) precisa ter partes (totalmente integradas) para funcionar corretamente (pode ser o que a natureza pensa) - um arquiteto brilhante). Se essas partes foram projetadas para serem substituíveis (tão simples quanto trocar um chapéu), o próprio significado do corpo 'humano' perde sua definição. Comente 1/2.
Lupchiazoem
6
Seguindo o exemplo, se a pele for substituída, a cabeça também deverá ser substituída novamente. Se isso acontecer, as pessoas podem não ser reconhecíveis de um encontro para outro. Uma boa analogia do acoplamento estanque / frouxo seria - um carro e suas partes, um computador e suas partes etc ... Se houver um problema com o mouse / teclado de um computador, ele poderá ser substituído por outra parte, em vez de tornar o computador inteiro inútil e jogue fora. Comentário 2/2.
Lupchiazoem
1
@BKSpurgeon Awesome explicação !! e sua maneira de dar um exemplo de explicação também é muito boa.
precisa
5
Explicado de forma muito criativa. Estou fortemente associado a esta resposta.
AliN11 27/05
72

No design orientado a objetos, a quantidade de acoplamento refere-se a quanto o design de uma classe depende do design de outra classe. Em outras palavras, com que frequência as alterações na classe A forçam alterações na classe B? Um acoplamento apertado significa que as duas classes geralmente mudam juntas; um acoplamento solto significa que na maior parte são independentes. Em geral, o acoplamento solto é recomendado porque é mais fácil testar e manter.

Você pode encontrar este documento de Martin Fowler (PDF) útil.

Don Kirkby
fonte
"com que frequência as alterações na classe A forçam alterações na classe B?" Eu preciso de um breve exemplo para a frase acima?
Kumaresan Perumal
15

Em geral, o Tight Coupling é ruim, mas na maioria das vezes, porque reduz a flexibilidade e a reutilização do código, torna as alterações muito mais difíceis, impede a testabilidade etc.

Objeto firmemente acoplado é um objeto que precisa conhecer um pouco um do outro e geralmente é altamente dependente uma da outra interface. Alterar um objeto em um aplicativo fortemente acoplado geralmente requer alterações em vários outros objetos. Em aplicativos pequenos, podemos identificar facilmente as alterações e há menos chances de perder qualquer coisa. Mas, em grandes aplicações, essas interdependências nem sempre são conhecidas por todos os programadores ou existem chances de perder alterações. Mas cada conjunto de objetos fracamente acoplados não depende de outros.

Em resumo, podemos dizer que o acoplamento frouxo é uma meta de projeto que busca reduzir as interdependências entre os componentes de um sistema com a meta de reduzir o risco de que alterações em um componente exijam alterações em qualquer outro componente. O acoplamento flexível é um conceito muito mais genérico, destinado a aumentar a flexibilidade de um sistema, torná-lo mais sustentável e tornar a estrutura inteira mais 'estável'.

Acoplamento refere-se ao grau de conhecimento direto que um elemento possui de outro. podemos dizer um exemplo: A e B, somente B muda seu comportamento somente quando A muda seu comportamento. Um sistema fracamente acoplado pode ser facilmente dividido em elementos definíveis.

Jom George
fonte
11

Quando dois objetos são fracamente acoplados, eles podem interagir, mas têm muito pouco conhecimento um do outro.

Projetos fracamente acoplados nos permitem construir sistemas OO flexíveis que podem lidar com mudanças.

O padrão de design do observador é um bom exemplo para criar classes pouco acopladas. Você pode dar uma olhada na Wikipedia .

Ahmed_Gad
fonte
6

Um extrato da minha postagem no blog sobre acoplamento:

O que é acoplamento estanque : -

Como definição acima, um Objeto firmemente acoplado é um objeto que precisa conhecer outros objetos e, geralmente, é altamente dependente das interfaces um do outro.

Quando alteramos um objeto em um aplicativo fortemente acoplado, geralmente é necessário alterar vários outros objetos. Não há problema em um aplicativo pequeno, podemos identificar facilmente a alteração. Porém, no caso de aplicativos grandes, essas interdependências nem sempre são conhecidas por todos os consumidores ou outros desenvolvedores ou há muitas chances de mudanças futuras.

Vamos dar um código de demonstração do carrinho de compras para entender o acoplamento rígido:

namespace DNSLooseCoupling
{
    public class ShoppingCart
    {
        public float Price;
        public int Quantity;

        public float GetRowItemTotal()
        {
            return Price * Quantity;
        }
    }

    public class ShoppingCartContents
    {
        public ShoppingCart[] items;

        public float GetCartItemsTotal()
        {
            float cartTotal = 0;
            foreach (ShoppingCart item in items)
            {
                cartTotal += item.GetRowItemTotal();
            }
            return cartTotal;
        }
    }

    public class Order
    {
        private ShoppingCartContents cart;
        private float salesTax;

        public Order(ShoppingCartContents cart, float salesTax)
        {
            this.cart = cart;
            this.salesTax = salesTax;
        }

        public float OrderTotal()
        {
            return cart.GetCartItemsTotal() * (2.0f + salesTax);
        }
    }
}

Problemas com o exemplo acima

O acoplamento apertado cria algumas dificuldades.

Aqui, OrderTotal()métodos é o valor total para os itens atuais dos carrinhos. Se quisermos adicionar os recursos de desconto neste sistema de carrinho. É muito difícil fazer isso no código acima, porque precisamos fazer alterações em todas as classes, pois ele é muito bem acoplado.

Anil Sharma
fonte
6

Um acoplamento fraco significa que o grau de dependência entre dois componentes é muito baixo.
Exemplo: GSM SIM

Um acoplamento rígido significa que o grau de dependência entre dois componentes é muito alto.
Exemplo: CDMA Mobile

govind satpute
fonte
5

Pelo que entendi, a arquitetura fortemente acoplada não oferece muita flexibilidade para mudanças quando comparada à arquitetura pouco acoplada.

Porém, no caso de arquiteturas fracamente acopladas, formatos de mensagem ou plataformas operacionais ou reformulação da lógica de negócios, isso não afeta a outra extremidade. Se o sistema for desativado para uma revisão, é claro que a outra extremidade não poderá acessar o serviço por um tempo, mas, além disso, a extremidade inalterada poderá retomar a troca de mensagens como era antes da revisão.

Amit Kumar
fonte
5

Acoplamento apertado significa que uma classe depende de outra classe.
Loose Coupling significa que uma classe depende da interface e não da classe.

No acoplamento rígido , há uma dependência codificada declarada nos métodos.
No acoplamento flexível , devemos passar a dependência externamente no tempo de execução, em vez de codificados. (Os sistemas de pares soltos usam a interface para diminuir a dependência da classe.)

Por exemplo, temos um sistema que pode enviar saída de duas ou mais maneiras, como saída JSON, saída CSV etc.

Apertado

public interface OutputGenerator {
    public void generateOutput();
}

public class CSVOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("CSV Output Generator");
    }
}

public class JSONOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("JSON Output Generator");
    }
}

// In Other Code, we write Output Generator like...
public class Class1 {
    public void generateOutput() {
        // Here Output will be in CSV-Format, because of hard-coded code.
        // This method tightly coupled with CSVOutputGenerator class, if we want another Output, we must change this method.
        // Any method, that calls Class1's generateOutput will return CSVOutput, because Class1 is tight couple with CSVOutputGenerator.
        OutputGenerator outputGenerator = new CSVOutputGenerator();
        output.generateOutput();
    }
}

No exemplo acima, se queremos alterar a saída em JSON, precisamos localizar e alterar todo o código, porque a Class1 está fortemente acoplada à classe CSVOutputGenerator.

Loose Coupled

public interface OutputGenerator {
    public void generateOutput();
}

public class CSVOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("CSV Output Generator");
    }
}

public class JSONOutputGenerator implements OutputGenerator {
    public void generateOutput() {
        System.out.println("JSON Output Generator");
    }
}

// In Other Code, we write Output Generator like...
public class Class1 {
    public void generateOutput(OutputGenerator outputGenerator) {
        // if you want to write JSON, pass object of JSONOutputGenerator (Dependency will be passed externally to this method)
        // if you want to write CSV, pass object of CSVOutputGenerator (Dependency will be passed externally to this method)

        // Due to loose couple with class, we don't need to change code of Class1, because Class1 is loose coupled with CSVOutputGenerator or JSONOutputGenerator class
        // Any method, that calls Class1's generateOutput will desired output, because Class1 does not tight couple with CSVOutputGenerator or JSONOutputGenerator class
        OutputGenerator outputGenerator = outputGenerator;
        output.generateOutput();
    }
}
Milan Vaghasiya
fonte
3

Existem certas ferramentas que fornecem injeção de dependência por meio de sua biblioteca, por exemplo, em .net, nós injetamos a biblioteca .

Se você estiver indo mais longe em java, o spring fornece esses recursos.

Objetos fracamente acoplados podem ser criados introduzindo interfaces no seu código, é o que essas fontes fazem.

Diga no seu código que você está escrevendo

Myclass m = new Myclass();

agora essa declaração no seu método diz que você é dependente myclassdisso e é chamada de fortemente acoplada. Agora, como você fornece alguma injeção de construtor ou objeto de instanciação e injeção de propriedade, ele se torna fracamente acoplado.

Vishal Sharma
fonte
3

Há muitas respostas legais aqui usando analogias, mas um amigo no trabalho me deu um exemplo que eu gostei mais do que todos os mencionados aqui ... Olhos e óculos!

Acoplamento apertado

Acoplamento apertado seriam os olhos. Se eu quiser corrigir minha visão, é muito caro fazer um transplante de olho e possui uma quantidade razoável de riscos. Mas e se o designer (sendo a raça humana) encontrasse um caminho melhor. Adicione um recurso que esteja fracamente acoplado ao corpo para que ele possa ser facilmente alterado! (sim .. óculos)

Acoplamento solto

Posso substituir facilmente meus óculos sem interromper minha visão subjacente. Posso tirar os óculos e minha visão será como era antes (nem melhor nem pior). O uso de diferentes pares de óculos muda a forma como vemos o mundo através de nossos olhos, com pouco risco e facilidade de manutenção.

Resumo

Então, da próxima vez que alguém lhe perguntar "quem se importa se meu código estiver fortemente associado?" A resposta é sobre esforço para mudar, esforço para manter e risco de mudança.

Então, como isso é feito em c #? Interfaces e injeção de dependência!

EDITAR

Este também é um bom exemplo do padrão Decorator, onde os olhos são da classe que estamos decorando, atendendo aos requisitos da interface, mas oferecendo funcionalidades diferentes (por exemplo, óculos de sol, óculos de leitura, lupas para joalheiro etc.)

JohnChris
fonte
2

O acoplamento flexível é uma resposta a dependências codificadas no estilo antigo e a problemas relacionados a questões como recompilação frequente quando algo muda e a reutilização de código. Ele enfatiza a implementação da lógica de trabalho em componentes e a evitação de códigos de conexão específicos da solução.

Acoplamento solto = IoC Veja isso para obter uma explicação mais fácil.

MSIL
fonte
3
Não acho que o acoplamento solto seja o mesmo que inversão de controle. A inversão do controle é uma técnica muito útil para reduzir o acoplamento do seu design, mas existem muitas outras técnicas.
Don Kirkby
2

Loose Coupling é o processo de fornecer a dependência que sua classe precisa indiretamente, sem fornecer todas as informações da dependência (por exemplo, na interface), no caso de um acoplamento rígido que você fornece diretamente na dependência, o que não é uma boa maneira de codificar.

David William
fonte
2

É sobre a taxa de dependência de classes para outras que são tão baixas em acoplamentos frouxos e tão altas em acoplamentos estreitos. Para ficar claro na arquitetura de orientação ao serviço , os serviços são fracamente acoplados uns aos outros contra monolítico que classes de dependência entre si têm um propósito

Mohammad Heydari
fonte
1

Se a criação / existência de um objeto depende de outro objeto que não pode ser adaptado, seu acoplamento rígido. E, se a dependência puder ser adaptada, seu acoplamento frouxo. Considere um exemplo em Java:

class Car {

    private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
    // Other parts

    public Car() { 
        // implemenation 
    }

}

O cliente da Carclasse pode criar um com o mecanismo ONLY "X_COMPANY".

Considere quebrar esse acoplamento com a capacidade de alterar isso:

class Car {

    private Engine engine;
    // Other members

    public Car( Engine engine ) { // this car can be created with any Engine type
        this.engine = engine;
    }

}

Agora, a Carnão depende de um mecanismo de "X_COMPANY", pois pode ser criado com tipos.

Uma observação específica de Java: o uso de interfaces Java apenas para desconectar o acoplamento não é uma abordagem apropriada. Em Java, uma interface tem um propósito - agir como um contrato que fornece intrisicamente comportamento / vantagem de desacoplamento.

O comentário de Bill Rosmus na resposta aceita tem uma boa explicação.

lupchiazoem
fonte
0

Um acoplamento rígido significa que classes e objetos são dependentes um do outro. Em geral, o acoplamento rígido geralmente não é bom porque reduz a flexibilidade e a reutilização do código, enquanto o acoplamento flexível significa reduzir as dependências de uma classe que usa diretamente a classe diferente.

Acoplamento apertado O objeto fortemente acoplado é um objeto que precisa conhecer outros objetos e geralmente é altamente dependente das interfaces um do outro. A alteração de um objeto em um aplicativo fortemente associado geralmente requer alterações em vários outros objetos. Nas pequenas aplicações, podemos identificar facilmente as alterações e há menos chances de perder alguma coisa. Porém, em aplicativos grandes, essas interdependências nem sempre são conhecidas por todos os programadores e há uma chance de ignorar as alterações. Exemplo:

    class A {
       public int a = 0;
       public int getA() {
          System.out.println("getA() method");
          return a;
       }
       public void setA(int aa) {
          if(!(aa > 10))
             a = aa;
       }
    }
    public class B {
       public static void main(String[] args) {
          A aObject = new A();
          aObject.a = 100; // Not suppose to happen as defined by class A, this causes tight coupling.
          System.out.println("aObject.a value is: " + aObject.a);
       }
    }

In the above example, the code that is defined by this kind of implementation uses tight coupling and is very bad since class B knows about the detail of class A, if class A changes the variable 'a' to private then class B breaks, also class A's implementation states that variable 'a' should not be more than 10 but as we can see there is no way to enforce such a rule as we can go directly to the variable and change its state to whatever value we decide.

    Output
    aObject.a value is: 100

Loose Coupling
Loose coupling is a design goal to reduce the inter-dependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
Loose coupling is a much more generic concept intended to increase the flexibility of the system, make it more maintainable and makes the entire framework more stable.
Example:

class A {
   private int a = 0;
   public int getA() {
      System.out.println("getA() method");
      return a;
   }
   public void setA(int aa) {
      if(!(aa > 10))
         a = aa;
   }
}
public class B {
   public static void main(String[] args) {
      A aObject = new A();
      aObject.setA(100); // No way to set 'a' to such value as this method call will
                         // fail due to its enforced rule.
      System.out.println("aObject value is: " + aObject.getA());
   }
}

No exemplo acima, o código definido por esse tipo de implementação usa acoplamento flexível e é recomendado, pois a classe B precisa passar pela classe A para obter seu estado em que as regras são aplicadas. Se a classe A for alterada internamente, a classe B não será interrompida, pois usa apenas a classe A como meio de comunicação.

Output
getA() method
aObject value is: 0
مهدی عابدی برنامه نویس و مشاور
fonte