Sobes.tech
Senior

Cosa sai dell'architettura di porte e adattatori?

sobes.tech AI

Risposta dell'AI

L'architettura dei porti e degli adattatori, nota anche come Architettura Esagonale (Hexagonal Architecture), separa la logica di dominio dell'applicazione (Core) dalle dipendenze esterne (interfacce utente, database, servizi esterni).

Concetti principali:

  • Porti: Definiscono le interfacce attraverso le quali il Core interagisce con il mondo esterno. I porti sono di due tipi:
    • In entrata (Driving Ports): Utilizzati da entità esterne per invocare le funzionalità del Core (ad esempio, interfaccia API).
    • In uscita (Driven Ports): Utilizzati dal Core per invocare funzionalità di entità esterne (ad esempio, interfaccia di repository per l'accesso ai dati).
  • Adattatori: Implementano i porti, collegando il Core a tecnologie o framework esterni specifici.
    • In entrata (Driving Adapters): Implementano i porti in entrata e trasformano le richieste esterne in chiamate al Core (ad esempio, controller REST).
    • In uscita (Driven Adapters): Implementano i porti in uscita e trasformano le chiamate dal Core per interagire con l'ambiente esterno (ad esempio, implementazione di repository per lavorare con un database specifico).
  • Core (Dominio): Contiene la logica di business dell'applicazione. È completamente isolato dai dettagli esterni e interagisce con essi solo attraverso i porti.

Vantaggi:

  • Testabilità: L'isolamento del Core facilita i test unitari della logica di business senza la necessità di simulare dipendenze esterne complesse.
  • Flessibilità: Permette di sostituire o aggiungere facilmente nuove tecnologie esterne (database, framework) senza modificare il Core. Basta scrivere un nuovo adattatore per un porto esistente.
  • Codice pulito: Favorisce la creazione di un codice più pulito e manutenibile, concentrandosi solo sulle regole di business.
  • Separazione delle responsabilità: Divide chiaramente le aree di responsabilità.

Relazione con il Frontend:

Nel frontend, l'architettura dei porti e degli adattatori si applica per:

  • Separare la logica di business dal componente dalle fonti di dati: Il componente interagisce con un "porto" (interfaccia), che può essere implementato da diversi "adattatori" (che recuperano dati da API, Storage Locale, mock, ecc.).
  • Gestione di eventi esterni: I porti in entrata possono rappresentare gestori di eventi UI, e gli adattatori trasformano questi eventi in chiamate alla logica interna.
  • Incapsulamento dell'interazione con librerie esterne: Gli adattatori possono avvolgere le chiamate a librerie di terze parti (ad esempio, librerie per lavorare con le mappe), fornendo al Core un'interfaccia semplice e stabile.

Esempio in JavaScript (schema):

// Esempio di porta in uscita (interfaccia per ottenere dati)
class DataGateway {
  getData() {
    throw new Error("Il metodo getData deve essere implementato");
  }
}

// Esempio di adattatore in uscita (implementazione della porta per API)
class ApiDataGateway extends DataGateway {
  async getData() {
    const response = await fetch('/api/data');
    return response.json();
  }
}

// Esempio di porta in entrata (interfaccia per la logica di business)
class BusinessLogicPort {
  constructor(dataGateway) {
    this.dataGateway = dataGateway;
  }

  async processData() {
    throw new Error("Il metodo processData deve essere implementato");
  }
}

// Esempio di Core (logica di business)
class MyBusinessLogic extends BusinessLogicPort {
  async processData() {
    const data = await this.dataGateway.getData();
    // Logica di elaborazione dei dati
    console.log("Dati elaborati:", data);
    return data;
  }
}

// Esempio di adattatore in entrata (uso in UI)
async function initApp() {
  const apiGateway = new ApiDataGateway(); // Adattatore concreto
  const businessLogic = new MyBusinessLogic(apiGateway); // Core usa il port
  await businessLogic.processData(); // L'adattatore in entrata chiama il Core
}

initApp();