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 is true, then save this payload 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 :)