Loose Coupling in real practice —Rules and Concepts

Following the series of knowledge summarization posts, I’m writing down another one to summarize some parts of the knowledge I have gotten over the last 2 years.

This topic is one of the toughest one I have ever written and the version you’re reading now is the 3rd edition of it since I deleted 2 posts I have written before. In this version, I won’t explain much again what is Loose Coupling, the things I will write down is about How to apply Loose Coupling in real practice with rules and concepts. Hopefully you will get some helpful information for practicing/improving your programming skill.

The ultimate goal and biggest benefit of Loose Coupling is to help to minimize the changes when it happens. There’re 2 concepts that I personally think it’s basically enough when we talk about Loose Coupling in real practices:

  1. Program to interfaces.
  2. “Knowing enough.”.

Program to interfaces — Class-Class relationship.

This first concept is the most basic one you would find in most of the articles about Programming and Dependency Injection. Program or depend on interfaces simply enable you to take the biggest advantage of Objection Oriented: Polymorphism.

I will take some examples to describe with you why “Program to interfaces” will enable you to have Loose Coupling in your code. Let’s think in the case that some parts of your code with DI doesn’t depend on interface but depends on an concrete.

class YourClass {
public function __construct(TheirClass $their) {
//… code goes here
$theirClass = new TheirClass();
$yourClassWithTheirClass = new YourClass($theirClass);
//This part is simply never happen without depending on interface
//Assume that TheirAnotherClass and TheirClass are the same interface
$theirAnotherClass = new TheirAnotherClass();
$yourClassWithTheirAnotherClass = new YourClass($theirAnotherClass);
  • There will be no Polymorphism or Composition, you won’t be able to replace the $theirClass with their family of classes to change your behavior when you need it.
  • If they added a new public method to TheirClass but it’s not in a part of the interface, YourClass still be able to catch it and sometimes it makes the code out of control (if you’re having a big team). Your implementation will be broken for some unnecessary reason rather than a change in Public Interface because someone in your team just use it.

Best code can be written as:

class YourClass {
public function __construct(TheirClassInterface $their) {
//… code goes here

This is the simplest form of Loose Coupling at the lowest level but it’s mandatory to enable you to go to other advance forms of Loose Coupling.

“Knowing enough” — Component-Component relationship.

We have gone through the simplest form of Loose Coupling but Loose Coupling isn’t only about Classes, it’s about all kinds of Components that you can find in programming world:

  • Module — Module
  • Package — Package
  • Sub-system — Sub-system
  • System — System

At this level of programming, classes won’t be enough as we’re talking about a group of classes. The concept will be more complicated, classes will be separated into smaller groups depends on their Responsibility and Hierarchy:

  • Public Interface classes/Non-Public Interface classes.
  • Direct Children/Non-Direct Children.

“Knowing enough” can be describe as a rule like this:

Component will only know/depend on the Public Interfaces of their Direct Children.

By applying this rule, you’re minimizing the changes which might happen in your component when the other components were changed. You don’t need to know more than something which are necessary to know. The reason for the rule can be explained in some cases like these:

  • Public Interface classes are classes which are designed to be used by other components, so these interfaces will rarely be changed and your code will less likely be affected by them. Depending on some parts which are not a Public Interface will cause more problem when the owner of that component decide to refactor their implementation (rename classes, rename method, change structure but interface will be untouched).
  • Direct children are something similar with the implementation of a component. The component can be implemented on this way or that way or depends on some other packages they want and once again, relying deeply on an implementation won’t give you any advantage rather than more reasons to change your code.

There’re more problem for you to deal with when you’re trying to apply the principle to real practice, life isn’t simply as it was written. But once again I hope that some rules/tips I figured out myself will be a good start or awareness for developers who want to improve their skills.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.