Vertical Slice Architecture
Idea y grado de estandarización
Vertical Slice Architecture organiza código principalmente alrededor de un caso de uso o feature, buscando concentrar lo que cambia junto. El término tiene menor estandarización académica que Layered o Hexagonal; sus límites varían entre prácticas. Aquí se usa con este sentido explícito, sin convertir una biblioteca o una plantilla de directorios en definición universal.
Jimmy Bogard describe organizar por requests, reducir coupling entre slices y permitir decisiones distintas para resolver cada petición. Su motivación incluye problemas observados con capas rígidas y abstracciones innecesarias. Es la perspectiva de su artículo de 2018, no una prueba de que toda arquitectura concéntrica tenga esos problemas.
Cohesión por caso de uso
En este ejemplo propio, una organización principalmente horizontal separa:
Controllers/
Services/
Repositories/
Models/Cambiar cómo se aprueba una solicitud puede exigir recorrer todos esos grupos. Una organización por feature puede acercar las piezas:
Features/
├── ApproveRequest/
│ ├── Request
│ ├── Handler
│ ├── Validation
│ └── Persistence interaction
├── RejectRequest/
└── GetRequest/Los nombres son ilustrativos. No se requieren cuatro tipos por slice ni un handler para cada clase. La pregunta es qué unidad concentra el comportamiento que evoluciona como caso de uso.
La localidad ayuda a entender qué debe cambiar y a quién pertenece. No garantiza que cada nueva feature agregue solamente archivos: una regla común puede exigir modificar varios recorridos. Tampoco convierte cada slice en un servicio desplegable; la frontera editorial del código puede ser local.
Independencia de decisiones y límites
En nuestro ejemplo, GetRequest puede usar una consulta simple y ApproveRequest necesita validar una transición con comportamiento de dominio. No hay obligación de crear la misma cadena Controller→Service→Repository para ambos.
Esa libertad requiere límites explícitos. Una slice no debería escribir datos de otro módulo o omitir una política de seguridad porque necesita menos clases. Podemos mantener contratos de ownership, autorización y consistencia compartidos sin imponer la misma implementación a todos los casos de uso.
Un límite de feature tampoco garantiza separación transaccional. Dos operaciones que afectan la misma invariante necesitan una regla común y pruebas de concurrencia apropiadas. Distribuir sus archivos reduce cierta navegación, pero no elimina la coordinación que exige el negocio.
Duplicación y abstracción
Dos validaciones parecidas pueden ser reglas independientes que cambiarán por razones diferentes. Extraerlas inmediatamente a un servicio común puede introducir change coupling. En cambio, duplicar la regla «solo el responsable autorizado puede aprobar» entre slices puede crear divergencias peligrosas si representa una única política del dominio.
El criterio práctico es preguntar si se comparte una intención estable o solo una forma de código parecida. Extraer una abstracción cuando esa intención es clara y su contrato puede expresarse suele ser más útil que diseñar una capa genérica antes de observar casos reales.
Se puede compartir infraestructura, composición, telemetría y mecanismos de transporte. También es razonable conservar reglas de negocio comunes en un modelo de dominio. Las slices no necesitan copiar clientes, seguridad o manejo de transacciones para mantener cohesión.
CQRS y MediatR son decisiones adicionales
Vertical Slice no es CQRS. Bogard relaciona su enfoque con separar commands y queries en su experiencia. Organizar una feature no obliga a adoptar esa separación de modelos; tampoco implica event sourcing, bases distintas o consistencia eventual. Esas son decisiones adicionales, que no se desarrollan como nuevos documentos aquí.
Vertical Slice no es MediatR. La documentación oficial de MediatR describe una biblioteca .NET para mensajería y dispatching en proceso. Puede seleccionar un handler para una petición; una llamada directa o mecanismos de otro lenguaje también pueden conectar la feature. Instalar la biblioteca no establece cohesión, ownership ni una política de dependencias.
Comparación con Layered
code-partitioning-strategies conecta organización por feature, módulo y responsabilidad técnica. Una carpeta por caso de uso no prueba esta arquitectura: debe conservar cohesión y reglas de dependencia efectivas.
layered-architecture suele agrupar por responsabilidad técnica; Vertical Slice prioriza el eje de cambio del caso de uso. Ninguna organización por sí sola responde todas las preguntas.
En nuestro ejemplo, capas horizontales pueden ofrecer un límite estable para almacenamiento común, pero una feature toca varias carpetas. Una slice puede acercar ese cambio, pero repetir decisiones de persistencia o seguridad si faltan fronteras claras. Conviene examinar qué cambios reales se localizan y cuáles siguen atravesando unidades compartidas. modifiability evalúa esa localidad mediante costo, propagación y evidencia del cambio concreto, sin deducirla de carpetas verticales.
Vertical Slice no elimina infraestructura, capas conceptuales, domain model o preocupaciones transversales. La comparación útil analiza dónde reside cada responsabilidad y quién puede depender de ella.
Composición con un núcleo protegido
Una variante posible diseñada para este ejemplo es:
Application/
├── ApproveRequest/
├── RejectRequest/
└── GetRequest/
Domain/
└── Approval policies
Infrastructure/
└── AdaptersLas features pueden consumir contratos interiores y reglas compartidas mientras los adaptadores concretos permanecen afuera. Así pueden coexistir con ports-and-adapters o principios de clean-architecture. Es una composición razonada del Atlas; no se atribuye a Bogard como su recomendación universal. Su crítica a capas rígidas merece conservarse cuando se evalúa el costo de esa combinación.
En un modular-monolith, las slices pueden vivir dentro de cada módulo, respetando sus contratos. En microservices, un servicio puede agrupar sus casos de uso así sin convertirse en un servicio por feature. internal-structure ayuda a distinguir estos ejes.
La revisión debe comprobar ejemplos de cambio, invariantes compartidas, dependencies permitidas y pruebas de comportamiento. Una jerarquía Features bonita no compensa reglas duplicadas que divergen o accesos externos que violan la frontera elegida.