JavaScript: A Short Story of Decoupling
I was working on a piece of code and submitted a Pull Request for it. During the review, a colleague left this comment:
Why not decouple this file?
It was a great idea. I’m always in favor of decoupling because it makes things easier to scale and aligns with the Single Responsibility Principle.
The requirement was:
If condition
A
istrue
, then save thispayload
into a file.
Note: For now, the filename
doesn’t matter.
Easy, right?
First Version
Well, my first iteration looked like this:
File: controller
import savePayload from "./utils";
if (CONDITION_A) {
savePayload(payload);
}
File: utils
const DIRECTORY = "some_directory";
export const savePayload = (payload) => {
const filename = "unique_name";
const filePath = `${DIRECTORY}/${filename}`;
...
}
The approach works; it’s clean, readable, and testable. But what if someone else wants to save to a different directory?
The approach won’t work 😔
This is where decoupling comes in handy. If the DIRECTORY
is decoupled from utils
, our code becomes scalable. The best part is that the change is quite simple.
Second Version
File: controller
import savePayload from "./utils";
const DIRECTORY = "some_directory"; // <-- small big change
if (CONDITION_A) {
savePayload(DIRECTORY, payload);
}
File: utils
export const savePayload = (directory, payload) => {
const filename = "unique_name";
const filePath = `${directory}/${filename}`;
...
}
Sweet! Now whoever calls savePayload
needs to pass the directory 🙃.
At least now, this method works for any desired directory. Essentially, the coupling has been moved to the consumer. 😄
Third Version
The last change introduced was moving the directory to a constants file.
File: constants
export const DIRECTORY = "some_directory";
File: controller
import savePayload from "./utils";
import { DIRECTORY } from "./constants";
if (CONDITION_A) {
savePayload(DIRECTORY, payload);
}
File: utils
export const savePayload = (directory, payload) => {
const filename = "unique_name";
const filePath = `${directory}/${filename}`;
...
}
Conclusion
As with any approach, there are always pros and cons. In our case, we knew savePayload
would be needed for other cases, so it made sense to proceed with decoupling.
Decoupling is definitely beneficial, but be cautious with early optimizations. Most of the time, it’s better to cross that bridge when you get there :)