In this lesson, you will learn how to maintain clean, scalable code by separating the "where" (the URL path) from the "what" (the business logic).
The Problem: Monolithic Routing
When you are building a server, it is tempting to cram all your code into one file. You might see a giant switch statement or a series of if/else blocks inside your request handler that checks the req.url. This leads to "Spaghetti Code," where changing a single business rule risks breaking your entire routing structure.
Decoupling with Modular Handlers
"Routing Logic Decoupling" means we treat the router as a traffic controller and the business logic as a specialized worker. The router’s only job is to inspect the incoming request and identify who should handle it. The actual logic is then moved into separate functions or modules.
Instead of writing logic inside the request listener, we map paths to functions:
// handlers.js
const getUser = (req, res) => { /* Complex logic here */ };
const updateSettings = (req, res) => { /* Complex logic here */ };
module.exports = { getUser, updateSettings };
// server.js
const { getUser, updateSettings } = require('./handlers');
const routeMap = {
'/user': getUser,
'/settings': updateSettings
};
server.on('request', (req, res) => {
const handler = routeMap[req.url] || defaultHandler;
handler(req, res); // The router doesn't need to know how these work!
});
Why this matters
By decoupling these layers, you achieve two major benefits:
- Maintainability: If your
getUserlogic changes, you only touchhandlers.js. Your server configuration remains untouched. - Testability: Because your business logic is now a standalone function, you can write unit tests for it without needing to simulate the entire HTTP network stack. You just pass in mock
reqandresobjects.
By offloading the "how-to" to dedicated modules, your server.js acts purely as an entry point, making your architecture robust and easy to navigate as your application grows from ten routes to a hundred.
Key Takeaway: Never put business logic inside your router; use the router as a traffic officer that delegates tasks to specialized, modular handler functions.