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();