[oop] What is the difference between loose coupling and tight coupling in the object oriented paradigm?

Can any one describe the exact difference between loose coupling and tight coupling in Object oriented paradigm?

This question is related to oop object coupling

The answer is


Tight Coupling means one class is dependent on another class.
Loose Coupling means one class is dependent on interface rather than class.

In tight coupling, there are hard-coded dependency declared in methods.
In loose coupling, we must pass dependency externally at runtime instead of hard-coded. (Loose couple systems use interface for decreased dependency with class.)

For example, we have a system that can send output in two or more ways like JSON output, CSV output, etc.

Tight 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() {
        // 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();
    }
}

In the example above, if we want to change the output in JSON, then we need to find and change in the whole code, because Class1 is tightly coupled with the CSVOutputGenerator class.

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();
    }
}

Tight coupling means classes and objects are dependent on one another. In general, tight coupling is usually not good because it reduces the flexibility and re-usability of the code while Loose coupling means reducing the dependencies of a class that uses the different class directly.

Tight Coupling The tightly coupled object is an object that needs to know about other objects and is usually highly dependent on each other's interfaces. Changing one object in a tightly coupled application often requires changes to a number of other objects. In the small applications, we can easily identify the changes and there is less chance to miss anything. But in large applications, these inter-dependencies are not always known by every programmer and there is a chance of overlooking changes. Example:

    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());
   }
}

In the above example, the code that is defined by this kind of implementation uses loose coupling and is recommended since class B has to go through class A to get its state where rules are enforced. If class A is changed internally, class B will not break as it uses only class A as a way of communication.

Output
getA() method
aObject value is: 0

The way I understand it is, that tightly coupled architecture does not provide a lot of flexibility for change when compared to loosely coupled architecture.

But in case of loosely coupled architectures, message formats or operating platforms or revamping the business logic does not impact the other end. If the system is taken down for a revamp, of course the other end will not be able to access the service for a while but other than that, the unchanged end can resume message exchange as it was before the revamp.


When two objects are loosely coupled, they can interact but have very little knowledge of each other.

Loosely coupled designs allow us to build flexible OO systems that can handle change.

Observer design pattern is a good example for making classes loosely coupled, you can have a look on it in Wikipedia.


There is a lot of nice answers here using analogies but a friend at work gave me an example that I liked more than all of the ones mentioned here... Eyes and Glasses!

Tight Coupling

Tight coupling would be the eyes. If I want to fix my vision, I'ts very expensive to get an eye transplant and holds a fair amount of risk. But what if the designer (being the human race) found a better way. Add a feature that is loosely coupled to the body so it can be easily changed! (yes.. glasses)

Loose coupling

I can easily replace my glasses without breaking my underlying vision. I can take off the glasses and my vision will be how it was before (not better or worse). Using different pairs of glasses changes how we see the world through our eyes with little risk and easy maintainability.

Summary

So next time someone asks you "who cares if my code is tightly-coupled?" The answer is all about effort to change, effort to maintain and risk of change.

So how is this done in C#? Interfaces and Dependency Injection!

EDIT

This a good example of the Decorator pattern as well, where the the eyes are the class we are decorating by meeting interface requirements but giving different functionality (e.g. sunglasses, reading glasses, magnifying glasses for jewelers e.t.c)


There are certain tools that provide dependency injection through their library, for example in .net we have ninject Library .

If you are going further in java then spring provides this capabilities.

Loosly coupled objects can be made by introducing Interfaces in your code, thats what these sources do.

Say in your code you are writing

Myclass m = new Myclass();

now this statement in your method says that you are dependent on myclass this is called a tightly coupled. Now you provide some constructor injection , or property injection and instantiating object then it will become loosly coupled.


Loose coupling means that the degree of dependency between two components is very low.
Example: GSM SIM

Tight coupling means that the degree of dependency between two components is very high.
Example: CDMA Mobile


Loose Coupling is the process of giving the dependency your class needs indirectly without providing all the information of the dependency(i.e in the from of interface) in case tight coupling you directly give in the dependency which is not good way of coding.


Loose coupling is and answer to to old style hardcoded dependencies and related issues issues like frequent recompilation when anything changes and code reuse. It stresses on implementing the worker logic in components and avoiding solution specific wire up code there.

Loose Coupling = IoC See this for easier explanation.


It's about classes dependency rate to another ones which is so low in loosely coupled and so high in tightly coupled. To be clear in the service orientation architecture, services are loosely coupled to each other against monolithic which classes dependency to each other is on purpose


Explanation without any code

Summary Example:

The Hat is "loosely coupled" to the body. This means you can easily take the hat off without making any changes to the person/body. When you can do that then you have "loose coupling". See below for elaboration.

The Hat is "loosely coupled" to the body. This means you can easily take then hat off without making any changes to the the person/body. Picture Attribution: https://pixabay.com/en/greeting-cylinder-chapeau-dignity-317250/

Tight coupling (Detailed Example)

Skin - tight coupling

Think of your skin. It's stuck to your body. It fits like a glove. But what if you wanted to change your skin colour from say white to black? Can you imagine just how painful it would be to peel off your skin, dye it, and then to paste it back on etc? Changing your skin is difficult because it is tightly coupled to your body. You just can't make changes easily. You would have to fundamentally redesign a human being in order to make this possible.

  • Key Point #1: In other words, if you want to change the skin, you would also HAVE TO change the design of your body as well because the two are joined together - they are tightly coupled.

God was not a good object oriented programmer.

Loose coupling (Detailed Example)

Now think of getting dressed in the morning. You don't like blue? No problems: you can put a red shirt on instead. You can do this easily and effortlessly because the shirt is not really connected to your body the same way as your skin. The shirt doesn't know or care about what body it is going on. In other words, you can change your clothes, without really changing your body.

  • That's key point #2. If you change your shirt, then you are not forced to change your body - when you can do that, then you have loose coupling. When you can't do that, then you have tight coupling.

That's the basic concept in a nutshell.

Why is all of this important?

It's important because software changes all the time. Generally speaking you want to be able to easily modify your code, without changing your code. I know that sounds like an oxymoron, but please bear with me.

Practical Examples of Coupling when Designing Software

  • CSV/JSON/DB Examples: If somebody wants their output in a CSV file rather than JSON etc., or if you want to switch from MySQL to PostGreSQL you should be able to make those changes extremely easily in your code, without having to rewrite the entire class etc. In other words, you do not want to tightly couple your application with a specific database implementation (e.g. Mysql) or to a particular output (e.g. CSV files). Because, as is inevitable in software, changes will come. When they do come, it's much easier if your parts of your code are loosely coupled. Or if you're using AWS and they start charging too much because of market dominance, you should be able to somewhat easily switch to Google or Azure etc.

Practical Example in Manufacturing - Car Parts:

Another example to reinforce coupling:

If somebody wants their car in black, you shouldn't have to redesign the entire car in order to do that. A car and its spare parts would be a perfect example of a loosely coupled architecture. If you want to replace your engine with a better one, you should be able to simply remove your engine without too much effort and swap it for a better one. If your car only works with Rolls Royce 1234 Engines and no other engines - then your car will is tightly coupled to that engine (Rolls Royce 1234).

Some amount of coupling is going to happen, but you should work to minimise it as much as you can. Why? Because when requirements change we should still be able to deliver good quality software, very quickly and we are aided in that goal by loose coupling.

Summary

In short, loose coupling makes code easier to change. The answers above provide some code which is worth reading at this point.

Picture Attribution.


In general Tight Coupling is bad in but most of the time, because it reduces flexibility and re-usability of code, it makes changes much more difficult, it impedes testability etc.

Tightly Coupled Object is an object need to know quite a bit about each other and are usually highly dependent on each other interfaces. Changing one object in a tightly coupled application often requires changes to a number of other objects, In small application we can easily identify the changes and there is less chance to miss anything. But in large applications these inter-dependencies are not always known by every programmer or chance is there to miss changes. But each set of loosely coupled objects are not dependent on others.

In short we can say, loose coupling is a design goal that seeks to reduce the interdependencies 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 a system, make it more maintainable, and make the entire framework more 'stable'.

Coupling refers to the degree of direct knowledge that one element has of another. we can say an eg: A and B, only B change its behavior only when A change its behavior. A loosely coupled system can be easily broken down into definable elements.


An extract from my blog post on coupling:

What is Tight Coupling:-

As par above definition a Tightly Coupled Object is an object that needs to know about other objects and are usually highly dependent on each other's interfaces.

When we change one object in a tightly coupled application often it requires changes to a number of other objects. There is no problem in a small application we can easily identify the change. But in the case of a large applications these inter-dependencies are not always known by every consumer or other developers or there is many chance of future changes.

Let’s take a shopping cart demo code to understand the tight coupling:

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);
        }
    }
}

Problems with the above example

Tight Coupling creates some difficulties.

Here, OrderTotal() methods is give us complete amount for the current items of the carts. If we want to add the discount features in this cart system. It is very hard to do in above code because we have to make changes at every class as it is very tightly coupled.


If an object's creation/existence dependents on another object which can't be tailored, its tight coupling. And, if the dependency can be tailored, its loose coupling. Consider an example in Java:

class Car {

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

    public Car() { 
        // implemenation 
    }

}

The client of Car class can create one with ONLY "X_COMPANY" engine.

Consider breaking this coupling with ability to change that:

class Car {

    private Engine engine;
    // Other members

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

}

Now, a Car is not dependent on an engine of "X_COMPANY" as it can be created with types.

A Java specific note: using Java interfaces just for de-coupling sake is not a proper desing approach. In Java, an interface has a purpose - to act as a contract which intrisically provides de-coupling behavior/advantage.

Bill Rosmus's comment in accepted answer has a good explanation.


In object oriented design, the amount of coupling refers to how much the design of one class depends on the design of another class. In other words, how often do changes in class A force related changes in class B? Tight coupling means the two classes often change together, loose coupling means they are mostly independent. In general, loose coupling is recommended because it's easier to test and maintain.

You may find this paper by Martin Fowler (PDF) helpful.