esedark
arquitectura Laravel en un editor de código

laravel / arquitectura / actions / services

Actions, Services y Repositories en Laravel: cuándo usar cada uno

Estos patrones resuelven problemas distintos. Úsalos para aclarar responsabilidades, no para convertir una aplicación sencilla en un laberinto.

Laravel permite colocar lógica en controladores, modelos, jobs y listeners. Esa velocidad ayuda hasta que la misma operación aparece en HTTP, un worker y un comando. Actions, Services y Repositories crean límites limpios solo cuando cada abstracción tiene una función clara.

La regla de decisión corta

  • Action: un caso de uso con entrada y resultado explícitos, como aprobar una factura.
  • Service: una capacidad cohesionada compartida, como precios o generación de documentos.
  • Repository: un límite ante persistencia compleja o fuentes externas, no cada llamada Eloquent.

El controlador traduce HTTP, invoca el caso y devuelve la respuesta. Deja validación en Form Requests y autorización en policies o comprobaciones explícitas para que la operación sea reutilizable sin HTTP.

Actions: una operación de negocio

Las Actions encajan con verbos como CreateSubscription o CancelOrder. Usa entrada tipada, propiedad clara de la transacción y un resultado útil. No extraigas cada actualización de tres líneas: hazlo cuando reglas, efectos, varios consumidores o pruebas independientes lo justifiquen.

Services: una capacidad estable

Un Service agrupa comportamiento relacionado más amplio que un comando: impuestos, pagos, PDF o matching. Mantén su API pequeña. Un OrderService con veinte métodos inconexos suele ser un controlador disfrazado. Los adaptadores estrechos de proveedores facilitan fallos y pruebas de contrato.

Este enfoque complementa cómo estructurar un Laravel grande sin caos.

Repositories: límites reales de persistencia

Eloquent ya es una interfaz expresiva. Un repositorio aporta valor con consultas complejas reutilizables, varios backends, API remotas, agregados o un dominio desacoplado de Eloquent. Aporta poco si solo reenvía find() y save(). Para filtros de lectura, usa scopes o query objects enfocados.

Transacciones, colas y trazabilidad

El caso de uso debe controlar la transacción. Lanza jobs después del commit si necesitan datos nuevos. Haz idempotentes las llamadas externas cuando sea viable, añade IDs de correlación, limita reintentos y elimina secretos y datos personales de logs. Evita esperar una API lenta dentro de una transacción.

Errores comunes

  • crear interfaces y repositorios para cada modelo
  • meter validación y autorización en Services genéricos
  • ocultar dependencias con helpers estáticos
  • construir servicios gigantes agrupados por modelo
  • abrir transacciones en varias capas
  • lanzar jobs antes del commit
  • mockear cada clase en vez de probar comportamiento
  • adoptar patrones sin documentar su objetivo

Checklist práctico

  • nombra el caso y su responsable
  • define entradas, salidas y fallos
  • separa transporte y negocio
  • usa Actions para verbos importantes
  • usa Services para capacidades cohesionadas
  • añade Repositories solo ante límites reales
  • define transacciones y reintentos
  • registra correlación sin contenido sensible
  • prueba reglas e integraciones críticas
  • elimina abstracciones que solo reenvían llamadas

Cuándo tiene sentido contratar a una persona técnica

Un perfil Laravel senior ayuda cuando los cambios rompen controladores, jobs y comandos, nadie controla las transacciones o no se entiende la dirección de dependencias. Empieza con evidencias: consulta cómo auditar Laravel antes de invertir en refactor.

Conclusión

Las Actions describen qué hace la aplicación, los Services aportan capacidades reutilizables y los Repositories aíslan datos solo cuando ofrece valor. Para límites prácticos, revisa mis servicios técnicos o contacta conmigo.