Senior
Τι γνωρίζετε για την αρχιτεκτονική των ports και των adapters;
sobes.tech AI
Απάντηση από AI
Η αρχιτεκτονική των ports και των adapters, γνωστή και ως Hexagonal Architecture, διαχωρίζει τη λογική του πεδίου εφαρμογής (Core) από τις εξωτερικές εξαρτήσεις (διασυνδέσεις χρήστη, βάσεις δεδομένων, εξωτερικές υπηρεσίες).
Βασικές έννοιες:
- Ports: Ορίζουν τα interfaces μέσω των οποίων το Core αλληλεπιδρά με τον εξωτερικό κόσμο. Υπάρχουν δύο τύποι:
- Εισερχόμενα (Driving Ports): Χρησιμοποιούνται από εξωτερικές οντότητες για να καλέσουν τη λειτουργικότητα του Core (π.χ., API interface).
- Εξερχόμενα (Driven Ports): Χρησιμοποιούνται από το Core για να καλέσουν λειτουργικότητα εξωτερικών οντοτήτων (π.χ., interface repository για πρόσβαση σε δεδομένα).
- Adapters: Υλοποιούν τα ports, συνδέοντας το Core με συγκεκριμένες εξωτερικές τεχνολογίες ή frameworks.
- Εισερχόμενοι (Driving Adapters): Υλοποιούν τα εισερχόμενα ports και μετατρέπουν τα εισερχόμενα αιτήματα από το περιβάλλον σε κλήσεις στο Core (π.χ., REST controller).
- Εξερχόμενοι (Driven Adapters): Υλοποιούν τα εξερχόμενα ports και μετατρέπουν τις κλήσεις από το Core για αλληλεπίδραση με το εξωτερικό περιβάλλον (π.χ., υλοποίηση repository για εργασία με συγκεκριμένη βάση δεδομένων).
- Core (Πεδίο εφαρμογής): Περιέχει τη λογική επιχειρηματικών κανόνων της εφαρμογής. Είναι πλήρως απομονωμένο από τις εξωτερικές λεπτομέρειες και αλληλεπιδρά μαζί τους μόνο μέσω των ports.
Πλεονεκτήματα:
- Δοκιμασία: Ο απομονωμένος Core διευκολύνει τη μονάδα δοκιμών της επιχειρηματικής λογικής χωρίς την ανάγκη για mocking σύνθετων εξωτερικών εξαρτήσεων.
- Ευελιξία: Επιτρέπει την εύκολη αντικατάσταση ή προσθήκη νέων εξωτερικών τεχνολογιών (βάσεις δεδομένων, frameworks) χωρίς να αλλάξει το Core. Αρκεί να γραφεί ένας νέος adapter για το υπάρχον port.
- Καθαρός κώδικας: Συμβάλλει στη δημιουργία καθαρότερου και πιο εύκολα συντηρήσιμου κώδικα, εστιάζοντας το Core μόνο στους επιχειρηματικούς κανόνες.
- Διαχωρισμός ευθυνών: Διαχωρίζει σαφώς τις περιοχές ευθύνης.
Σύνδεση με το Frontend:
Στο frontend, η αρχιτεκτονική των ports και adapters εφαρμόζεται για:
- Διαχωρισμός επιχειρηματικής λογικής του component από τις πηγές δεδομένων: Το component αλληλεπιδρά με το "port" (διασύνδεση), το οποίο μπορεί να υλοποιηθεί από διαφορετικά "adapters" (λαμβάνοντας δεδομένα από API, Local Storage, mock δοκιμές κ.λπ.).
- Επεξεργασία εξωτερικών γεγονότων: Τα εισερχόμενα ports μπορούν να αντιπροσωπεύουν χειριστές γεγονότων UI, και τα adapters μετατρέπουν αυτά τα γεγονότα σε κλήσεις στη λογική εσωτερικά.
- Εγκλεισμός της αλληλεπίδρασης με εξωτερικές βιβλιοθήκες: Τα adapters μπορούν να καλύπτουν τις κλήσεις σε τρίτες βιβλιοθήκες (π.χ., βιβλιοθήκη για εργασίες με χάρτες), παρέχοντας στο Core μια απλή και σταθερή διεπαφή.
Παράδειγμα σε JavaScript (σχήμα):
// Παράδειγμα port εξαγωγής (διασύνδεση για λήψη δεδομένων)
class DataGateway {
getData() {
throw new Error("Η μέθοδος getData πρέπει να υλοποιηθεί");
}
}
// Παράδειγμα adapter εξαγωγής (υλοποίηση port για API)
class ApiDataGateway extends DataGateway {
async getData() {
const response = await fetch('/api/data');
return response.json();
}
}
// Παράδειγμα port εισόδου (διασύνδεση για επιχειρηματική λογική)
class BusinessLogicPort {
constructor(dataGateway) {
this.dataGateway = dataGateway;
}
async processData() {
throw new Error("Η μέθοδος processData πρέπει να υλοποιηθεί");
}
}
// Παράδειγμα Core (επιχειρηματική λογική)
class MyBusinessLogic extends BusinessLogicPort {
async processData() {
const data = await this.dataGateway.getData();
// Λογική επεξεργασίας δεδομένων
console.log("Δεδομένα επεξεργάστηκαν:", data);
return data;
}
}
// Παράδειγμα εισερχόμενου adapter (χρήση λογικής στο UI)
async function initApp() {
const apiGateway = new ApiDataGateway(); // Συγκεκριμένος adapter
const businessLogic = new MyBusinessLogic(apiGateway); // Core χρησιμοποιεί port
await businessLogic.processData(); // Εισερχόμενος adapter καλεί Core
}
initApp();