
Controller-Service Pattern
The Controller-Service Pattern is a software design pattern that helps structure backend applications by separating concerns. It divides responsibilities between controllers (handling HTTP requests) and services (handling business logic).
Endpoint Definition
This API provides endpoints to manage user data. The main endpoints are:
GET /user/:id --> Retrieves a user by ID
POST /user --> Creates a new user
The controller handles these requests and delegates logic to the service.
Controller
The controller is responsible for handling HTTP requests and responses.
// userController.js
const UserService = require('./userService');
class UserController {
async getUser(req, res) {
const user = await UserService.getUserById(req.params.id);
res.json(user);
}
async createUser(req, res) {
const newUser = await UserService.createUser(req.body);
res.status(201).json(newUser);
}
}
module.exports = new UserController();
Service
The service contains the business logic and interacts with the data layer.
// userService.js
const UserModel = require('./userModel');
class UserService {
async getUserById(userId) {
return await UserModel.findById(userId);
}
async createUser(userData) {
return await UserModel.create(userData);
}
}
module.exports = new UserService();
Model
The model interacts with the database to store and retrieve user data.
// userModel.js
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: String,
email: String
});
module.exports = mongoose.model('User', UserSchema);
Routes
The routes define API endpoints and map them to the controller functions.
// routes.js
const express = require('express');
const UserController = require('./userController');
const router = express.Router();
router.get('/user/:id', UserController.getUser);
router.post('/user', UserController.createUser);
module.exports = router;
Benefits of applying the pattern
- Maintainability: Changes only affect a specific class
- Readability: The code is easier to understand
- Testability: Easier to test with unit tests
- Reusability: Classes can be reused in other contexts
- Fewer errors: Changes have fewer side effects
Diagram of Controller-Service Pattern
Below is a visual representation of how the pattern works:
