{"id":1263,"date":"2025-05-16T06:33:27","date_gmt":"2025-05-16T06:33:27","guid":{"rendered":"https:\/\/www.wordpress-prod.sharpener.tech\/?p=1263"},"modified":"2025-05-16T06:33:27","modified_gmt":"2025-05-16T06:33:27","slug":"mastering-controllers-in-expressjs","status":"publish","type":"post","link":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/","title":{"rendered":"Mastering Controllers in Express.js"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/www.wordpress-prod.sharpener.tech\/wp-content\/uploads\/2025\/05\/controller-1024x683.jpg\" alt=\"\" class=\"wp-image-1264\" srcset=\"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller-1024x683.jpg 1024w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller-300x200.jpg 300w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller-768x512.jpg 768w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Hi everyone! I hope you\u2019re all doing fine. My name is Julian, and today we\u2019re going to learn about controllers. Before diving in, let me share an experience that perfectly illustrates why controllers are essential.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Jimmy&#8217;s Story: The Need for Controllers<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>You might remember Jimmy from our earlier discussion on routers.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Jimmy\u2019s caf\u00e9 was doing great. Initially, when he had just a few orders, everything was simple.<br>Jimmy himself would take the orders, process them, and pass them to the kitchen. His workers (routers) would just direct the orders to the right places, and things ran smoothly. But as Jimmy\u2019s caf\u00e9 grew, so did the complexity of managing his orders.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">He started to have more customers with special requests\u2014like those wanting gluten-free or vegan meals. The kitchen staff began to struggle with understanding the details of each order, and customers started getting frustrated when their meals weren\u2019t exactly as requested.<br>Jimmy realized that just passing the orders along wasn\u2019t enough.<br>He needed someone to <strong>oversee the process<\/strong>, ensuring that the orders were processed correctly, all customer requirements were met, and nothing was overlooked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, Jimmy hired a <strong>supervisor<\/strong> for each section of the caf\u00e9: one for managing the orders, one for ensuring quality control in the kitchen, and one for handling special requests.<br>These supervisors not only received the orders (just like the workers did) but also ensured that the orders were handled correctly and everything ran smoothly in the kitchen. <strong>These supervisors are like the controllers in Express.js.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Why Controllers Are Needed<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In the same way that supervisors ensure each aspect of the caf\u00e9 runs smoothly, controllers manage the business logic of your application. Let\u2019s break it down:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Separation of Concerns:<\/strong><strong><br><\/strong>Just like Jimmy\u2019s caf\u00e9 divided the responsibilities between workers and supervisors, controllers help separate <strong>routing<\/strong> (handling incoming requests) from <strong>business logic<\/strong> (processing and responding to those requests). This makes your code cleaner and easier to manage.<\/li>\n\n\n\n<li><strong>Cleaner Code:<\/strong><strong><br><\/strong>If Jimmy had mixed the tasks of taking orders with managing the kitchen, things would get messy. Similarly, controllers keep business logic separate from routes, making your code more readable.<\/li>\n\n\n\n<li><strong>Reusability:<\/strong><strong><br><\/strong>Jimmy\u2019s caf\u00e9 supervisors don\u2019t always redo tasks from scratch. They follow established procedures. Similarly, controllers allow you to reuse logic across different routes without duplication.<\/li>\n\n\n\n<li><strong>Error Handling:<\/strong><strong><br><\/strong>If an order goes wrong in Jimmy\u2019s caf\u00e9, the supervisor steps in to correct it. Controllers handle errors in your app and ensure that everything runs smoothly, even when something goes wrong.<\/li>\n\n\n\n<li><strong>Scalability:<\/strong><strong><br><\/strong>As Jimmy\u2019s caf\u00e9 grew, he hired more supervisors to manage different aspects of the business. Controllers do the same\u2014they allow your app to grow and scale without becoming unmanageable.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>So let\u2019s try to understand when to Use Controllers<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You should consider using controllers when<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>You have multiple routes with similar logic.<\/strong> If multiple routes require the same logic or tasks (like checking user authentication), controllers allow you to reuse that logic rather than duplicating it in every route handler.<\/li>\n\n\n\n<li><strong>You need better organization and maintainability.<\/strong> As your app grows, separating logic into controllers helps you keep your code organized and more maintainable, especially if you have many routes and services interacting.<\/li>\n\n\n\n<li><strong>You want to handle errors consistently.<\/strong> If you need a standard way to handle errors across your application (such as catching missing parameters or bad requests), controllers give you a centralized location to manage those errors.<\/li>\n\n\n\n<li><strong>Your routes involve complex business logic.<\/strong> If you find that your routes are getting crowded with logic like data validation, processing, or interacting with other services (like databases which we will learn in upcoming videos), controllers can keep the routes clean and manageable.:<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Change the implementation:<\/strong><\/h3>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementing Controllers in Code<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we know why controllers are essential, let\u2019s see how we can implement them in an Express.js app. Below is how the process would look, just like the supervisor in Jimmy\u2019s caf\u00e9.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Main Application File (app.js)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This file will remain largely the same, except we\u2019ll import the routes and their controllers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const app = express();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Import routes<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ordersRouter = require(&#8216;.\/routes\/orders&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const usersRouter = require(&#8216;.\/routes\/users&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Use routers<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use(&#8216;\/orders&#8217;, ordersRouter);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use(&#8216;\/users&#8217;, usersRouter);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Start the server<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.listen(3000, () =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;console.log(&#8216;Server is running on port 3000&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Orders Controller (controllers\/ordersController.js)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This file will contain the logic for handling requests related to orders. This keeps the business logic separate from the routes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ controllers\/ordersController.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Controller to get all orders<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const getAllOrders = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.send(&#8216;Order List&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Controller to create a new order<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const createOrder = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.send(&#8216;Order Created&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;getAllOrders,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;createOrder,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Orders Routes (routes\/orders.js)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now, the routes will simply refer to the appropriate controller functions for handling requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">javascript<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Copy code<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const router = express.Router();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Import controllers<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ordersController = require(&#8216;..\/controllers\/ordersController&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Define routes and delegate to controllers<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/&#8217;, ordersController.getAllOrders);&nbsp; \/\/ Get all orders<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.post(&#8216;\/&#8217;, ordersController.createOrder); \/\/ Create a new order<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = router;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Users Controller (controllers\/usersController.js)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is similar to the orders controller but handles the logic for users.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">javascript<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Copy code<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ controllers\/usersController.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Controller to get all users<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const getAllUsers = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.send(&#8216;User List&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Controller to create a new user<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const createUser = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.send(&#8216;User Created&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;getAllUsers,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;createUser<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. Users Routes (routes\/users.js)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Just like the orders routes, the users routes will use the user controller to handle requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">javascript<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Copy code<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const router = express.Router();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Import controllers<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const usersController = require(&#8216;..\/controllers\/usersController&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Define routes and delegate to controllers<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/&#8217;, usersController.getAllUsers); \/\/ Get all users<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.post(&#8216;\/&#8217;, usersController.createUser); \/\/ Create a new user<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = router;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Summary of Changes:<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Controllers:<\/strong>\n<ul class=\"wp-block-list\">\n<li>controllers\/ordersController.js and controllers\/usersController.js are created to handle the logic for orders and users, respectively.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Routes:<\/strong>\n<ul class=\"wp-block-list\">\n<li>routes\/orders.js and routes\/users.js now only define the route paths and delegate the logic to the appropriate controller functions.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This way, your routes and controllers are separated, making the code more modular, easier to maintain, and test.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Advantages of Using Controllers<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Better Code Organization:<\/strong><strong><br><\/strong>Just like Jimmy organized his caf\u00e9 by hiring supervisors, controllers organize your code by separating the business logic from the routes.<\/li>\n\n\n\n<li><strong>Scalability:<\/strong><strong><br><\/strong>As Jimmy&#8217;s caf\u00e9 grew, he added more supervisors. Similarly, as your app grows, controllers allow you to scale without adding complexity to your routes.<\/li>\n\n\n\n<li><strong>Consistency in Error Handling:<\/strong><strong><br><\/strong>Jimmy\u2019s supervisors handle all order-related issues the same way. Controllers ensure that errors are handled in a consistent manner, improving the reliability of your app.<\/li>\n\n\n\n<li><strong>Reusability:<\/strong><strong><br><\/strong>Jimmy\u2019s supervisors follow the same procedure for every order. Similarly, controllers let you reuse logic across different parts of your app.<\/li>\n\n\n\n<li><strong>Testability:<\/strong><strong><br><\/strong>Just like it\u2019s easier to evaluate a supervisor\u2019s performance, controllers make it easier to test the individual components of your app without worrying about the route handling.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Conclusion<\/strong><strong><br><\/strong><strong><br><\/strong>Controllers, like supervisors in Jimmy\u2019s caf\u00e9, are vital for managing complex tasks.<br><strong>They ensure that business logic, data processing, and error handling are taken care of, leaving your routes simple and focused on handling requests.<\/strong> By using controllers in Express.js, you can achieve a cleaner, more organized, and scalable codebase\u2014just like Jimmy did by adding supervisors to his caf\u00e9.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u2014&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br>Updating the example for Code:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><br>One example for ecommerce:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Before Using Controllers<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">All logic is embedded directly in the routes file:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ routes\/productRoutes.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const router = express.Router();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Fetch all products<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/products&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(&#8220;Fetching all products&#8221;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Fetch a product by ID<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/products\/:id&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Fetching product with ID: ${req.params.id}`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Add a new product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.post(&#8216;\/products&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(&#8220;Product is created&#8221;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Update a product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.put(&#8216;\/products\/:id&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Product with ID: ${req.params.id} is updated`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Delete a product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.delete(&#8216;\/products\/:id&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Product with ID: ${req.params.id} is deleted`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = router;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>After Using Controllers<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The logic is moved to a separate <strong>controller<\/strong> file, keeping routes clean:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Controller Code (Individual Exports)<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ controllers\/ProductController.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Fetch all products<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const getAllProducts = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(&#8220;Fetching all products&#8221;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Fetch a product by ID<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const getProductById = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Fetching product with ID: ${req.params.id}`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Add a new product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const createProduct = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(&#8220;Product is created&#8221;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Update a product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const updateProduct = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Product with ID: ${req.params.id} is updated`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Delete a product<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const deleteProduct = (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.send(`Product with ID: ${req.params.id} is deleted`);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Export each function individually<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;getAllProducts,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;getProductById,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;createProduct,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;updateProduct,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;deleteProduct,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Routes Code<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ routes\/productRoutes.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ProductController = require(&#8216;..\/controllers\/ProductController&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const router = express.Router();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/products&#8217;, ProductController.getAllProducts);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.get(&#8216;\/products\/:id&#8217;, ProductController.getProductById);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.post(&#8216;\/products&#8217;, ProductController.createProduct);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.put(&#8216;\/products\/:id&#8217;, ProductController.updateProduct);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">router.delete(&#8216;\/products\/:id&#8217;, ProductController.deleteProduct);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = router;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Key Comparison<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Before Controller:<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>All route logic is handled inline, making the file lengthy and harder to maintain.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>After Controller:<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Routes are simplified and focus only on mapping HTTP methods to controller methods.<\/li>\n\n\n\n<li>The actual logic is moved to a separate controller file, improving readability and reusability.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Key Benefits of Individual Exports<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Clarity<\/strong>: Named exports explicitly show what the module provides.<\/li>\n\n\n\n<li><strong>Flexibility<\/strong>: You can import only the specific functions you need in other files.<\/li>\n\n\n\n<li><strong>Testability<\/strong>: Individual exports make it easier to test functions separately.<\/li>\n\n\n\n<li><strong>Modularity<\/strong>: Allows functions to be reused independently across different parts of the application.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This method works especially well in larger applications where the same controller functions might be used in different contexts or modules.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi everyone! I hope you\u2019re all doing fine. My name is Julian, and today we\u2019re going to learn about controllers. Before diving in, let me share an experience that perfectly&hellip;<\/p>\n","protected":false},"author":6,"featured_media":1264,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24],"tags":[],"class_list":["post-1263","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tips"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Mastering Controllers in Express.js: Best Practices &amp; Examples for 2025<\/title>\n<meta name=\"description\" content=\"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mastering Controllers in Express.js: Best Practices &amp; Examples for 2025\" \/>\n<meta property=\"og:description\" content=\"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/\" \/>\n<meta property=\"og:site_name\" content=\"Sharpener Tech\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-16T06:33:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Julian Toppo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Julian Toppo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/\"},\"author\":{\"name\":\"Julian Toppo\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/person\\\/eb9482df421e52d30f961eae8a0fd67a\"},\"headline\":\"Mastering Controllers in Express.js\",\"datePublished\":\"2025-05-16T06:33:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/\"},\"wordCount\":1709,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/16061110\\\/controller.jpg\",\"articleSection\":[\"Tips\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/\",\"name\":\"Mastering Controllers in Express.js: Best Practices & Examples for 2025\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/16061110\\\/controller.jpg\",\"datePublished\":\"2025-05-16T06:33:27+00:00\",\"description\":\"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#primaryimage\",\"url\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/16061110\\\/controller.jpg\",\"contentUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/16061110\\\/controller.jpg\",\"width\":1536,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/mastering-controllers-in-expressjs\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Mastering Controllers in Express.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\",\"name\":\"Sharpener Tech\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\",\"name\":\"Sharpener Tech\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wordpress-prod.sharpener.tech\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Sharpener_logo-removebg-preview.png\",\"contentUrl\":\"https:\\\/\\\/wordpress-prod.sharpener.tech\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Sharpener_logo-removebg-preview.png\",\"width\":187,\"height\":62,\"caption\":\"Sharpener Tech\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/person\\\/eb9482df421e52d30f961eae8a0fd67a\",\"name\":\"Julian Toppo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"caption\":\"Julian Toppo\"},\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/author\\\/julian\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Mastering Controllers in Express.js: Best Practices & Examples for 2025","description":"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/","og_locale":"en_US","og_type":"article","og_title":"Mastering Controllers in Express.js: Best Practices & Examples for 2025","og_description":"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.","og_url":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/","og_site_name":"Sharpener Tech","article_published_time":"2025-05-16T06:33:27+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg","type":"image\/jpeg"}],"author":"Julian Toppo","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Julian Toppo","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#article","isPartOf":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/"},"author":{"name":"Julian Toppo","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/person\/eb9482df421e52d30f961eae8a0fd67a"},"headline":"Mastering Controllers in Express.js","datePublished":"2025-05-16T06:33:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/"},"wordCount":1709,"commentCount":0,"publisher":{"@id":"https:\/\/www.sharpener.tech\/blog\/#organization"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#primaryimage"},"thumbnailUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg","articleSection":["Tips"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/","url":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/","name":"Mastering Controllers in Express.js: Best Practices & Examples for 2025","isPartOf":{"@id":"https:\/\/www.sharpener.tech\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#primaryimage"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#primaryimage"},"thumbnailUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg","datePublished":"2025-05-16T06:33:27+00:00","description":"Learn how to create and manage controllers in Express.js effectively. Discover best practices, code examples, and tips to build clean, scalable backend APIs in 2025.","breadcrumb":{"@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#primaryimage","url":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg","contentUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/16061110\/controller.jpg","width":1536,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/www.sharpener.tech\/blog\/mastering-controllers-in-expressjs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sharpener.tech\/blog\/"},{"@type":"ListItem","position":2,"name":"Mastering Controllers in Express.js"}]},{"@type":"WebSite","@id":"https:\/\/www.sharpener.tech\/blog\/#website","url":"https:\/\/www.sharpener.tech\/blog\/","name":"Sharpener Tech","description":"","publisher":{"@id":"https:\/\/www.sharpener.tech\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sharpener.tech\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.sharpener.tech\/blog\/#organization","name":"Sharpener Tech","url":"https:\/\/www.sharpener.tech\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/wordpress-prod.sharpener.tech\/wp-content\/uploads\/2026\/05\/Sharpener_logo-removebg-preview.png","contentUrl":"https:\/\/wordpress-prod.sharpener.tech\/wp-content\/uploads\/2026\/05\/Sharpener_logo-removebg-preview.png","width":187,"height":62,"caption":"Sharpener Tech"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/person\/eb9482df421e52d30f961eae8a0fd67a","name":"Julian Toppo","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","caption":"Julian Toppo"},"url":"https:\/\/www.sharpener.tech\/blog\/author\/julian\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/comments?post=1263"}],"version-history":[{"count":1,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1263\/revisions"}],"predecessor-version":[{"id":1265,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1263\/revisions\/1265"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/media\/1264"}],"wp:attachment":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/media?parent=1263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/categories?post=1263"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/tags?post=1263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}