5

Sto sviluppando un'applicazione C++ utilizzata per simulare uno scenario del mondo reale. Sulla base di questa simulazione, il nostro team svilupperà, testerà e valuterà i diversi algoritmi che operano all'interno di uno scenario del mondo reale.Configurazione dell'applicazione flessibile in C++

Abbiamo bisogno della possibilità di definire diversi scenari (potrebbero differire in alcuni parametri, ma uno scenario futuro potrebbe anche richiedere la creazione di oggetti di nuove classi) e la possibilità di mantenere un insieme di algoritmi (che è, ancora una volta, un insieme di parametri ma anche la definizione di quali classi devono essere create). I parametri vengono passati alle classi nel costruttore.

Mi chiedo quale sia il modo migliore per gestire tutte le configurazioni di scenari e algoritmi. Dovrebbe essere facilmente possibile avere uno sviluppatore che lavora su uno scenario con il "suo" algoritmo e un altro sviluppatore che lavora su un altro scenario con il "suo" algoritmo diverso. Tuttavia, i set di parametri potrebbero essere enormi e dovrebbero essere "condivisibili" (se ho definito un insieme di parametri per un determinato algoritmo nello scenario A, dovrebbe essere possibile utilizzare l'algoritmo nello scenario B senza copiare la copia &).

sembra che ci sono due modi principali per realizzare il mio compito:

  • definire un formato di file di configurazione in grado di gestire le mie esigenze. Questo formato potrebbe essere basato su XML o personalizzato. Dato che non c'è riflessione in C++ in C++, sembra che devo aggiornare il parser dei file di configurazione ogni volta che una nuova classe di algoritmo viene aggiunta al progetto (per convertire una stringa come "MyClass" in una nuova istanza di MyClass). Potrei creare un nome per ogni setup e passare questo nome come argomento della riga di comando.

    • I pro sono: nessuna compilation necessario per modificare un parametro e re-run, posso facilmente memorizzare l'intero file di configurazione con la simulazione risultati
    • contra: sembra un sacco di fatica, in modo particolarmente duro perché io sto usando un sacco di classi template che devono essere istanziate con determinati argomenti del template. Nessun supporto IDE per la scrittura del file (almeno senza creare un intero XSD che avrei dovuto aggiornare ogni volta che viene aggiunto un parametro/classe)
  • Wire tutto in codice C++. Non sono completamente sicuro di come farei questo per separare tutte le diverse logiche di creazione, ma sono comunque in grado di riutilizzare i parametri attraverso gli scenari. Penso che proverei anche a dare a ogni setup un nome (stringa) e usare questo nome per selezionare l'impostazione tramite la riga di comando arg.

    • pro: la sicurezza di tipo, il supporto IDE, non aveva bisogno di parser
    • con: (? Forse qualche serializzazione) come posso facilmente memorizzare l'impostazione con i risultati ?, ha la necessità di compilazione dopo ogni modifica dei parametri

Ora ecco le mie domande: - Qual è la tua opinione? Mi sono perso i pro/contro importanti ? - ho perso una terza opzione? - C'è un modo semplice per implementare l'approccio del file di configurazione che dà a una flessibilità sufficiente? - Come organizzeresti tutto il codice factory nell'approccio seconde? Ci sono dei buoni esempi C++ per qualcosa di simile là fuori?

Grazie mille!

risposta

-1

Ho trovato this website con un modello di fabbrica di supporto che credo verrà utilizzato nel mio codice.

0

Se non si utilizza XML, è possibile che boost :: spirit possa cortocircuitare almeno alcuni dei problemi che si presentano. Ecco un semplice example di come i dati di configurazione possono essere analizzati direttamente in un'istanza di classe.

+0

Grazie, Steve. Non l'ho visto prima e sembra abbastanza buono per avere parametri nei file di configurazione, ma sembra ancora molto lavoro per ottenere gli argomenti del mio modello in ... – Philipp

2

C'è un modo per farlo senza modelli o riflessioni.

Innanzitutto, ci si assicura che tutte le classi che si desidera creare dal file di configurazione abbiano una classe base comune. Chiamiamo questo MyBaseClass e assumiamo che MyClass1, MyClass2 e MyClass3 tutti ereditiamo da esso.

In secondo luogo, si implementa una funzione di fabbrica per ciascuna delle MyClass1, MyClass2 e MyClass3. Le firme di tutte queste funzioni di fabbrica devono essere identiche. Una funzione di fabbrica di esempio è la seguente.

MyBaseClass * create_MyClass1(Configuration & cfg) 
{ 
    // Retrieve config variables and pass as parameters 
    // to the constructor 
    int age = cfg->lookupInt("age"); 
    std::string address = cfg->lookupString("address"); 
    return new MyClass1(age, address); 
} 

In terzo luogo, si registrano tutte le funzioni di fabbrica in una mappa.

typedef MyBaseClass* (*FactoryFunc)(Configuration *); std::map<std::string, FactoryFunc> nameToFactoryFunc; nameToFactoryFunc["MyClass1"] = &create_MyClass1; nameToFactoryFunc["MyClass2"] = &create_MyClass2; nameToFactoryFunc["MyClass3"] = &create_MyClass3;

Infine, si analizza il file di configurazione e scorrere su di esso per trovare tutte le voci che specificano il nome di una classe. Quando trovi una tale voce, cerchi la sua funzione di fabbrica nella tabella nameToFactoryFunc e invoca la funzione per creare l'oggetto corrispondente.

+0

Implementando le funzioni 'create_ *' con la stessa firma e il tipo di ritorno diverso hai praticamente fatto il lavoro dei modelli a mano. Non dico che sia male, ma penso che sarebbe più chiaro se usassi una funzione basata su 'create' e la specializzassi per ogni sottotipo. –

+0

La decisione su quale funzione template chiamare viene eseguita in fase di compilazione. Al contrario, l'uso di una mappa di funzione _name-> factory consente di prendere questa decisione in fase di runtime, quindi è una forma di polimorfismo. –

+0

In fase di compilazione avviene solo la deduzione del tipo - puoi ancora mantenere i puntatori alle funzioni basate su modelli - https://stackoverflow.com/questions/3641657/address-of-c-template-function –

Problemi correlati