CodeGym/Java Course/Modulo 3/Come allentare l'accoppiamento tra i moduli software

Come allentare l'accoppiamento tra i moduli software

Disponibile

8.1 La decomposizione è tutto

Per chiarezza, un'immagine tratta da un buon articolo "Disaccoppiamento dei sistemi orientati agli oggetti", che illustra i punti principali che verranno discussi.

Decomposizione

Pensi ancora che progettare un'architettura applicativa sia facile?

8.2 Interfacce, nascondere l'implementazione

I principi fondamentali per ridurre l'accoppiamento del sistema sono i principi di OOP e il principio di incapsulamento + astrazione + polimorfismo dietro di essi.

È per questo:

  • I moduli dovrebbero essere "scatole nere" l'uno per l'altro (incapsulamento) . Ciò significa che un modulo non dovrebbe "arrampicarsi" su un altro modulo e non sapere nulla della sua struttura interna. Gli oggetti in un sottosistema non dovrebbero accedere direttamente agli oggetti in un altro sottosistema.
  • I moduli/sottosistemi dovrebbero interagire tra loro solo attraverso interfacce (ovvero astrazioni che non dipendono dai dettagli di implementazione). Di conseguenza, ogni modulo deve avere un'interfaccia o interfacce ben definite per interagire con altri moduli.

Il principio della "scatola nera" (incapsulamento) ci permette di considerare la struttura di ciascun sottosistema indipendentemente dagli altri sottosistemi. Il modulo, che è una "scatola nera", può essere modificato relativamente liberamente. I problemi possono sorgere solo alla giunzione di diversi moduli (o un modulo e un ambiente).

E questa interazione deve essere descritta nella forma più generale (astratta), cioè sotto forma di interfaccia. In questo caso, il codice funzionerà allo stesso modo con qualsiasi implementazione conforme al contratto di interfaccia. È questa capacità di lavorare con diverse implementazioni (moduli o oggetti) attraverso un'interfaccia unificata che si chiama polimorfismo.

Ecco perché Servlet è un'interfaccia : il contenitore web non sa nulla di servlet, poiché si tratta di alcuni oggetti che implementano l'interfaccia Servlet e basta. I servlet conoscono anche un po' la struttura del contenitore. L'interfaccia Servlet è quel contratto, quello standard, quell'interazione minima necessaria per far sì che le applicazioni web Java conquistino il mondo.

Il polimorfismo non è affatto l'override dei metodi, come a volte erroneamente si crede, ma prima di tutto l'intercambiabilità di moduli/oggetti con la stessa interfaccia o “un'interfaccia, molte implementazioni”. Per implementare il polimorfismo, il meccanismo di ereditarietà non è affatto necessario. Questo è importante da capire perché l'ereditarietà in generale dovrebbe essere evitata quando possibile .

Grazie alle interfacce e al polimorfismo si ottiene proprio la possibilità di modificare ed estendere il codice senza modificare quanto già scritto (Principio Open-Closed).

Finché l'interazione dei moduli è descritta esclusivamente sotto forma di interfacce e non è legata a implementazioni specifiche, si ha la possibilità di sostituire assolutamente "indolore" per il sistema un modulo con qualsiasi altro che implementa la stessa interfaccia, così come aggiungerne uno nuovo e quindi espandere la funzionalità.

È come nel costruttore LEGO: l'interfaccia standardizza l'interazione e funge da sorta di connettore in cui è possibile collegare qualsiasi modulo con un connettore adatto.

La flessibilità del progettista è assicurata dal fatto che possiamo semplicemente sostituire un modulo o una parte con un altro con gli stessi connettori (con la stessa interfaccia), nonché aggiungere tutte le nuove parti che vogliamo (allo stesso tempo, esistenti le parti non vengono modificate o alterate in alcun modo).

Le interfacce consentono di costruire un sistema più semplice, considerando ogni sottosistema nel suo insieme e ignorando la sua struttura interna. Consentono ai moduli di interagire e allo stesso tempo non sapere nulla della struttura interna l'uno dell'altro, implementando così pienamente il principio della conoscenza minima, che è alla base dell'accoppiamento libero.

Più generali/astratte sono le interfacce definite e meno restrizioni impongono all'interazione, più flessibile è il sistema. Da qui, in realtà segue un altro dei principi di SOLID: il principio di segregazione dell'interfaccia , che si oppone alle "interfacce spesse".

Dice che le interfacce grandi e ingombranti dovrebbero essere suddivise in interfacce più piccole e più specifiche, in modo che i client di interfacce piccole (moduli dipendenti) conoscano solo i metodi con cui devono lavorare.

Questo principio è formulato come segue: "I clienti non dovrebbero dipendere da metodi (essere consapevoli dei metodi) che non usano" o "Molte interfacce specializzate sono meglio di una universale".

Si scopre che la connettività debole viene fornita solo quando l'interazione e le dipendenze dei moduli sono descritte solo con l'aiuto di interfacce, cioè astrazioni, senza utilizzare la conoscenza della loro struttura e struttura interna, e infatti l'incapsulamento viene quindi implementato. Inoltre, abbiamo la possibilità di espandere/modificare il comportamento del sistema aggiungendo e utilizzando diverse implementazioni, cioè grazie al polimorfismo. Sì, siamo tornati di nuovo a OOP: incapsulamento, astrazione, polimorfismo.

8.3 Facciata: interfaccia del modulo

Qui un programmatore esperto chiederà: se il design non è a livello di oggetti che implementano essi stessi le interfacce corrispondenti, ma a livello di moduli, allora qual è l'implementazione dell'interfaccia del modulo?

Risposta: parlando nel linguaggio dei modelli di progettazione, quindi un oggetto speciale può essere responsabile dell'implementazione dell'interfaccia del modulo - Facade . Se stai chiamando metodi su un oggetto che contiene il suffisso Gateway (ad esempio, MobileApiGateway), è molto probabile che si tratti di una facciata.

Una facciata è un oggetto interfaccia che accumula un insieme di operazioni di alto livello per lavorare con un certo sottosistema, nascondendo dietro di esso la sua struttura interna e la vera complessità . Fornisce protezione contro le modifiche nell'implementazione del sottosistema. Funge da singolo punto di ingresso: "prendi a calci la facciata e lui sa chi ha bisogno di essere preso a calci in questo sottosistema per ottenere ciò di cui ha bisogno".

Ti è appena stato presentato uno dei modelli di progettazione più importanti che ti consente di utilizzare il concetto di interfacce durante la progettazione dei moduli e quindi disaccoppiarli: "Facade".

Inoltre, "Facade" consente di lavorare con i moduli allo stesso modo degli oggetti ordinari e di applicare tutti i principi e le tecniche utili utilizzati nella progettazione delle classi durante la progettazione dei moduli.

Facciata: interfaccia del modulo

Nota : sebbene la maggior parte dei programmatori comprenda l'importanza delle interfacce durante la progettazione di classi (oggetti), sembra che molti scoprano l'idea di utilizzare le interfacce anche a livello di modulo.

Commenti
  • Popolari
  • Nuovi
  • Vecchi
Devi avere effettuato l'accesso per lasciare un commento
Questa pagina non ha ancora commenti