Skip to content

Base de Datos y ORM


Especialízate en el stack que más te apasiona y destaca en el mercado laboral. La personalización de tus habilidades puede ser la clave para obtener el empleo y salario que deseas. ¡Inscríbete ya!


Quiero destacar en el mercado laboral


Si pudiste completar los talleres anteriores, nuestro proyecto ya debería contar con un esqueleto visual interactivo gracias a la Lección 5 (L5) y unas reglas de comunicación estructuradas en tu API (L4). Sin embargo, habrás notado que cada vez que recargamos la página, todo vuelve a cero. Nuestra aplicación sufre de amnesia temporal.

En esta sesión le daremos memoria y persistencia a nuestro proyecto. No nos limitaremos a escribir algunas consultas SQL al azar; aprenderemos a diseñar bases de datos robustas, a versionar los esquemas y a mantener nuestro código de base de datos estrictamente aislado de nuestra lógica de negocio empresarial.

¡Es hora de construir los cimientos que sostendrán toda tu información!


1. Modelado de Datos Profesional

Antes de elegir si usaremos Postgres, MySQL o MongoDB, necesitamos entender la forma de nuestra información basándonos en los requerimientos que documentaste en tu Backlog (L2).

SQL vs NoSQL: La Decisión Estratégica

En el mundo del almacenamiento, existen dos filosofías principales:

  • SQL (Relacionales): Bases de datos como PostgreSQL o MySQL. La información se guarda en tablas estrictamente definidas (filas y columnas). Son ideales cuando tus datos tienen relaciones complejas y necesitas garantizar integridad absoluta (ej. sistemas financieros, inventarios).
  • NoSQL (No Relacionales): Bases de datos como MongoDB o DynamoDB. Guardan la información en documentos flexibles (usualmente similares a JSON). Son excelentes para desarrollo rápido, esquemas que cambian constantemente o aplicaciones de lectura masiva rápida.

Normalización de Datos

Si eliges una base de datos relacional (SQL), debes evitar la redundancia. La Normalización es el proceso de organizar los datos para minimizar la duplicación.

  • Mala práctica (Desnormalizado): Guardar el "Nombre del Autor" en cada uno de los artículos del blog. Si el autor cambia su nombre, ¡tendrás que actualizar mil artículos!
  • Buena práctica (Normalizado): Guardar un autor_id en el artículo, y tener una tabla separada de Autores. Si el autor cambia su nombre, solo actualizas un registro.

Diagrama Entidad-Relación (ERD)

Un buen arquitecto no crea tablas directamente en código. Primero, genera un Diagrama Entidad-Relación (ERD), que es una representación visual de cómo se conectan los conceptos del negocio. Existen herramientas gratuitas como dbdiagram.io o planttext que te permiten generar el modelo visual escribiendo pseudocódigo.


2. Implementación con ORMs

Años atrás, los desarrolladores escribían código SQL crudo mezclado dentro de su lógica backend. Hoy en día, utilizamos ORMs (Object-Relational Mapping).

Un ORM (como Prisma o TypeORM) es una librería que traduce tablas de base de datos a objetos en tu lenguaje de programación (ej. clases o interfaces de TypeScript) automáticamente.

¿Por qué Prisma es el estándar moderno para SQL?

En el ecosistema de TypeScript y Node.js para bases de datos relacionales, Prisma ha dominado el mercado porque ofrece:

  1. Tipado Seguro Absoluto: Autocompletado en tu editor para las consultas en la base de datos.
  2. Esquema Declarativo: Describes tu base de datos en un solo archivo schema.prisma legible, en lugar de decenas de consultas para crear tablas.
// Ejemplo de un archivo schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[] // Prisma maneja esta relación "1 a muchos" por ti
}
model Post {
id Int @id @default(autoincrement())
title String
authorId Int
author User @relation(fields: [authorId], references: [id])
}
  1. Migraciones Automáticas: Genera los scripts SQL para modificar la base de datos sin romperla.

Migraciones Seguras

Las migraciones son como el “Git” de tu base de datos. Cada vez que añades una nueva columna o cambias una tabla, el ORM crea un archivo de migración que cuenta la historia de lo que cambió. Esto es crítico: nunca debes modificar la base de datos de producción a mano. Tu código de migración debe ser el encargado de evolucionar el esquema.

Data Seeding

Tener la base de datos vacía en el entorno local (desarrollo) ralentiza muchísimo la verificación y el maquetado. El Data Seeding (o sembrado de datos) consiste en tener un pequeño script que infla automáticamente tu base de datos local con “datos falsos o simulados” (Usuarios ficticios de prueba, tareas por defecto, etc.) para que puedas desarrollar la UI localmente al instante y probar flujos de interfaz con datos.

seed.ts
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
console.log('🌱 Sembrando base de datos...')
// Borramos datos viejos para evitar duplicados en local
await prisma.post.deleteMany()
await prisma.user.deleteMany()
// Insertamos data simulada
await prisma.user.create({
data: {
name: 'Student',
posts: {
create: [
{ title: 'Learn Programming 2024' }
]
}
}
})
}
main().finally(async () => await prisma.$disconnect())

3. Capa de Persistencia y Repositorios

Como exploramos en la lección teórica sobre Arquitectura (L3), la Arquitectura Hexagonal nos invita a mantener una separación estricta de capas. Si aquel concepto te pareció un poco abstracto en su momento, ¡no te preocupes! Ahora visualizaremos e implementaremos exactamente esa teoría en la práctica.

Aislando el Dominio

Un error clásico es acoplar la base de datos, literalmente, en medio de la regla de negocio.

Mal ejemplo (Muy Acoplado): Acoplando la lógica de la API REST o Resolvers GraphQL directamente a la sintaxis del ORM. Si mañana dejamos de usar Prisma para usar TypeORM, habrá que reescribir toda la aplicación.

// Controlador / Endpoint REST muy acoplado al detalle de Infraestructura
async function createPost(req, res) {
// Regla de Negocio:
if (req.body.title.length < 5) return res.status(400);
// Detalle de Infraestructura mezclado:
const newPost = await prisma.post.create({ data: req.body });
return res.json(newPost);
}

El Patrón Repository

Para corregirlo, usamos el patrón Repository. Un repositorio actúa como un mediador silencioso. Nuestra lógica principal llama al Repositorio pidiéndole datos, y el Repositorio, de puertas para adentro, averigua cómo usar Prisma o cualquier ORM para traerlos.

Buen Ejemplo (Desacoplado):

// 1. EL CONTRATO (Puerto)
interface PostRepository {
create(post: PostEntity): Promise<PostEntity>;
}
// 2. EL ADAPTADOR (Infraestructura de DB usando Prisma en este caso)
class PrismaPostRepository implements PostRepository {
async create(post) {
return await prisma.post.create({ data: post });
}
}
// 3. LA LÓGICA DE NEGOCIO EN LA API (L4), totalmente ignorante de Prisma
class PostService {
constructor(private postRepo: PostRepository) {} // Inyectamos la Interfaz
async createPost(data) {
if (data.title.length < 5) throw new Error("Title too short");
return await this.postRepo.create(data);
}
}

Si adoptas esta separación garantizamos que los Controladores (API REST) o Resolvers (GraphQL) de tu API (L4) jamás se enteren de qué ORM usas debajo, manteniendo el corazón de tu aplicación completamente a salvo de la evolución incesante de frameworks o tecnologías externas.


4. Taller: Persistencia de Mi Proyecto

Llegó el momento de darle permanencia a tu proyecto personal de las semanas previas.

Fase 1: Toma de Decisión (ADR)

Revisa tus apuntes, requisitos y notas de Arquitectura (L3) y asegúrate de elegir el motor correcto. Crea un archivo llamado ADR-seleccion-bbdd.md en tu carpeta local /docs/architecture/decisions/ justificando técnicamente tu elección de Motor de Base de Datos y tu tecnología como ORM.

Fase 2: Configuración Inicial

  1. Define un plan local usando contenedores. Levanta un contenedor Docker con tu motor de base de datos elegido o créate una instancia gratuita en la nube usando plataformas como Supabase o PlanetScale.
  2. Instala y provee de su configuración tu ORM elegido dentro del código.

Fase 3: La Primera Entidad y Migración

  1. De las historias priorizadas del Backlog (L2), identifica tu Entidad Core número 1.
  2. Traduce y define el esquema de esa entidad, estableciendo las columnas, restricciones (Not Nulls) y tipos para reflejar un Modelado de datos Profesional.
  3. Corre tu primera migración de esquema para forjar las tablas físicas de forma segura.
  4. Crea un pequeño script de Seeding para insertarte a ti mismo como tu usuario maestro o como primer recurso, corriendo la data por defecto directamente.

Fase 4: Conexión Integral Frontend-Backend

Es tu momento crucial de orquestación.

  1. Si lograste avanzar con tu API (L4), usa esos Resolvers o Controladores e inyecta el Repository para apuntarlos a la base de datos real.
  2. Inicia tus servidores locales. Si lograste construir parte de la interfaz en la Lección 5 (L5), intenta navegar por ella.
  3. Trata de mutar y crear la entidad directamente desde tu formulario UI (o usando alguna herramienta como Postman).

Si llegaste hasta aquí logrando persistir datos, ¡felicidades por tu esfuerzo constante! La ilusión del software ahora tiene sustancia y tu plataforma está cobrando vida de forma real. Y recuerda: no pasa nada si no has terminado todos los talleres anteriores, lo verdaderamente importante es que vayas entendiendo pacientemente cómo cada una de estas piezas encaja en el gran rompecabezas.


Referencias y Lecturas Recomendadas

Para afinar tus nuevos dotes como Ingeniero de Datos en Software y tu Arquitectura Backend, explora los siguientes materiales estándar:


Especialízate en el stack que más te apasiona y destaca en el mercado laboral. La personalización de tus habilidades puede ser la clave para obtener el empleo y salario que deseas. ¡Inscríbete ya!


Quiero destacar en el mercado laboral