DEV Community

Discussion on: What are the least intuitive fundamentals and best practices in software development?

Collapse
 
jamesmh profile image
James Hickey • Edited

High Cohesion And Low Coupling

Having an understanding of what building systems or code with high cohesion and low coupling really means.

Having code with high cohesion will inevitably "look" like you are repeating code that could be generalized.

Let's say we have two (or more) classes that have very similar code in them. Most people will invoke DRY and attempt to generalize anything that looks the same.

But, once you create an abstraction to generalize that code you've just created a new shared point of coupling. Over-time, this practice creates code with high-coupling and low cohesion since everything is tied to each other via transitive dependencies.

I've seen SO many projects suffer from an irreversible web of dependencies because everything was generalized. Then, new requirements come - and the easiest thing is to just add a new layer of abstraction on top of everything else! Because, after all, creating more abstractions is a "good" thing 😉

It needs to be considered that different classes, modules or systems do not have the same responsibilities - and therefore will evolve differently over time. Any shared dependencies (libraries, classes, functions, etc.) will make this harder. Especially in the case of sharing many - massive problems will arise.

The biggest selling point of micro-services (which everyone praises) is that it promotes systems with high cohesion and low coupling.

Almost 100% of the experts in that area will stand unmoved on the idea that services should never share any code (libraries, etc.) and never share data stores.

Basically, the exact opposite of what most of us end up building!

I've seen shared code become a detriment rather than a blessing more-than-not.

Dependency Direction / Flow

To add another... on a similar note, a not-so-obvious principle is that the order and direction of your dependencies matter.

For example, don't mix web related libraries into your core business rule modules (package, project, whatever your language calls it 😋)

If, let's say, you have your main business rules and logic in some core library. And, if that is referencing some web or MVC related library, depending on the language, you'll probably have issues when you want to then expose that core business library to a new API project you are building (def an issue if using .NET!).

There would be (complicated) ways around that. But if the dependency wasn't there in the first place then you could expose your main business rules to both an MVC project and an API project with much less of a headache 🤣.