Scalable Architecture: Routes & Controllers
When building a simple Express.js server, it's tempting to put all your logic inside `app.js`. However, as an application grows, this leads to a "Monolithic File" anti-pattern—thousands of lines of code that are impossible to maintain or test.
The Separation of Concerns (SoC)
The gold standard in backend development is the MVC (Model-View-Controller) pattern. In the context of a JSON API, we typically focus on MC (Models and Controllers), letting the Frontend handle the View.
❌ Monolithic (Bad)
// app.js
app.get('/users', (req, res) => {
// Database logic here
// Validation logic here
// Response logic here
// ... 50 lines later ...
});Hard to read, hard to test, hard to reuse.
✔️ Modular (Good)
// routes/users.js
router.get('/', userController.getAll);
// controllers/users.js
exports.getAll = (req, res) => {
// Logic isolated here
};Clean, testable, and strictly defined responsibilities.
The Role of the Controller
Controllers act as the traffic cops of your application. They shouldn't necessarily contain deep business logic (that belongs in Services or Models), but they *must* handle the HTTP layer:
- Parsing Request data (body, params, query).
- Invoking the correct Business Logic.
- Formatting the Response (Status codes, JSON structure).
- Handling Errors passed to `next()`.
Pro Tip: Keep your controllers "skinny". If a controller function is longer than 20 lines, you probably need to extract logic into a separate Service or Utility helper.