← Servidor web y API con Node

Sesión 7 · Semana 3

Separar en capas

Hoy · Hoja de ruta

  1. 1. Aprende: Qué hace cada capa y qué no debe saber ninguna de ellas.
  2. 2. Haz: Separa ruta, servicio y repositorio en tu proyecto.
  3. 3. Comprueba: Puedes cambiar el almacén sin tocar una sola ruta.

Antes de empezar · 5 minutos, sin apuntes

  1. ¿Cuántos ficheros tocarías hoy si cambiaras el fichero JSON por una base de datos?
  2. ¿Hay alguna función que sepa a la vez de HTTP y de ficheros?
  3. ¿Dónde vive la regla «no se puede borrar un producto con stock»?

Las tres capas

Qué sabe cada capa
  1. Ruta · HTTP
  2. Servicio · las reglas
  3. Repositorio · el almacén
Capa Sabe de No sabe de
Ruta Peticiones, respuestas y códigos Ficheros ni reglas de negocio
Servicio Reglas y validaciones HTTP ni de dónde salen los datos
Repositorio Cómo se guardan y se leen Reglas ni HTTP
// repositorio/productos.js
export async function porId(id) {
  const productos = await leerProductos();
  return productos.find((p) => p.id === id) ?? null;
}

// servicio/productos.js
export async function borrar(id) {
  const producto = await repositorio.porId(id);
  if (!producto) return false;
  if (producto.stock > 0) throw new ErrorDeConflicto("No se puede borrar con stock");
  return repositorio.eliminar(id);
}

// rutas/productos.js
export async function borrarProducto(peticion, respuesta, next) {
  try {
    const borrado = await servicio.borrar(Number(peticion.params.id));
    if (!borrado) throw new ErrorNoEncontrado("Producto no encontrado");
    respuesta.status(204).end();
  } catch (error) {
    next(error);
  }
}

La prueba de que las capas están bien separadas

Busca en tu servicio la palabra respuesta, y en tu repositorio la palabra peticion. Si aparecen, la separación es decorativa.

Y la prueba de fuego: si cambiar el fichero JSON por una base de datos obliga a tocar algo fuera del repositorio, todavía no están separadas. Ese es exactamente el ejercicio de la sesión siguiente.

Por qué molestarse

Con un solo recurso y un fichero, esta separación parece burocracia. Sus tres razones aparecen enseguida: se puede probar el servicio sin levantar un servidor; se puede cambiar el almacén sin tocar la API; y cuando el proyecto tiene ocho recursos, todos se organizan igual y cualquiera sabe dónde mirar.

Es, además, la arquitectura que verás en el módulo de servidor con otros nombres: controlador, servicio y repositorio.

Tarea 7 · La separación

  1. Crea src/servicio/ y src/repositorio/ y reparte tu código.
  2. Deja las rutas sin ninguna referencia a ficheros.
  3. Deja el servicio sin ninguna referencia a peticiones ni respuestas.
  4. Mueve al servicio las reglas de negocio que estaban en las rutas.
  5. Busca las dos palabras de la prueba y arregla lo que aparezca.
  6. Escribe un programa que use el servicio directamente, sin HTTP.
Objetivo mínimoTres capas separadas y la prueba de las dos palabras superada.
Si lo tienesAñade una regla de negocio nueva y comprueba que solo tocas el servicio.
RetoHaz que el servicio reciba el repositorio como parámetro, para poder sustituirlo.

Checkpoint · fin de la sesión 7

  • Cada capa sabe solo lo suyo.
  • Las reglas de negocio están en el servicio.
  • El servicio se puede usar sin servidor.
  • Sabes nombrar las tres razones de separar.
Ver respuestas

1 · Ruta, servicio y repositorio.

2 · En el servicio, que es donde viven las reglas.

3 · Probar sin servidor, cambiar el almacén sin tocar la API y organizar igual todos los recursos.