Розуміння архітектури бекенду: MVC та рефакторинг для чистого коду

Створення надійного бекенду вимагає добре структурованої архітектури, яка організує ваш код і спрощує його підтримку. Одним із найпопулярніших патернів для структуризації бекенд-застосунків є архітектура Model-View-Controller (MVC). Цей блог ознайомить вас з MVC, обговорить типи логіки та покаже, як рефакторити простий застосунок на Express у структуру MVC.

pic

Вступ до архітектури бекенду: MVC

Що таке MVC?

MVC — це скорочення від Model-View-Controller, патерн проектування, який розділяє логіку застосунку на три взаємопов'язані компоненти:

  1. Модель (Model): Керує даними, логікою та правилами застосунку. Вона безпосередньо взаємодіє з базою даних.
  2. Подання (View): Обробляє презентаційний рівень — те, що бачить користувач (HTML, JSON відповіді тощо).
  3. Контролер (Controller): Діє як посередник між Моделлю та Поданням. Він обробляє введення користувача, взаємодіє з Моделлю і визначає, що повинно відображатися в Поданні.

Чому використовувати MVC?

  • Розподіл відповідальності (Separation of Concerns): Кожен рівень обробляє конкретний аспект, що робить код простішим для розуміння і підтримки.
  • Масштабованість: Модульний дизайн спрощує додавання нових функцій.
  • Повторне використання (Reusability): Компоненти можуть бути повторно використані в різних частинах застосунку.

Типи логіки в розробці бекенду

При створенні бекенд-застосунків логіка зазвичай ділиться на три типи:

  1. Бізнес-логіка (Business Logic): Визначає, як дані можуть бути створені, збережені або змінені. Наприклад, перевірка віку користувача перед створенням профілю.
  2. Презентаційна логіка (Presentation Logic): Обробляє форматування і відображення даних користувачеві.
  3. Логіка маршрутизації (Routing Logic): Направляє вхідні запити до правильного контролера або функції.

Розуміння цих типів допомагає визначити, куди має потрапляти кожен функціональний блок в структурі MVC.

Рефакторинг до MVC

Щоб продемонструвати рефакторинг до MVC, почнемо з простого застосунку на Express, який не має структури, і організуємо його в патерн MVC.

Початковий код: Простий застосунок на Express

Ось базовий застосунок на Express:

const app = express();  
app.use(express.json());  

mongoose.connect('mongodb://localhost:27017/myApp', {  
 useNewUrlParser: true,  
 useUnifiedTopology: true,  
}).then(() => console.log('Database connected')).catch(err => console.error(err));  

const tourSchema = new mongoose.Schema({  
 name: String,  
 price: Number,  
});  
const Tour = mongoose.model('Tour', tourSchema);  

app.get('/tours', async (req, res) => {  
 const tours = await Tour.find();  
 res.status(200).json(tours);  
});  

app.post('/tours', async (req, res) => {  
 const newTour = await Tour.create(req.body);  
 res.status(201).json(newTour);  
});  

app.listen(3000, () => console.log('Server running on port 3000'));

Цей застосунок працює, але змішує маршрутизацію, бізнес-логіку та операції з базою даних в одному файлі.
Давайте рефакторимо це, використовуючи MVC.

Крок 1: Організуйте файли

Створіть нову структуру для вашого застосунку:

project-folder/  
|-- models/  
| |-- tourModel.js  
|-- controllers/  
| |-- tourController.js  
|-- routes/  
| |-- tourRoutes.js  
|-- app.js  
|-- server.js

Крок 2: Створіть Модель

Перемістіть схему та модель в models/tourModel.js:

const mongoose = require('mongoose');  

const tourSchema = new mongoose.Schema({  
 name: {  
 type: String,  
 required: [true, 'A tour must have a name'],  
 },  
 price: {  
 type: Number,  
 required: [true, 'A tour must have a price'],  
 },  
});  

const Tour = mongoose.model('Tour', tourSchema);  
module.exports = Tour;

Крок 3: Створіть Контролер

Перемістіть логіку маршруту в controllers/tourController.js:

const Tour = require('../models/tourModel');  

exports.getAllTours = async (req, res) => {  
 try {  
 const tours = await Tour.find();  
 res.status(200).json({  
 status: 'success',  
 results: tours.length,  
 data: { tours },  
 });  
 } catch (err) {  
 res.status(500).json({  
 status: 'error',  
 message: err.message,  
 });  
 }  
};  

exports.createTour = async (req, res) => {  
 try {  
 const newTour = await Tour.create(req.body);  
 res.status(201).json({  
 status: 'success',  
 data: { tour: newTour },  
 });  
 } catch (err) {  
 res.status(400).json({  
 status: 'fail',  
 message: err.message,  
 });  
 }  
};

Крок 4: Налаштуйте Маршрути

Оголосіть маршрути в routes/tourRoutes.js:

const express = require('express');  
const tourController = require('../controllers/tourController');  

const router = express.Router();  

router.route('/')  
 .get(tourController.getAllTours)  
 .post(tourController.createTour);  

module.exports = router;

Крок 5: Оновіть файл App

Використовуйте маршрути в app.js:

const express = require('express');  
const tourRoutes = require('./routes/tourRoutes');  

const app = express();  
app.use(express.json());  
app.use('/api/v1/tours', tourRoutes);  

module.exports = app;

Крок 6: Запустіть сервер

Перемістіть логіку запуску сервера в server.js:

const app = require('./app');  

const PORT = 3000;  
app.listen(PORT, () => {  
 console.log(`App running on port ${PORT}`);  
});

Висновок

Після рефакторингу застосунку на Express у патерн MVC ми розділили відповідальність і покращили підтримуваність. Модель обробляє дані, контролер управляє логікою, а маршрути з'єднують усе разом. Така структура добре масштабується і підтримує чистоту вашого коду, особливо коли ваш застосунок росте. Удачі в програмуванні!

Перекладено з: Understanding Back-End Architecture: MVC and Refactoring for Clean Code

Leave a Reply

Your email address will not be published. Required fields are marked *