DEV Community

Achla
Achla

Posted on

When I Thought Writing Everything in One File Was Smart (And Then It Hit Me...)

🚀 The Junior Dev Inside Me

When I started as a junior developer, I saw my senior teammate writing so many files... just to save a user to the database. 🤯

There was a UserDTO, a UserService, a UserRepository, some interfaces, and even a folder just for exceptions.

I stared at the structure and thought:

“Isn’t this overkill? I could do this in one file with 10 lines of code. Why make it so complicated?”

So I did just that.


💻 My One-File Hero Moment

// saveUser.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
app.use(express.json());

mongoose.connect("mongodb://localhost:27017/test");

app.post("/user", async (req, res) => {
  const { name, email } = req.body;
  const User = mongoose.model("User", new mongoose.Schema({ name: String, email: String }));
  await User.create({ name, email });
  res.send("User created");
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

It worked. ✅
I was proud. I deployed it. I slept well. 😌


🧨 Then Reality Hit

A few weeks later:

  • The client wanted to validate the email.
  • Then they wanted to add a phone number.
  • Then they wanted to store the user's role.

Every small update meant:

Digging through my one big file and changing everything 😫

  • I accidentally broke the DB connection once.
  • Forgot to validate input once.
  • It became a bug-prone mess.

That’s when I finally understood why seniors use so many files.
It wasn’t overkill — it was SOLID.


📐 What Are SOLID Principles?

SOLID is a set of 5 design principles that help write clean, maintainable, and scalable code:

Principle Meaning in Simple Words
S - Single Responsibility One class/file/function should do only one job
O - Open/Closed Code should be open for extension but closed for changes
L - Liskov Substitution Subclasses should behave like their base class
I - Interface Segregation Don’t force components to depend on things they don’t use
D - Dependency Inversion Depend on abstractions, not concrete implementations

🛠️ Before vs After (Real Code Example)

❌ Bad (All-in-one mess)

app.post("/user", async (req, res) => {
  const User = mongoose.model("User", new mongoose.Schema({ name: String }));
  await User.create({ name: req.body.name });
  res.send("User created");
});
Enter fullscreen mode Exit fullscreen mode
  • No validation
  • Direct DB code in route
  • Hard to test
  • Not reusable

✅ Good (SOLID way – broken into parts)

📁 routes/userRoute.js

router.post("/", userController.createUser);
Enter fullscreen mode Exit fullscreen mode

📁 controllers/userController.js

export const createUser = async (req, res) => {
  const dto = new CreateUserDTO(req.body);
  const user = await userService.create(dto);
  res.send(user);
};
Enter fullscreen mode Exit fullscreen mode

📁 services/userService.js

export const create = async (dto) => {
  validateUser(dto);
  return userRepository.save(dto);
};
Enter fullscreen mode Exit fullscreen mode

📁 repositories/userRepository.js

export const save = async ({ name }) => {
  const User = mongoose.model("User", new mongoose.Schema({ name }));
  return await User.create({ name });
};
Enter fullscreen mode Exit fullscreen mode

Now each file has one job, and I can:

  • ✅ Easily test each part
  • ✅ Reuse userService elsewhere
  • ✅ Change DB logic without touching the controller
  • ✅ Scale the app without fear

🍔 Real-Life Analogy

Imagine you run a burger shop:

  • One person takes orders
  • Another cooks
  • One packs
  • One delivers

Now imagine if one person does everything — they’ll mess something up.

💡 Like in code, separating responsibilities makes things faster, cleaner, and less buggy.


🧠 Final Lesson I Learned

Just because your code works doesn’t mean it’s good.But if it’s modular, testable, and SOLID, you’ll thank yourself later.

I once thought "one file is smart."
Now I know: "smart is writing maintainable code."


💬 What About You?

Have you ever written a one-file monster and paid for it later?

Let me know in the comments — let's normalize learning from messy code! 😄

Top comments (2)

Collapse
 
xwero profile image
david duymelinck • Edited

The file separation shown in the post is not all SOLID. Those principles are mainly for classes.
The only principle you used is single responsibility, because that is the one that is the most universal.

Separating the routes, and I assume the database connection string, is isolating the configuration from the application code.

Using a controller is part of the MVC pattern.

Services where a default for a long time but now the best practice is to create use cases. The difference is with a use case there is only a single action, while with a service there are multiple actions. To create a use case just rename the file to CreateUser.js and return the function as the default method.
The general idea is to keep the dependencies as focused as possible. With a service it is possible dependencies are added for other methods, that is just waste. Like taking a winter jacket to a tropical place.

For the example i wouldn't bother with a repository, because the use case is the gate to the database action.
Repositories are needed if there are different ways to prepare for a database action. For example a use case where users are filtered based on their role and a use case where users are filtered on their country. Both can go to a repository method that accepts field values to return a list of users.

While best practices like SOLID, design patterns and clean code are good advise, you need to figure out which practice helps your code. Don't blindly apply all the best practices every time.

Collapse
 
achlacodes profile image
Achla

Thank you so much for this detailed and thoughtful comment 😊

You’re absolutely right — the file separation I shared in the post is more about organizing responsibilities and keeping things modular, and not a full SOLID implementation. My main goal was to share my personal learning journey as a junior dev — going from “one file that works” to “structured, maintainable code.”

I really appreciate you highlighting the differences between services vs. use cases, and the clarity you brought to when and why repositories are truly helpful — especially the winter jacket analogy — loved that!

Thanks again for sharing your insights — it really adds value for me and anyone else reading this! 🙌

Some comments may only be visible to logged-in visitors. Sign in to view all comments.