From Good to Great: Part 3
Applying SOLID Principles in Your Code

Life is becoming more interesting every day...
Currently, I am invested in being a better backend engineer, and also a medical doctor in training.
I have a keen interest in cloud engineering, biotechnology and molecular biology, and a fascination with VR.
In my free time, I enjoy reading, playing strategy games, experiencing music, and exploring philosophy.
Gratitude
We have learned a lot so far in the Modern Web Dev series, from understanding why we needed more web complexity to use learning about a bundler(Webpack) to learning design patterns modern internet companies used in writing their code.
I just want to tell you, that you are a STAR. Thanks for reading through, I appreciate it.
Pre-requisites
JavaScript Classes
JavaScript Objects
Introduction
Loosely Coupled Objects design is a design pattern idea closely related to the SOLID principles.
Loosely Coupled Objects are the opposite of tightly coupled objects, and to understand the importance of loosely coupled objects, we would take a brief description of both, a comparison, and the reasons why loosely coupled objects are better.
SOLID vs Loosely-Coupled Objects
Loosely coupled objects are a method that inspires both the Single Responsibility and Dependency-Inversion of SOLID.
It ensures that a piece of code does not depend too much on outside pieces of code and advocates for making code as modular as possible.
However, The main difference between loosely-coupled objects and the SOLID principles is that loosely-coupled objects are a general concept that can apply to any programming paradigm or design pattern, whereas the SOLID principles are specific guidelines for object-oriented programming.
In the context of the SOLID principles, loose coupling is typically achieved by adhering to the Dependency Inversion Principle (DIP), which states that modules should not depend directly on other modules, but instead should depend on abstractions.
This means that code should be designed in such a way that the implementation details of one module can be easily changed without affecting other modules that depend on it.
Coupling
Coupling refers to how closely two or more components(Classes, functions, etc.) are closely connected or dependent on each other.
When two components are tightly coupled with each other, it means they are highly dependent on each other and any change made on one will warrant an equal change in one or will lead to breaking.
On the other hand, when components are loosely coupled, they can still depend on each other vaguely. A change in one component might not lead to an entire failure.
If we were developing an app that takes in input and thanks customers after receiving input, tightly coupling this app could likely mean that for the app to take input from the customer, it has to thank the customer.
But what if the thank function was not working? It means our receiving input app will not work. Although there is not one way of loosely coupling objects, the key is to ensure that there is not a single point of failure, meaning that the failure of one component should not entirely lead to the failure of another.
There can be coupling between components, and our goal is to reduce the failures arising from their interaction. Let's look at some code examples of tight and loose coupling.
Tight Coupling
function addNumbers(num1, num2) {
return num1 + num2;
}
function calculateTotal() {
let num1 = 5;
let num2 = 10;
let total = addNumbers(num1, num2);
console.log(total);
}
- The
calculateTotalfunction depends on theaddNumbersfunction. If we were to change the parameters ofaddNumbersor the way it calculates the result, it could break thecalculateTotalfunction.
Loose Coupling
function addNumbers(num1, num2) {
return num1 + num2;
}
function calculateTotal(num1, num2) {
let total = addNumbers(num1, num2);
console.log(total);
}
- Although the
calculateTotalfunction usesaddNumbersin its code block, it is less likely to fail because it takes its own parameters, and you can add a change to theaddNumbersfunction, and worry less about it breaking.
Error Demo
If you are like me, you are wondering what kind of errors could occur from an example as simple as this. Here's one using the same examples in the previous two sections:
Tight coupling error: Using the same code snippet for tight coupling
function addNumbers(num1, num2, num3) { //Change
return num1 + num2 + num3; // Change
}
function calculateTotal() {
let num1 = 5;
let num2 = 10;
let total = addNumbers(num1, num2);
console.log(total);
}
calculateTotal();
If you run the
calculateTotalthe function above, it doesn't work.What is returned is
NaN, this happens because since thecalculateTotalfunction is entirely dependent on theaddNumbersfunction even for parameters, it has to have three numbers called inside it.
Solution: To solve this, we need to add a third num3 variable to the code snippet.
function addNumbers(num1, num2, num3) {
return num1 + num2 + num3;
}
function calculateTotal() {
let num1 = 5;
let num2 = 10;
let num3 = 12; // Solution
let total = addNumbers(num1, num2, num3); // Solution
console.log(total);
}
calculateTotal();
Loose coupling error: Now let's use the code snippet in the loose coupling section,
function addNumbers(num1, num2, num3) {
return num1 + num2 + num3;
}
function calculateTotal(num1, num2) {
let total = addNumbers(num1, num2);
console.log(total);
}
calculateTotal(3, 4);
Now run
calculateTotaland you see, IT WORKS!!!calculateTotalis only trying to access two parameters withaddNumbersand it can do because of how it's designed.
There's no underlying algorithm that makes this happen, it's just design patterns. Now, this is amazing.
Conclusion
Loosely coupled objects are an important design pattern that advocates for code modularity, and it is a general concept that applies to any programming paradigm or design pattern.
In comparison, tightly coupled objects are highly dependent on each other, and any change in one component will lead to the breaking of another.
Our goal as developers is to reduce the failures arising from the interaction between components, and one way to achieve this is through loose coupling.
By implementing loose coupling, we can reduce the probability of a single point of failure in our code, which will make our applications more robust and resilient to changes.




