El patrón de arquitectura MVC (Modelo-Vista-Controlador) es uno de los más populares para organizar aplicaciones tanto en el backend como en el frontend. Divide la aplicación en tres capas principales para mejorar la separación de responsabilidades, facilitar el mantenimiento y permitir la escalabilidad.
El modelo define cómo interactuar con la base de datos. En un sistema con MongoDB, el modelo se crea con Mongoose:
import { Schema, model } from 'mongoose';
const TaskSchema = new Schema({
title: { type: String, required: true },
completed: { type: Boolean, default: false },
});
export const Task = model('Task', TaskSchema);
En aplicaciones backend, las vistas suelen ser respuestas JSON o plantillas dinámicas.
res.json({ message: 'Task created', task });
<!DOCTYPE html>
<html>
<head><title>Tareas</title></head>
<body>
<h1><%= title %></h1>
</body>
</html>
El controlador maneja la lógica del negocio y las solicitudes HTTP.
import { Task } from '../models/Task';
export const getTasks = async (req, res) => {
const tasks = await Task.find();
res.json(tasks);
};
Define las URL que conectan a los controladores.
import express from 'express';
import { getTasks } from './controllers/taskController';
const router = express.Router();
router.get('/tasks', getTasks);
export default router;
El estado de la aplicación sirve como el modelo en React.
const [tasks, setTasks] = useState<Task[]>([]);
La vista está compuesta por componentes que muestran datos al usuario.
const TaskList = ({ tasks }) => (
<ul>
{tasks.map(task => (
<li key={task.id}>{task.title}</li>
))}
</ul>
);
El controlador en React maneja eventos y llamadas a APIs.
const fetchTasks = async () => {
const response = await fetch('/api/tasks');
const data = await response.json();
setTasks(data);
};
import React, { useEffect, useState } from 'react';
const App = () => {
const [tasks, setTasks] = useState([]);
useEffect(() => {
fetchTasks();
}, []);
return <TaskList tasks={tasks} />;
};
export default App;