0

Arquitectura de Software con C# 20: ¿Qué es Vertical Slice Architecture? (Diferencias clave)

Introducción a la clase

Vertical Slice Architecture organiza la aplicación por funcionalidades en lugar de capas horizontales, permitiendo que cada módulo sea independiente y contenga todo lo necesario para operar.

En esta clase aprenderás:

  • Qué es Vertical Slice Architecture y cómo funciona
  • Diferencias con Clean Architecture y Hexagonal Architecture
  • Ventajas y desventajas de este enfoque
  • Un ejemplo básico en C#

¿Qué es Vertical Slice Architecture?

En lugar de organizar el código en capas horizontales como Presentación, Aplicación, Dominio e Infraestructura, cada funcionalidad es un módulo independiente (Slice).

Estructura tradicional en capas:

Presentación (Controladores, UI)
--------------------------------
Aplicación (Casos de Uso, Servicios)
--------------------------------
Dominio (Entidades, Value Objects)
--------------------------------
Infraestructura (Repositorios, DB)

Estructura de Vertical Slice Architecture:

Crear Pedido (Controller, UseCase, DB)
--------------------------------------
Obtener Pedido (Controller, UseCase, DB)
--------------------------------------
Cancelar Pedido (Controller, UseCase, DB)

Diferencias con Clean Architecture y Hexagonal Architecture

  • Clean Architecture → Separa la aplicación en capas concéntricas con reglas estrictas de dependencia.
  • Hexagonal Architecture → Usa Puertos y Adaptadores para desacoplar el dominio de la infraestructura.
  • Vertical Slice Architecture → Divide la aplicación en módulos funcionales independientes.
CaracterísticaClean ArchitectureHexagonal ArchitectureVertical Slice Architecture
OrganizaciónCapas horizontalesNúcleo + AdaptadoresFuncionalidades independientes
AcoplamientoBajoMuy bajoCasi inexistente
EscalabilidadAltaAltaMuy alta
MantenibilidadAltaAltaMuy alta
ComplejidadMedia-AltaMedia-AltaMedia-Baja
Mejor paraAplicaciones grandes y manteniblesAplicaciones con múltiples integracionesAplicaciones modulares

Ventajas de Vertical Slice Architecture

  • Separación total de funcionalidades → Cada Slice es independiente.
  • Facilita el mantenimiento → Modificar una funcionalidad no afecta otras.
  • Escalabilidad modular → Se pueden agregar nuevas funcionalidades sin tocar el resto del código.
  • Menos código innecesario → Evita capas de abstracción innecesarias.
  • Ideal para microservicios → Cada Slice puede convertirse en un microservicio.

Desventajas de Vertical Slice Architecture

  • Duplicación de código → Algunas funcionalidades pueden repetirse en distintos Slices.
  • No es ideal para proyectos pequeños → Puede ser más simple usar Clean Architecture.
  • Requiere una buena organización → Si no se maneja bien, puede volverse difícil de entender.

Ejemplo en C#: Implementando Vertical Slice Architecture

Cada Slice tendrá:

  • Un Handler (Caso de Uso)
  • Un Repositorio
  • Un Controlador

Estructura del código:

/PedidosAPI
│── /Features
│   ├── /CrearPedido
│   │   ├── CrearPedidoCommand.cs
│   │   ├── CrearPedidoHandler.cs
│   │   ├── PedidoRepository.cs
│   │   ├── PedidoController.cs
│   ├── /ObtenerPedido
│   │   ├── ObtenerPedidoQuery.cs
│   │   ├── ObtenerPedidoHandler.cs
│   │   ├── PedidoRepository.cs
│   │   ├── PedidoController.cs
│── Program.cs
│── appsettings.json

Paso 1: Implementar el Slice «Crear Pedido»

Definir el comando (Request DTO)

public class CrearPedidoCommand
{
    public string Cliente { get; set; }
    public List<string> Productos { get; set; }
}

Implementar el Handler (Caso de Uso)

public class CrearPedidoHandler
{
    private readonly PedidoRepository _repository;

    public CrearPedidoHandler(PedidoRepository repository)
    {
        _repository = repository;
    }

    public void Handle(CrearPedidoCommand command)
    {
        var pedido = new Pedido(0, command.Cliente);
        
        foreach (var producto in command.Productos)
        {
            pedido.AgregarProducto(new Producto(0, producto, 100)); // Precio por defecto
        }

        _repository.Guardar(pedido);
    }
}

Implementar el Adaptador de Persistencia (Repositorio)

public class PedidoRepository
{
    private readonly List<Pedido> _pedidos = new List<Pedido>();

    public void Guardar(Pedido pedido)
    {
        _pedidos.Add(pedido);
    }
}

Implementar el Controlador REST

[ApiController]
[Route("api/pedidos")]
public class PedidoController : ControllerBase
{
    private readonly CrearPedidoHandler _crearPedidoHandler;

    public PedidoController(CrearPedidoHandler crearPedidoHandler)
    {
        _crearPedidoHandler = crearPedidoHandler;
    }

    [HttpPost]
    public IActionResult CrearPedido([FromBody] CrearPedidoCommand command)
    {
        _crearPedidoHandler.Handle(command);
        return Ok("Pedido creado exitosamente");
    }
}

Paso 2: Implementar el Slice «Obtener Pedido»

Definir la Query

public class ObtenerPedidoQuery
{
    public int Id { get; set; }
}

Implementar el Handler (Caso de Uso)

public class ObtenerPedidoHandler
{
    private readonly PedidoRepository _repository;

    public ObtenerPedidoHandler(PedidoRepository repository)
    {
        _repository = repository;
    }

    public Pedido Handle(ObtenerPedidoQuery query)
    {
        return _repository.ObtenerPorId(query.Id);
    }
}

Implementar el Controlador REST

[ApiController]
[Route("api/pedidos")]
public class PedidoController : ControllerBase
{
    private readonly ObtenerPedidoHandler _obtenerPedidoHandler;

    public PedidoController(ObtenerPedidoHandler obtenerPedidoHandler)
    {
        _obtenerPedidoHandler = obtenerPedidoHandler;
    }

    [HttpGet("{id}")]
    public IActionResult ObtenerPedido(int id)
    {
        var pedido = _obtenerPedidoHandler.Handle(new ObtenerPedidoQuery { Id = id });
        return pedido != null ? Ok(pedido) : NotFound();
    }
}

Resumen de la Clase

  • Vertical Slice Architecture organiza el código por funcionalidad en lugar de capas.
  • Cada funcionalidad es un Slice independiente con su propia lógica.
  • Facilita la modularidad y el desacoplamiento extremo.
  • Ideal para sistemas que crecen rápidamente o para microservicios.

Próximo paso

En la siguiente clase veremos cómo separar las Features en lugar de las capas y cómo usar MediatR en Vertical Slice Architecture.

Fernando Sonego

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *