immagine evocativa di una Hexagonal Architecture

Perché scegliere Hexagonal Architecture (e non fermarsi a Layered o Clean)

Introduzione

Molti sviluppatori iniziano con la classica Layered Architecture e alcuni tentano la Clean Architecture. Ma quando serve testabilità, manutenibilità e flessibilità, la scelta migliore è spesso la Hexagonal Architecture, nota anche come Ports and Adapters.

In questo articolo vedremo:

  • Perché conviene adottarla
  • Come si differenzia dalle altre architetture
  • Un esempio pratico in .NET Core

Cos’è l’Hexagonal Architecture?

L’Hexagonal Architecture organizza l’applicazione in modo da isolare completamente la business logic dal mondo esterno.

Componenti principali:

ComponenteDescrizione
CoreDominio + Application logic, indipendente da tecnologia
PortsInterfacce per comunicare con l’esterno (Input e Output)
AdaptersImplementazioni concrete delle Ports (API, DB, eventi, ecc.)

👉 Il Core non conosce nulla di HTTP, database o framework.
✅ Risultato: codice testabile, manutenibile, riusabile.


Hexagonal vs Layered vs Clean

CaratteristicaLayeredCleanHexagonal ✅
Dominio isolato❌ No✅ Sì✅ Sì
Testabilità❌ Bassa✅ Alta✅ Alta
Complessità architetturale✅ Bassa❌ Alta✅ Media
Estendibilità❌ Limitata✅ Buona✅ Eccellente
Tempo di onboarding✅ Rapido❌ Lento✅ Gestibile

Esempio pratico in .NET Core

Vediamo una semplice API REST per creare e recuperare un ordine, scritta seguendo l’Hexagonal Architecture.

1. Entity e Ports

// Core/Domain/Order.cs
public class Order
{
    public Guid Id { get; }
    public string Product { get; }
    public int Quantity { get; }

    public Order(string product, int quantity)
    {
        Id = Guid.NewGuid();
        Product = product;
        Quantity = quantity;
    }
}

// Core/Ports/Input/ICreateOrderPort.cs
public interface ICreateOrderPort
{
    Guid CreateOrder(string product, int quantity);
}

2. Application Logic (Use Case)

// Core/Application/OrderService.cs
public class OrderService : ICreateOrderPort
{
    private readonly IOrderRepository _repository;

    public OrderService(IOrderRepository repository)
    {
        _repository = repository;
    }

    public Guid CreateOrder(string product, int quantity)
    {
        var order = new Order(product, quantity);
        _repository.Save(order);
        return order.Id;
    }
}

3. Outbound Adapter – Repository InMemory

public class InMemoryOrderRepository : IOrderRepository
{
    private readonly Dictionary<Guid, Order> _store = new();

    public void Save(Order order) => _store[order.Id] = order;
    public Order? FindById(Guid id) => _store.TryGetValue(id, out var o) ? o : null;
}

4. Inbound Adapter – Controller REST

[ApiController]
[Route("api/orders")]
public class OrderController : ControllerBase
{
    private readonly ICreateOrderPort _createOrder;

    public OrderController(ICreateOrderPort createOrder)
    {
        _createOrder = createOrder;
    }

    [HttpPost]
    public IActionResult Create([FromBody] CreateOrderRequest req)
    {
        var id = _createOrder.CreateOrder(req.Product, req.Quantity);
        return CreatedAtAction(nameof(Create), new { id }, new { id });
    }

    public record CreateOrderRequest(string Product, int Quantity);
}

5. Dependency Injection – Program.cs

builder.Services.AddSingleton<IOrderRepository, InMemoryOrderRepository>();
builder.Services.AddSingleton<OrderService>();
builder.Services.AddSingleton<ICreateOrderPort>(sp => sp.GetRequiredService<OrderService>());

✅ Con questa struttura:

  • L’intera logica può essere testata senza HTTP o DB.
  • Il dominio è puro.
  • Puoi aggiungere nuovi adapter (es. un webhook, CLI, consumer Kafka) senza toccare il core.

FAQ – Domande Frequenti

❓ Cos’è l’Hexagonal Architecture in parole semplici?

È un modo di strutturare il codice separando completamente la logica di business da tutto il resto (DB, API, UI), rendendolo più testabile e modulare.

❓ Quali sono i vantaggi dell’Hexagonal Architecture?

  • Maggiore testabilità
  • Isolamento dalle tecnologie
  • Facilità di estensione
  • Maggiore manutenibilità

❓ In cosa si differenzia dalla Clean Architecture?

Sono simili, ma la Hexagonal Architecture è più pragmatica e meno “cerimoniosa”, focalizzata su input/output e sul dominio isolato.

❓ È adatta a microservizi?

Sì, è perfetta: ogni servizio può essere isolato, testabile e facilmente estendibile.

❓ Posso usarla con ASP.NET Core?

Assolutamente sì. È compatibile e consigliata per progetti C#/.NET Core orientati alla manutenibilità.

❓ Posso iniziare in Layered e migrare verso Hexagonal?

Sì. Puoi isolare gradualmente il dominio e introdurre Ports e Adapters senza riscrivere tutto.

❓ Esistono librerie o framework per implementarla?

No, il punto di forza è che non dipende da framework: sei tu a strutturare il codice. Ma puoi usare pattern come DI, MediatR, e automapper per aiutarti.


Conclusione

L’Hexagonal Architecture rappresenta una soluzione moderna e bilanciata per costruire software solido, scalabile e testabile.

✔ È più leggera della Clean Architecture
✔ È più potente della Layered Architecture
✔ È perfetta per team piccoli e medi che puntano alla qualità


Hai un progetto legacy da ristrutturare?

Contattami qui per:

  • Analisi architetturale
  • Refactoring verso Hexagonal
  • Formazione al tuo team
  • Realizzazione di Adapter personalizzati (REST, Kafka, DB, ecc.)

Risorse utili per chi vuole approfondire l’argomento

Ecco una selezione di link ufficiali e autorevoli per approfondire la Hexagonal Architecture, il confronto con la Layered e la Clean Architecture, e best practices in ambito .NET:


Hexagonal Architecture (Ports and Adapters)


Clean Architecture


Layered Architecture


.NET e Architetture Moderne


📌 Bonus – Riferimenti GitHub/Code



Pubblicato

in

da

Tag: