Decoupled code is easy to change code. This is because the code that is linked needs to be changed in parallel.
Decoupled code is reusable code. When writing reusable code, you put it into a function/method call, you give it clean interfaces. Reusable code is usually a small unit of code that does not have dependencies.
Symptoms of coupling:
simple changes to one module that breaks functionality in other modules
developers are reluctant to do changes because they expect them to have side-effects
Forms of coupling in code
A. Train Wrecks
Train wrecks occur when implementation details are exposed in a series of function calls. Implementation details hardcoded in train wrecks that are likely to change, make them hard to change. This is not the case for 3rd party libraries that come with the language and are stable.
To fight train wrecks,
Apply Principle Tell, Don't Ask
can be applied. The principle states that the code should not make decisions based on the internal state of an object and then modify that object. In doing so, implementation detail is spread across the code. The implementation detail can be encapsulated within the object and put behind an abstraction layer that is exposed. This abstraction layer does not change, but the implementation detail within the layer can easily change as long as you have the same inputs and same outputs.
B. Globalization
Each global state "acts as if every method in your application suddenly gained an additional parameter".
Why globalization introduces coupling:
change to the global code affects each function that makes use of the global state
reusable code cannot be split (eg., in tests that need as set up a global variable)
If there is indeed a need for a global variable, then it needs to be wrapped in another layer. For example, using methods/functions introduces an abstraction layer that hides changes to the data structure.
In general, to have easy-to-change code, keep it shy!
Challenges:
- do a coupling map of the codebase (divided into components), perhaps then it is easier to think what needs to be changed; perhaps the nx dependency map is of help in this case.