Java 17 + Clean Architecture + Estilo Funcional (con REST listo) 🚀🎧
Un proyecto open-source para modelar una tienda de auriculares con core funcional e inmutable, capas desacopladas y una API REST limpia para integrarte en minutos. Hecho con ❤️ por Laboratorios Terabyte.
TL;DR
- Stack: Java 17, Maven multimódulo (
core
,cli
,rest
), Spring Boot 3.5.x - Arquitectura: dominio funcional (puro) + capas IO (CLI/REST) desacopladas
- API lista:
/api/carts
para crear carrito, agregar items, ver y hacer checkout - Errores tipados: envelope uniforme
ApiResponse<T>
con códigos (NOT_FOUND
,VALIDATION_ERROR
, …) - Tests: slice tests con
@WebMvcTest
y@MockitoBean
(sin deprecations) - Repo: github.com/darklatiz/TiendaFuncional
¿Qué es y por qué existe?
Tienda Funcional es un proyecto de ejemplo/plantilla para enseñar y practicar:
- Dominio funcional (reglas puras y componibles, inmutabilidad, VOs).
- Separación estricta entre negocio y IO (CLI/REST, seguridad, serialización).
- Contratos claros (envelope de respuesta, manejo de errores, validación).
- Pruebas reales con slices de Spring (sin levantar todo el contexto).
La idea es que puedas enchufar el core a cualquier interfaz (CLI, REST, mensajería) sin tocar reglas. Así enseñamos a diseñar “como en la chamba” y no solo “para que compile”.
Arquitectura (multimódulo)
TiendaFuncional/
├─ core/ # Dominio y reglas puras (funciones, VOs, orquestación de cálculo)
├─ cli/ # Interfaz de consola (usa core)
└─ rest/ # API HTTP (Spring Boot) que delega todo al core
Highlights
- Core inmutable y determinista → tests fáciles, cero side-effects.
- Reglas Open/Closed → agregas promociones/condiciones sin romper lo existente.
- REST delgadito → valida, mapea DTOs y delega al servicio del core.
- Errores tipados + handler global → devuelves 404/400/422/500 con contrato consistente.
API REST (carritos)
1. Crear carrito
POST /api/carts → 201 Created
{ "cartId": "e2f4c6a4-9b7e-4e2a-9e0a-6d0d3b8f3c1a" }
- Agregar/Reemplazar item
PUT /api/carts/{id}/items
{ "sku": "SONY-1000XM5", "quantity": 2 }
Respuesta 200 OK
: lista actualizada de líneas (si hay mismo sku
, se reemplaza).
- Ver carrito
GET /api/carts/{id}
→200 OK
con array de líneas. - Checkout
POST /api/carts/{id}/checkout
→200 OK
Calcula totales con el core y limpia el carrito.
Errores (envelope estándar):
{
"success": false,
"data": null,
"error": { "code": "NOT_FOUND", "message": "Cart not found: <id>", "details": null },
"meta": { "requestId": "...", "timestamp": "..." }
}
Además: VALIDATION_ERROR
(422) con fieldErrors[]
, MALFORMED_JSON
(400), INTERNAL_ERROR
(500).
Build & Run (rápido)
# compilar todo
mvn -q -DskipTests clean package
# correr CLI (fat-jar)
java -jar cli/target/cli-*-jar-with-dependencies.jar
# correr REST
mvn -q -DskipTests -pl rest -am spring-boot:run
# o
java -jar rest/target/rest-*.jar
cURL demo
# Crear carrito
curl -s -X POST http://localhost:8080/api/carts | jq
# Agregar item
curl -s -X PUT http://localhost:8080/api/carts/<cartId>/items \
-H 'Content-Type: application/json' \
-d '{"sku":"SONY-1000XM5","quantity":2}' | jq
# Ver carrito
curl -s http://localhost:8080/api/carts/<cartId> | jq
# Checkout
curl -s -X POST http://localhost:8080/api/carts/<cartId>/checkout | jq
Testing (sin deprecations)
- Controller slice:
@WebMvcTest(CartController.class)
+@MockitoBean
(reemplaza@MockBean
deprecado). - Verificamos 201/200/404, invocación a
CartService.checkout(...)
y borrado de carrito. - Próximos: validar shape exacto de
CartLine
/CartResult
y casos de validación (422).
Seguridad (opcional)
- Basic Auth para demos rápidas (roles por endpoint).
- OAuth2 Resource Server (JWT) para escenarios enterprise.
El core no cambia: solo ajustas el mecanismo en el módulo REST.
Roadmap corto
- OpenAPI/Swagger con ejemplos reales.
- Matriz de reglas configurable (YAML/DB) para activar promos sin redeploy.
- Métricas (Prometheus) y logging estructurado (ELK).
- Más tests de integración y validación.
¿Para quién es?
- Devs Java que quieren practicar diseño limpio y funcional.
- Instructores que necesitan un laboratorio realista (CI/CD, métricas, seguridad).
- Equipos que buscan un esqueleto reusable para e-commerce pequeño/mediano.
Call to action
Échale un 👀, corre los comandos y dime qué te gustaría ver en la siguiente versión:
- ⭐ Dale star al repo: TiendaFuncional
- Crea un issue con ideas de reglas/promos
- Manda un PR (guía en el README)
Hashtags
#Java17 #SpringBoot #CleanArchitecture #Hexagonal #FunctionalProgramming #DomainDrivenDesign #RESTAPI #Maven #OpenSource #LaboratoriosTerabyte #CDMX #Testing #TiendaFuncional 💻🧪🧱🚀