Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Adattarsi al cambiamento
I sistemi software tendono a diventare complicati. Uno dei motivi potrebbero essere le frequenti modifiche ai requisiti aziendali e il poco tempo necessario per adattare di conseguenza l'architettura del software. Un altro motivo potrebbe essere un investimento insufficiente per configurare l'architettura software all'inizio del progetto per adattarla ai frequenti cambiamenti. Qualunque sia la ragione, un sistema software potrebbe diventare complicato al punto che è quasi impossibile apportare modifiche. Pertanto, è importante creare un'architettura software gestibile sin dall'inizio del progetto. Una buona architettura software può adattarsi facilmente ai cambiamenti.
Questa sezione spiega come progettare applicazioni gestibili utilizzando un'architettura esagonale che si adatta facilmente a requisiti non funzionali o aziendali.
Adattamento ai nuovi requisiti non funzionali mediante porte e adattatori
Come elemento centrale dell'applicazione, il modello di dominio definisce le azioni necessarie dal mondo esterno per soddisfare i requisiti aziendali. Queste azioni sono definite tramite astrazioni, chiamate porte. Queste porte sono implementate da adattatori separati. Ogni adattatore è responsabile dell'interazione con un altro sistema. Ad esempio, potresti avere un adattatore per il repository del database e un altro adattatore per interagire con un'API di terze parti. Il dominio non è a conoscenza dell'implementazione dell'adattatore, quindi è facile sostituire un adattatore con un altro. Ad esempio, l'applicazione potrebbe passare da un database SQL a un database NoSQL. In questo caso, è necessario sviluppare un nuovo adattatore per implementare le porte definite dal modello di dominio. Il dominio non dipende dal repository del database e utilizza le astrazioni per interagire, quindi non sarebbe necessario modificare nulla nel modello di dominio. Pertanto, l'architettura esagonale si adatta facilmente ai requisiti non funzionali.
Adattamento ai nuovi requisiti aziendali utilizzando comandi e gestori di comandi
Nella classica architettura a strati, il dominio dipende dal livello di persistenza. Se si desidera modificare il dominio, è necessario modificare anche il livello di persistenza. In confronto, nell'architettura esagonale, il dominio non dipende da altri moduli del software. Il dominio è il fulcro dell'applicazione e tutti gli altri moduli (porte e adattatori) dipendono dal modello di dominio. Il dominio utilizza il principio di inversione delle dipendenze per comunicare con il mondo esterno attraverso le porte. Il vantaggio dell'inversione delle dipendenze è che puoi modificare liberamente il modello di dominio senza aver paura di rompere altre parti del codice. Poiché il modello di dominio riflette il problema aziendale che state cercando di risolvere, l'aggiornamento del modello di dominio per adattarlo alle mutevoli esigenze aziendali non è un problema.
Quando si sviluppa un software, la separazione delle preoccupazioni è un principio importante da seguire. Per ottenere questa separazione, è possibile utilizzare uno schema di comando leggermente modificato. Si tratta di un modello di progettazione comportamentale in cui tutte le informazioni necessarie per completare un'operazione sono incapsulate in un oggetto di comando. Queste operazioni vengono quindi elaborate dai gestori di comandi. I gestori di comandi sono metodi che ricevono un comando, alterano lo stato del dominio e quindi restituiscono una risposta al chiamante. È possibile utilizzare diversi client, ad esempio API sincrone o code asincrone, per eseguire comandi. Ti consigliamo di utilizzare comandi e gestori di comandi per ogni operazione sul dominio. Seguendo questo approccio, è possibile aggiungere nuove funzionalità introducendo nuovi comandi e gestori di comandi, senza modificare la logica aziendale esistente. Pertanto, l'utilizzo di uno schema di comando semplifica l'adattamento ai nuovi requisiti aziendali.
Disaccoppiamento dei componenti utilizzando la facciata di servizio o il modello CQRS
Nell'architettura esagonale, gli adattatori primari sono responsabili dell'accoppiamento approssimativo delle richieste di lettura e scrittura in entrata dai client al dominio. Esistono due modi per ottenere questo accoppiamento libero: utilizzando uno schema di facciata del servizio o utilizzando il modello di segregazione della responsabilità delle query di comando (CQRS).
Lo schema della facciata del servizio fornisce un'interfaccia frontale per servire clienti come il livello di presentazione o un microservizio. Una facciata di servizio offre ai clienti diverse operazioni di lettura e scrittura. È responsabile del trasferimento delle richieste in arrivo al dominio e della mappatura della risposta ricevuta dal dominio ai clienti. L'utilizzo di una facciata di servizio è facile per i microservizi che hanno un'unica responsabilità con diverse operazioni. Tuttavia, quando si utilizza la facciata di servizio, è più difficile seguire una responsabilità unica e principi di apertura e chiusura. Il principio della responsabilità unica stabilisce che ogni modulo dovrebbe avere la responsabilità di una sola funzionalità del software. Il principio aperto/chiuso stabilisce che il codice deve essere aperto all'estensione e chiuso alle modifiche. Man mano che la facciata del servizio si estende, tutte le operazioni vengono raccolte in un'unica interfaccia, in essa vengono incapsulate più dipendenze e più sviluppatori iniziano a modificare la stessa facciata. Pertanto, consigliamo di utilizzare una facciata del servizio solo se è chiaro che il servizio non si estenderebbe molto durante lo sviluppo.
Un altro modo per implementare gli adattatori primari nell'architettura esagonale consiste nell'utilizzare il pattern CQRS, che separa le operazioni di lettura e scrittura utilizzando interrogazioni e comandi. Come spiegato in precedenza, i comandi sono oggetti che contengono tutte le informazioni necessarie per modificare lo stato del dominio. I comandi vengono eseguiti con i metodi del gestore dei comandi. Le interrogazioni, d'altra parte, non alterano lo stato del sistema. Il loro unico scopo è restituire i dati ai clienti. Nel modello CQRS, i comandi e le query sono implementati in moduli separati. Ciò è particolarmente vantaggioso per i progetti che seguono un'architettura basata sugli eventi, poiché un comando potrebbe essere implementato come un evento elaborato in modo asincrono, mentre una query può essere eseguita in modo sincrono utilizzando un'API. Una query può anche utilizzare un database diverso ottimizzato per tale scopo. Lo svantaggio del modello CQRS è che l'implementazione richiede più tempo rispetto a una facciata di servizio. Ti consigliamo di utilizzare il modello CQRS per i progetti che prevedi di scalare e mantenere a lungo termine. I comandi e le interrogazioni forniscono un meccanismo efficace per applicare il principio di responsabilità unica e sviluppare software vagamente associati, specialmente in progetti su larga scala.
Il CQRS offre grandi vantaggi a lungo termine, ma richiede un investimento iniziale. Per questo motivo, consigliamo di valutare attentamente il progetto prima di decidere di utilizzare il modello CQRS. Tuttavia, è possibile strutturare l'applicazione utilizzando comandi e gestori di comandi fin dall'inizio senza separare le operazioni di lettura/scrittura. Questo ti aiuterà a rifattorizzare facilmente il tuo progetto per il CQRS se deciderai di adottare tale approccio in un secondo momento.
Scalabilità organizzativa
Una combinazione di architettura esagonale, progettazione basata sul dominio e (facoltativamente) CQRS consente all'organizzazione di scalare rapidamente il prodotto. Secondo la legge di Conway, le architetture software tendono ad evolversi per riflettere le strutture di comunicazione di un'azienda. Questa osservazione ha storicamente avuto connotazioni negative, perché le grandi organizzazioni spesso strutturano i propri team in base a competenze tecniche come database, bus di servizio aziendali e così via. Il problema di questo approccio è che lo sviluppo di prodotti e funzionalità comporta sempre problemi trasversali, come la sicurezza e la scalabilità, che richiedono una comunicazione costante tra i team. La strutturazione dei team in base alle caratteristiche tecniche crea inutili silos nell'organizzazione, il che si traduce in comunicazioni scadenti, mancanza di proprietà e perdita di vista del quadro generale. Alla fine, questi problemi organizzativi si riflettono nell'architettura del software.
La manovra inversa di Conway, d'altra parte, definisce la struttura organizzativa basata su domini che promuovono l'architettura del software. Ad esempio, ai team interfunzionali viene assegnata la responsabilità di un insieme specifico di contesti limitati, che vengono identificati utilizzando DDD e event storming. Questi contesti limitati potrebbero riflettere caratteristiche molto specifiche del prodotto. Ad esempio, il team dell'account potrebbe essere responsabile del contesto di pagamento. Ogni nuova funzionalità viene assegnata a un nuovo team con responsabilità altamente coese e vagamente collegate, in modo che possano concentrarsi solo sulla distribuzione di quella funzionalità e ridurre i tempi di commercializzazione. I team possono essere scalati in base alla complessità delle funzionalità, in modo da assegnare funzionalità complesse a più ingegneri.