Arquitectura Escalable con Clases en JavaScript: De Código Spaghetti a Estructura Profesional
¿Tu proyecto JavaScript está creciendo y el código se vuelve inmanejable? Te presento el patrón ModeloBase que transformó mi código de spaghetti desorganizado a arquitectura limpia y escalable.
❌ El Caos del Código Duplicado
Antes tenía clases repetitivas para cada entidad de mi aplicación:
// ❌ Código duplicado para Producto
class Producto {
constructor() {
this.recurso = 'productos';
this.server = this.getServer();
}
async lista(page = 1, filtro = '') {
// 50 líneas de código repetitivo...
}
getServer() {
return location.origin;
}
}
// ❌ Mismo código duplicado para Cliente
class Cliente {
constructor() {
this.recurso = 'clientes';
this.server = this.getServer();
}
async lista(page = 1, filtro = '') {
// 50 líneas de código repetitivo... otra vez
}
getServer() {
return location.origin;
}
}
Problema: Duplicación de código, mantenimiento difícil, cambios tediosos y alta probabilidad de errores.
✅ La Solución: Patrón ModeloBase con Herencia
Creé una clase base reutilizable y clases específicas que la extienden:
// ✅ ModeloBase.js - Clase padre con funcionalidad común
export default class ModeloBase {
constructor(recurso) {
this.recurso = recurso;
this.server = this.getServer();
this.template = null;
}
setTemplate(template) {
this.template = template;
}
getServer() {
return location.origin;
}
async lista(page = 1, filtro = '') {
// Lógica común para TODOS los modelos
const url = `${this.server}/api/${this.recurso}?page=${page}&q=${filtro}`;
const response = await fetch(url);
const data = await response.json();
// Usa el template específico de cada clase hija
if (this.template) {
return data.items.map(item => this.template(item)).join('');
}
}
}
// ✅ Producto.js - Clase específica y limpia
import ModeloBase from './ModeloBase.js';
export class Producto extends ModeloBase {
constructor() {
super('productos'); // ← Llama al constructor padre
this.setTemplate(item => `
<tr data-line_id="${item.producto}">
<td>${item.producto}</td>
<td>${item.descripcion}</td>
<td>${item.unidadMedida}</td>
<td>${item.precioUnitario}</td>
</tr>
`);
}
// ✅ Puedo agregar métodos ESPECÍFICOS de Producto
calcularImpuestos(productoId) {
// Lógica exclusiva de productos
}
}
// ✅ Cliente.js - Otra clase específica
import ModeloBase from './ModeloBase.js';
export class Cliente extends ModeloBase {
constructor() {
super('clientes'); // ← Mismo padre, diferente recurso
this.setTemplate(item => `
<tr data-line_id="${item.cliente}">
<td>${item.razonSocial}</td>
<td>${item.ruc}</td>
<td>${item.telefono}</td>
</tr>
`);
}
// ✅ Métodos específicos de Cliente
obtenerHistorialCompras(clienteId) {
// Lógica exclusiva de clientes
}
}
🎯 Estructura de Herencia Visualizada
| ModeloBase (Padre) | Producto (Hijo) | Cliente (Hijo) |
|---|---|---|
| recurso | super('productos') | super('clientes') |
| server | ✅ Heredado | ✅ Heredado |
| lista() | ✅ Heredado | ✅ Heredado |
| template | 🔄 Específico | 🔄 Específico |
| Métodos extra | calcularImpuestos() | obtenerHistorialCompras() |
📈 Beneficios de Esta Arquitectura
| ✅ DRY Principle | No te repitas - lógica común en un solo lugar |
| ✅ Mantenibilidad | Cambios en ModeloBase afectan a TODAS las clases hijas |
| ✅ Escalabilidad | Nuevas entidades en minutos: extends ModeloBase + super() |
| ✅ Consistencia | Todas las clases siguen la misma estructura |
| ✅ Flexibilidad | Cada clase hija puede especializarse según sus necesidades |
🔧 Uso en la Práctica
// Inicialización limpia y consistente
const producto = new Producto();
const cliente = new Cliente();
// Mismo método, comportamiento diferente
producto.lista(1, 'laptop'); // → Busca en /api/productos
cliente.lista(1, 'empresa'); // → Busca en /api/clientes
// Métodos específicos de cada clase
producto.calcularImpuestos(123);
cliente.obtenerHistorialCompras(456);
💡 Patrón de Templates Integrado
Nota cómo cada clase define su propio template. Esto combina perfectamente con el patrón de herencia, permitiendo reutilizar la lógica de renderizado mientras personalizas la presentación.
Nota cómo cada clase define su propio template. Esto combina perfectamente con el patrón de herencia, permitiendo reutilizar la lógica de renderizado mientras personalizas la presentación.
🚀 Escalando tu Aplicación
¿Necesitas agregar una nueva entidad? Solo minutos:
// ✅ Proveedor.js - Nueva entidad en 2 minutos
import ModeloBase from './ModeloBase.js';
export class Proveedor extends ModeloBase {
constructor() {
super('proveedores'); // ← ¡Listo!
this.setTemplate(item => `
<tr>
<td>${item.nombre}</td>
<td>${item.contacto}</td>
</tr>
`);
}
// Agregar métodos específicos cuando los necesites
}
Conclusión
La herencia con clases en JavaScript no es solo teoría académica. Con el patrón ModeloBase, transformé mi código en una arquitectura profesional, mantenible y escalable. Ahora agregar nuevas funcionalidades es cuestión de minutos, no de horas.
La herencia con clases en JavaScript no es solo teoría académica. Con el patrón ModeloBase, transformé mi código en una arquitectura profesional, mantenible y escalable. Ahora agregar nuevas funcionalidades es cuestión de minutos, no de horas.
Comentarios
Publicar un comentario