Di recente ho apportato alcune importanti rifattorizzazioni al mio codice. Una delle cose principali che ho cercato di fare è stata quella di dividere le mie classi in oggetti dati e oggetti worker. Questo è stato ispirato, tra le altre cose, da questa sezione di Clean Code :
ibridi
Questa confusione a volte porta a sfortunate strutture dati ibride che sono metà oggetto e metà struttura dati. Hanno funzioni che fanno cose significative e hanno anche variabili pubbliche o accessori e mutatori pubblici che, a tutti gli effetti, rendono pubbliche le variabili private, tentando altre funzioni esterne di usare quelle variabili come un programma procedurale userebbe struttura dati.
Tali ibridi rendono difficile l'aggiunta di nuove funzioni ma anche l'aggiunta di nuove strutture dati. Sono i peggiori di entrambi i mondi. Evita di crearli. Sono indicativi di un disegno confuso i cui autori non sono sicuri - o peggio, ignoranti - se hanno bisogno di protezione da funzioni o tipi.
Recentemente stavo guardando il codice di uno dei miei oggetti worker (che succede per implementare il modello visitatore ) e ho visto questo:
@Override
public void visit(MarketTrade trade) {
this.data.handleTrade(trade);
updateRun(trade);
}
private void updateRun(MarketTrade newTrade) {
if(this.data.getLastAggressor() != newTrade.getAggressor()) {
this.data.setRunLength(0);
this.data.setLastAggressor(newTrade.getAggressor());
}
this.data.setRunLength(this.data.getRunLength() + newTrade.getLots());
}
Mi sono subito detto "invidia delle funzionalità! Questa logica dovrebbe essere nella Data
classe - in particolare nel handleTrade
metodo. handleTrade
E updateRun
dovrebbe sempre accadere insieme". Ma poi ho pensato "la classe di dati è solo una public
struttura di dati, se comincio a farlo, allora arriverà un oggetto ibrido!"
Cosa c'è di meglio e perché? Come decidi quale fare?