Controller, service, data: one job per file
Think of a restaurant. The waiter takes your order and brings the food. The chef cooks. The pantry stores ingredients. The waiter does not cook. The chef does not seat customers. The pantry does not take orders. When you hire a new chef, the waiters do not need retraining.
Backends work the same way. Controllers handle HTTP (req, res, status codes). Services handle business logic (find, create, delete, validate). The data layer handles persistence (in-memory now, a real Postgres database once we get to persistence). Each one only knows about itself and the layer below it.
import { booksDb, Book } from '../data';
export function getAllBooks(): Book[] {
return booksDb;
}
export function getBookById(id: number): Book | undefined {
return booksDb.find(book => book.id === id);
}
export function createBook(input: Omit<Book, 'id'>): Book {
const newId = booksDb.length > 0
? Math.max(...booksDb.map(b => b.id)) + 1
: 1;
const newBook = { id: newId, ...input };
booksDb.push(newBook);
return newBook;
}
export function deleteBook(id: number): boolean {
const idx = booksDb.findIndex(b => b.id === id);
if (idx === -1) return false;
booksDb.splice(idx, 1);
return true;
}Pure business logic. No req. No res. No HTTP at all.
import { Request, Response } from 'express';
import * as bookService from '../services/book.service';
export function getBooksHandler(req: Request, res: Response) {
const books = bookService.getAllBooks();
res.json(books);
}
export function getBookHandler(req: Request, res: Response) {
const id = parseInt(req.params.id, 10);
const book = bookService.getBookById(id);
if (!book) {
res.status(404).json({ error: 'Book not found' });
return;
}
res.json(book);
}Translates between HTTP and the service. No business logic.
The payoff from this split shows up twice. You can test the service without HTTP at all. And when you swap the in-memory array for Postgres later on, only the data and service layers change. The controllers and routes stay exactly the same.
Because the file you have to read at 2 a.m. when something breaks is the one with the bug. If everything is in one file, the bug could be in HTTP parsing, validation, business logic, or persistence. With layers, you start in the right file. Time to root cause drops by an order of magnitude. The extra files cost minutes. The clarity saves hours.
Quiz: Quiz
Loading practiceโฆ