Modularización del código: separación de archivos y organización de la estructura
Al finalizar este tema
Comprenderá por qué es necesario dividir el código en varios archivos y podrá separar los archivos directamente mediante los patrones require/module.exports de Node.js.
¿Por qué no se debe incluir todo en un solo archivo?
Cuando el proyecto es pequeño, puede incluir todo el código en un solo archivo app.js. Sin embargo, surgen problemas cuando el código supera las 500 o 1000 líneas.
- Dificultad para encontrar: "¿Dónde está la lógica de inicio de sesión?" → Hay que desplazarse mucho.
- Conflictos: Si varias personas modifican el mismo archivo, los conflictos de fusión (merge) en Git son frecuentes.
- No se puede reutilizar: Para utilizar una función auxiliar creada en el proyecto A en el proyecto B, hay que copiar y pegar.
La modularización resuelve estos problemas. Se trata de separar el código de modo que un archivo = una función.
Cómo separar archivos en Node.js
Node.js utiliza module.exports para exportar y require() para importar.
// math.js — módulo de utilidades de cálculo
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
module.exports = { add, multiply };// app.js — usar desde el archivo principal
const math = require('./math');
console.log(math.add(3, 5)); // 8
console.log(math.multiply(4, 7)); // 28math.js se encarga únicamente de los cálculos. app.js simplemente utiliza esa función, por lo que no es necesario que conozca la lógica de cálculo. Este es el principio de separación de responsabilidades (Separation of Concerns).
Estructura de carpetas en un proyecto real
A medida que el proyecto crece, se organiza en carpetas. A continuación, se muestra una estructura típica de un proyecto Express:
project/
├── app.js # Punto de entrada — inicio del servidor
├── routes/
│ ├── users.js # Rutas relacionadas con /users
│ └── posts.js # Rutas relacionadas con /posts
├── controllers/
│ ├── userController.js
│ └── postController.js
├── models/
│ └── db.js # Conexión a la base de datos
└── utils/
└── helpers.js # Funciones de utilidad comunesroutes/ gestiona las rutas URL, controllers/ la lógica de negocio y models/ el procesamiento de datos. Dado que cada carpeta tiene una función específica, si aparece un "error relacionado con el usuario", solo es necesario revisar routes/users.js y controllers/userController.js.
ES Modules: sintaxis moderna
En Node.js 14+ o en el navegador, se puede utilizar la sintaxis de ES Modules con import/export.
// math.mjs (o configurar "type": "module" en package.json)
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}// app.mjs
import { add, multiply } from './math.mjs';
console.log(add(3, 5)); // 8
console.log(multiply(4, 7)); // 28require y import tienen el mismo propósito, pero import permite el análisis estático, lo que facilita que los empaquetadores (Webpack, Vite) eliminen el código innecesario mediante la técnica de "tree-shaking". Se recomienda usar módulos ES en los nuevos proyectos.
Resumen clave
| Pregunta | Respuesta |
|---|---|
| ¿Por qué dividir? | Facilita la búsqueda, permite la reutilización y reduce los conflictos de colaboración. |
| ¿Cómo dividir? | module.exports + require (CommonJS) o export + import (ESM). |
| ¿Cuál es el criterio? | Un archivo = una función (separación de responsabilidades). |
| ¿Estructura de carpetas? | Clasificación por función: routes / controllers / models / utils, etc. |
Es recomendable empezar a dividir los archivos cuando el código tenga 100 líneas. Si se espera a tener 1000 líneas para hacerlo, ya estará tan enredado que será difícil.