Nella mia domanda, ho alcune classi. Molte di queste classi condividono lo stato comune come un riferimento al logger, ad esempio. Ad esempio, sia A
che B
richiedono uno stato comune per portare a termine il loro lavoro.
class A {
Logger &logger;
CommonThing &thing;
public:
void performTaskA();
};
class B {
Logger &logger;
CommonThing &thing;
std::vector<OtherThing> stuff;
public:
void performTaskB();
};
Un altro esempio di pattern dalla mia applicazione: C
contiene un'istanza di A
perché C
ha bisogno di performTaskA
per performTaskC
.
class C {
Logger &logger;
CommonThing &thing;
A a;
public:
void performTaskC() {
a.performTaskA();
}
};
C
sta essenzialmente memorizzando Logger
e CommonThing
due volte. A
in realtà non ha uno stato proprio così C
potrebbe molto bene costruire A
sul posto ogni volta che è necessario accedere alla sua interfaccia.
Sono un fan dell'iniezione di dipendenza. Se è richiesto un oggetto per eseguire un'operazione, lo passo. Tuttavia, ciò ha comportato il fatto che funzioni e costruttori prendessero molti parametri. Spesso devo avvolgere gli elenchi dei parametri su più righe perché sono così dannatamente lunghi.
Le operazioni eseguite richiedono molto stato. Questa è la natura delle operazioni. Se potessi, le funzioni avrebbero solo meno dipendenze ma non è davvero un'opzione. Ho un'idea per risolvere alcuni dei problemi citati.
Mi sono imbattuto in un frammento di codice da un compilatore C ++. Non ricordo i dettagli, ma ho visto un certo numero di funzioni, ognuna delle quali puntava un puntatore a un oggetto di contesto come parametro. Potrei mettere tutto lo stato comune in una singola struttura e quindi passare un riferimento alla struttura.
struct Context {
Logger logger;
CommonThing thing;
};
void performTaskA(Context &);
void performTaskC(Context &);
Né A
né C
devono essere più classi. Possono essere solo gruppi di funzioni che prendono un contesto. La ragione per cui erano classi prima è perché se fossero funzioni, avrebbero liste di parametri molto lunghe.
L'uso di una struttura di contesto sembra risolvere la maggior parte dei problemi, ma porta con sé una serie di problemi. Quello che sto facendo essenzialmente è una "classe di Dio", tranne per il fatto che le funzioni membro sono raggruppate in più file. Non è più ovvio a cosa acceda una funzione perché potrebbe accedere a qualsiasi cosa. Sebbene, se una funzione ha improvvisamente bisogno di accedere a qualcosa, non ho più bisogno di aggiornare gli elenchi dei parametri di un gruppo di funzioni.
Il contesto è migliore di quello che ho adesso?
Spero davvero che questo non sia fuori tema. Ho cercato di mantenerlo generico in modo che le risposte potessero aiutare più di una persona. Volevo chiedere qui prima di apportare un grosso cambiamento al codice base e riscrivere un sacco di cose.