Quello che segue è più un'affermazione che una domanda - descrive qualcosa che può essere un modello. La domanda è: è un modello noto? Oppure, se non lo è, dovrebbe essere?
Ho avuto una situazione in cui ho dovuto scorrere su due strutture di dati multistrato diverse e copiare le informazioni da una all'altra. A seconda del caso d'uso particolare, avevo circa otto diversi tipi di livelli, combinati in circa otto diverse combinazioni:
A-B-C
B-C
A-C
D-E
A-D-E
e così via
Dopo alcuni tentativi infruttuosi di calcolare la ripetizione del codice di iterazione per livello, mi sono reso conto che la difficoltà principale in questo refactoring era il fatto che il livello più basso richiedeva l'accesso ai dati raccolti a livelli più alti. Per soddisfare esplicitamente questo requisito, ho introdotto la classe IterationContext
con un numero di metodi get()
e set()
per l'accumulo delle informazioni necessarie.
Alla fine, ho avuto la seguente struttura di classe:
class Iterator {
virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const = 0;
};
class RecursingIterator : public Iterator {
RecursingIterator(const Iterator &below);
};
class IterateOverA : public RecursingIterator {
virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
// Iterate over members in dataStructure1
// locate corresponding item in dataStructure2 (passed via context)
// and set it in the context
// invoke the sub-iterator
};
class IterateOverB : public RecursingIterator {
virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
// iterate over members dataStructure2 (form context)
// set dataStructure2's item in the context
// locate corresponding item in dataStructure2 (passed via context)
// invoke the sub-iterator
};
void main()
{
class FinalCopy : public Iterator {
virtual void iterateOver(const Structure &dataStructure1, IterationContext &ctx) const {
// copy data from structure 1 to structure 2 in the context,
// using some data from higher levels as needed
}
}
IterationContext ctx(dateStructure2);
IterateOverA(IterateOverB(FinalCopy())).iterate(dataStructure1, ctx);
}
Accade quindi che dataStructure1 sia una struttura dati uniforme, simile al DOM XML, mentre dataStructure2 è una struttura di dati legacy composta da vari struct
s e matrici. Ciò mi consente di passare dataStructure1 al di fuori del contesto per comodità. In generale, entrambi i lati dell'iterazione o entrambi i lati possono essere passati tramite il contesto, come conveniente.
I punti chiave della situazione sono:
- codice complicato che deve essere richiamato in "layers", con più combinazioni di tipi di layer possibili
- nel livello inferiore, le informazioni dei livelli superiori devono essere visibili.
I punti chiave dell'implementazione sono:
- uso della classe di contesto per accedere ai dati da tutti i livelli di iterazione
- codice di iterazione complicato incapsulato nell'implementazione della pura funzione virtuale
- due interfacce: una a conoscenza dell'iteratore sottostante, di cui non si è a conoscenza.
- uso di
const &
per semplificare la sintassi dell'utilizzo