Loose coupling is essentially the indirect dependency between module on how they can evolve.
Generally, when there is a tightly coupled systems different modules/objects have a very specific behaviors that assumes that behavior of the peripheral objects. Such objects are linked/coupled to other modules behaviors and they cannot be re-used in isolation or in any other context.
Such modules even though responsible for individual functionality cannot evolve independently or cannot evolve
An example:
Let's say you have 3 objects
Shape (a model object) and Canvas (a UI element).
Now
Assume that a method shape.draw(Canvas) will draw an object on the plane that is supplied by the plane of the canvas.
Now, sometimes windows are partially covered and are resized. In such cases,
the above method might just do something like this.
shape::draw(Canvas) {
Rect.WindowLeft = Canvas.GetWindowRect.getLeftOffset();
Rect.LeftPixel = Canvas.GetWindowRect.pixels() + Rect.WindowLeft;
.... // like this get all co-ordinates.
draw_instance(Rect); // This will draw the actual shape.
}
Basically, here the draw function picks up the rectangle where things needs to be drawn. This is easy to understand (people might call this simple) code. However, this is extremely coupled code.
Imagine the situation:
- What if the canvas's mechanism of holding windows is no longer a rectangle?
- what if there are additional offsets that Canvas keeps which is private?
- What if some other application wants the same shape but no longer has a GUI window (for example, it is creating images and saving in files).
The root cause of the problem is that object shape knows and hence tightly coupled with Canvas.
What is desirable that a pixel set is given to shape where it writes; the shape should not have (even implicit) knowledge about where the pixels are actually written.