Nei precedenti articoli sulle strategie utili a migliorare il disaccoppiamento (Disaccoppiamento Lost Identity, Disaccoppiamento totale con Protezione Implicita) abbiamo visto come esistano diversi fattori che determinano l’accoppiamento tra unità software: in particolare abbiamo evidenziato come le classi in java e addirittura le firme dei metodi, siano fattori che possono promuovere una politica di sviluppo software poco propensa al disaccoppiamento tra le classi.
Questi fattori vanno contro il principio OCP (Open Closed Principle) secondo il quale una classe o più in generale un software, dovrebbe essere aperto alle estensioni e chiuso alle modifiche.
Possiamo quindi tranquillamente affermare che lo scambio di messaggi sia anch'esso un fattore che accentua l'accoppiamento tra classi. Spesso poi in implementazioni di uso comune quando una classe A chiama un metodo su una Classe B quest'ultima ha necessità di capire la tipologia del messaggio ricevuto e dieffettuare un casting in locale.
Questo può dunque essere visto come elemento accoppiante, anche se in realtà non fa parte di questo contesto.

scambio messaggi
Partiamo da un presupposto di base e che cioè non necessariamente una classe Source
per richiamare un metodo sulla classe Target
al quale passare un parametro debba necessariamente farlo attraverso quel metodo. Cioè più semplicemente, deve esistere un modo per far si che una classe Source
richiami un metodo printMessage(String message)
su una classe target senza inviargli message
.
La nostra tesi è che se questo fosse possibile si otterrebbe un ulteriore grado di disaccoppiamento.
Per il casting in locale questo è un tema che riprenderemo a fine articolo e che in qualche modo verrà risolto specializzando i metodi, come vedremo in seguito.
Creiamo un progetto java e chiamiamolo DecouplingCommunication
creiamo quindi la seguente classe nel relativo package:
package com.sperimental;
import java.util.Hashtable;
public class DataShared {
private Hashtable queue = new Hashtable();
public String getStringProperty(String source, String key) {
return (String) queue.get(key);
}
public void setProperty(String source , String key, Object prop) {
queue.put(key, prop);
}
}
DataShared è una classe che utilizzeremo per il transito del messaggio tra due classi: Source
Target
package com.sperimental;
public interface PrinterInterface {
public void printMessage();
}
E le due classi Source
Target
package com.sperimental;
public class Source {
private DataShared ds;
private PrinterInterface pi;
private Source() {
super();
}
public Source(DataShared ds,PrinterInterface pi) {
super();
this.ds = ds;
this.pi = pi;
}
public void foo() {
ds.setProperty(this.getClass().getName(), "key Message4Target","messaggio da Source per Target!");
pi.printMessage();
}
}
package com.sperimental;
public class Target implements PrinterInterface {
private DataShared ds;
private Target() {
super();
}
public Target(DataShared ds) {
super();
this.ds = ds;
}
public void printMessage() {
String msg= ds.getStringProperty(this.getClass().getName(), "key Message4Target");
System.out.println("messaggio ricevuto:" + msg);
}
}
Cerchiamo ora di fare un po' di chiarezza analizzando il codice:
public void foo() {
ds.setProperty(
this.getClass().getName(),
"key Message4Target",
"messaggio da Source per Target!"
);
pi.printMessage();
}
Utilizza una istanza condivisa di DataShared
Target
DataShared
DataShared
Object
public class DataShared {
private Hashtable queue = new Hashtable();
public void setProperty(String source , String key, Object prop) {
queue.put(key, prop);
}
}
La classe Target
printMessage()
public void printMessage() {
String msg= ds.getStringProperty(
this.getClass().getName(),
"key Message4Target"
);
System.out.println("messaggio ricevuto:" + msg);
}
recupera la property e la stampa.
Facciam oa questo punto alcune considerazioni:
- Le classi
Source
Target
Source
printMessage()
Target
DataShared
- Quando viene recuperato il messaggio da
Target
printMessage()
getStringproperty()
DataShared
Source
Target
DataShared
- Possono essere considerate tranquillamente precauzioni per la Thread-Safety
Questo articolo approfondisce una tematica che riguarda i limiti della metodologia OOP: aldilà dell'aspetto pratico ci sarà utile come introduzione al prossimo articolo di questa serie di approfondimenti su Java e OOP, dedicato alla Programmazione Data Centric.