Search code examples
javadependenciescoupling

Why you don't need to change the Java class in loosely coupling?


I'm a Java developer and I try to understand the coupling in Java, tightly coupling vs loosely coupling. There are a lot of information and the definition is simple: Coupling – the degree of dependency between the components. If more dependency is there it’s considered tightly coupling, if less dependency is there it’s considered loosely coupling.

But when I look at the example I don't understand it. For ex this website https://www.geeksforgeeks.org/coupling-in-java/

tight coupling example

class Volume  
{ 
     public static void main(String args[])  
     { 
         Box b = new Box(5,5,5); 
         System.out.println(b.volume); 
     } 
} 
class Box  
{ 
     public int volume; 
     Box(int length, int width, int height)  
     { 
         this.volume = length * width * height; 
     } 
} 

"Explanation:In the above example, there is a strong inter-dependency between both the classes. If there is any change in Box class then they reflects in the result of Class Volume."

loose coupling example

class Volume  
{ 
     public static void main(String args[])  
     { 
         Box b = new Box(5,5,5); 
         System.out.println(b.getVolume()); 
     } 
} 
final class Box  
{ 
     private int volume; 
     Box(int length, int width, int height)  
     { 
         this.volume = length * width * height; 
     } 
     public int getVolume()  
     {  
         return volume;  
           
     } 
} 

"Explanation : In the loosely coupling program, there is no dependency between both the classes. If we change anything in the Box classes then we don't have to change anything in Volume class."

But this is not true, if we change the class Box for ex we add another parameter in the constructor like here:

 Box(int length, int width, int height, int b)  
 { 
     this.volume = length * width * height + b; 
 } 

Then we need to change the class Volume otherwise there will be compilation errors:

     Box b = new Box(5,5,5,3); 

So, these changes should be done for both examples tightly coupling and also loosely coupling. What are they referring when they are saying you don't need to change something in the Volume class? Any feedback will be appreciated!


Solution

  • The problem with examples of tight (strong) versus weak (loose) coupling is that they tend to conflate the concepts of coupling and data abstraction. These are related concepts ... but they are not the same thing.

    In the example you found1, the most important problem with the "tight coupling" case is that the Box.volume field is declared as public. This allows other code to directly use that field, and it means that the other code can depend on the name and type (and implied semantics) of the field.

    By contrast, the "loose coupling" case declares that field as private, which removes the possibility of other code depending on the actual field. Of course, we have replaced it with a getter method (int getVolume()), and there will still be coupling between the two classes. But we have removed the possibility of coupling between the actual (now private) field and the classes that consume the volume. And for the sake of argument, we could change the Box class to store the box dimensions and compute the volume on the fly; e.g.

    class Box { 
         private int length, width, height; 
         Box (int length, int width, int height) { 
             // check the arguments are >= 0 and set the fields  
         }
         public int getVolume() {  
             return length * width * height;    
         } 
    }
    

    But how does this relate to data abstraction? Well in the version above with private fields, some other class can't assign values to the fields directly. But if they were public, other classes could change the box dimensions ... and even assign nonsense values to them, resulting in (say) the getVolume returning a negative volume.


    Note that in an example like this it is not possible remove all coupling. And whenever you have any coupling at all, that means that some changes to a class will inevitably require changes to others.

    Your counter-example seems to be arguing that since adding a 4th parameter (dimension?) to Box will entail changing Volume. That is true. But it does not mean that the "loose coupling" example is invalid. The proposition was that the "loose" version was less coupled than the "tight" version. It was NOT that there was no coupling at all.

    And indeed, if you add the 4th parameter to Box in your "tight" version in the obvious way, the same changes will need to be made to Volume. For >that< change, our reduction in coupling by hiding of the volume field is neutral. But it is not neutral for the change embodied in my version above!


    To sum it up, coupling is a matter of degree. Coupling between modules (classes, whatever) cannot be removed entirely ... if they need to work together. What you really need to focus on is coupling that makes it harder to understand and maintain a code base; e.g. coupling that is unnecessary, unexpected or hidden from the programmer in some way.


    1 - I commented that the example you found is a poor one. In fact, the real problem is in the explanation that you quoted. That explanation is simply incorrect. I don't recommend Geeks-for-Geeks as a source of information.