Senior
Wat weet u over de architectuur van ports en adapters?
sobes.tech AI
Antwoord van AI
Hexagonale Architectuur (ook bekend als Ports en Adapters Architectuur) scheidt de domeinlogica van de applicatie (Core) van externe afhankelijkheden (gebruikersinterfaces, databases, externe services).
Belangrijke concepten:
- Poorten: Definiëren de interfaces waarmee de Core communiceert met de buitenwereld. Poorten zijn van twee typen:
- Inkomend (Driving Ports): Gebruikt door externe entiteiten om de functionaliteit van de Core aan te roepen (bijvoorbeeld API-interface).
- Uitgaand (Driven Ports): Gebruikt door de Core om functionaliteiten van externe entiteiten aan te roepen (bijvoorbeeld repository-interface voor gegevenstoegang).
- Adapters: Implementeren de poorten en verbinden de Core met specifieke externe technologieën of frameworks.
- Inkomend (Driving Adapters): Implementeren de inkomende poorten en transformeren externe verzoeken naar calls naar de Core (bijvoorbeeld REST-controller).
- Uitgaand (Driven Adapters): Implementeren de uitgaande poorten en transformeren calls van de Core om te communiceren met de externe omgeving (bijvoorbeeld implementatie van repository voor werken met een specifieke database).
- Core (Domein): Bevat de bedrijfslogica van de applicatie. Het is volledig geïsoleerd van externe details en communiceert alleen via poorten.
Voordelen:
- Testbaarheid: De isolatie van de Core maakt het eenvoudiger om eenheidstests van de bedrijfslogica uit te voeren zonder complexe externe afhankelijkheden te mocken.
- Flexibiliteit: Maakt het gemakkelijk om nieuwe externe technologieën (databases, frameworks) te vervangen of toe te voegen zonder de Core te wijzigen. Het schrijven van een nieuwe adapter voor een bestaande poort is voldoende.
- Schone code: Bevordert het schrijven van schonere en onderhoudbare code, gericht op de bedrijfsregels.
- Verantwoordelijkheden scheiding: Verdeelt duidelijk de verantwoordelijkheidsgebieden.
Relatie met Frontend:
In de frontend wordt de architectuur van poorten en adapters toegepast om:
- De bedrijfslogica van de component te scheiden van de gegevensbronnen: De component communiceert met een "poort" (interface), die door verschillende "adapters" (die gegevens ophalen uit API, Local Storage, mocks, etc.) geïmplementeerd kan worden.
- Afhandeling van externe gebeurtenissen: Inkomende poorten kunnen UI-gebeurtenishandlers vertegenwoordigen, en adapters transformeren deze gebeurtenissen in calls naar de interne logica.
- Encapsulatie van de interactie met externe bibliotheken: Adapters kunnen de oproepen naar externe bibliotheken kapselen (bijvoorbeeld, bibliotheek voor werken met kaarten), en zo de Core een eenvoudige en stabiele interface bieden.
Voorbeeld in JavaScript (schema):
// Voorbeeld van een uitgaande poort (interface voor gegevensophaling)
class DataGateway {
getData() {
throw new Error("De getData-methode moet worden geïmplementeerd");
}
}
// Voorbeeld van een uitgaande adapter (implementatie van de poort voor API)
class ApiDataGateway extends DataGateway {
async getData() {
const response = await fetch('/api/data');
return response.json();
}
}
// Voorbeeld van een inkomende poort (interface voor bedrijfslogica)
class BusinessLogicPort {
constructor(dataGateway) {
this.dataGateway = dataGateway;
}
async processData() {
throw new Error("De processData-methode moet worden geïmplementeerd");
}
}
// Voorbeeld van Core (bedrijfslogica)
class MyBusinessLogic extends BusinessLogicPort {
async processData() {
const data = await this.dataGateway.getData();
// Logica voor gegevensverwerking
console.log("Verwerkte gegevens:", data);
return data;
}
}
// Voorbeeld van een inkomende adapter (gebruik in UI)
async function initApp() {
const apiGateway = new ApiDataGateway(); // Concrete adapter
const businessLogic = new MyBusinessLogic(apiGateway); // Core gebruikt de poort
await businessLogic.processData(); // Inkomende adapter roept Core aan
}
initApp();