Quali sono i pro e i contro di mantenere la maggior parte dello stato di un'applicazione in una singola struttura?

2

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 &);

AC 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.

    
posta Kerndog73 15.11.2018 - 09:11
fonte

1 risposta

3

Penso che riassumi già i pro e i contro.

Pro: riduce un numero elevato di parametri

Contro: "God object" aumenta l'accoppiamento e diventa più grande facilmente ma difficile da rendere più piccolo.

Direi che gli svantaggi pesano i professionisti. Esistono altri modi per controllare il numero di parametri iniettati richiesti. Oltre a un contenitore DI devi popolarli automaticamente, riducendo il problema in qualche modo.

Anche i due metodi non sono del tutto funzionalmente equivili. Ad esempio, puoi passare in diversi logger per classe.

Inoltre, il problema di avere questi alberi degli oggetti profondi non è solo un lungo elenco di parametri di costruzione.

È probabilmente un po 'di odore di codice, e forse indica che il codice potrebbe essere refactored ad un grafo di oggetto meno profondo. Forse, dato che dici che queste funzioni non hanno uno stato proprio, un modello di oggetto più anemico in cui un gestore con metodi elabora un intero elenco di A che contiene solo dati potrebbe appianare le tue dipendenze su un singolo livello?

    
risposta data 15.11.2018 - 10:40
fonte