Come progettare un metodo log () che può essere facilmente accessibile dall'esterno della classe Console?

3

Recentemente il mio team ha programmato una console per sviluppatori personalizzata in un videogioco che può essere facilmente nascosto o visualizzato, perché è più comodo e meno complicato.

La classe Console contiene una funzione log (stringa) che dovrebbe essere facilmente accessibile da qualsiasi parte al di fuori di essa, senza doverla fare riferimento ovunque.

Come possiamo progettare un metodo che possa essere facilmente accessibile dall'esterno della classe? Ad esempio, la stampa di un messaggio sulla console in C ++ è semplice come:

cout << "Message";

Bene, vogliamo qualcosa di simile nel migliore dei casi, forse Console :: log (), ma non sappiamo come ottenere un corretto modo di farlo.

Saluti.

    
posta Bugster 13.09.2013 - 18:43
fonte

1 risposta

6

Il modo corretto per farlo è usare un framework di registrazione. Apache (o modellato su) 'log4xyz' (dove xyz è la scelta della lingua - log4j per java, log4net per .net, log4cpp per C ++) è uno degli stili più comuni.

Dato che si tratta specificamente di C ++, farò riferimento a log4cpp (anche se sono più familiare con log4j).

log4cpp ha un numero di livelli di log: emerg, fatal, alert, crit, error, warn, notice, info e debug ( docs ).

Configura le appendici (un appender è un modo per registrare qualcosa - in un database c'è un appender, in un file c'è un altro, in un file che ruota ogni 24 ore è un altro, in un file che ruota ogni 1 Megabyte di i dati sono un altro, ecc ...) e le categorie (una categoria è un gruppo di cose che si registrano allo stesso modo). Questo può essere fatto sia in codice grezzo, sia in un file di proprietà.

Il codice raw dovrebbe essere simile a questo:

int main(int argc, char** argv) {
    log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
    appender1->setLayout(new log4cpp::BasicLayout());

    log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");
    appender2->setLayout(new log4cpp::BasicLayout());

    log4cpp::Category& root = log4cpp::Category::getRoot();
    root.setPriority(log4cpp::Priority::WARN);
    root.addAppender(appender1);
    root.addAppender(appender2);

    ...
}

Un esempio di file di proprietà può essere visto sulla pagina web del progetto.

In questo codice, hai due appendici che sono collegati alla categoria radice: uno collegato a un flusso di output, l'altro a un file. La categoria radice è impostata per registrare elementi a livello di avviso o superiori.

Per richiamare i logger si farebbero cose come:

root.warn("%d + %d == %s ?", 1, 1, "two");
root << log4cpp::Priority::ERROR << "Streamed root error";
root << log4cpp::Priority::INFO << "Streamed root info";

E qui hai tre messaggi inviati al root logger, uno con warn, uno con priorità sugli errori, uno con informazioni. Poiché l'informazione è inferiore all'errore di avviso, non verrebbe registrata. Nota i due diversi stili di registrazione.

Sotto questo modello, dovresti creare un appender che si collega al tuo oggetto Console e collegarlo ad alcune categorie. La regolazione del livello di registro su quella categoria consentirebbe quindi di determinare ciò che appare sulla console.

Il codice per ottenere una categoria arbitraria è simile a:

log4cpp::Category& root = log4cpp::Category::getRoot();

log4cpp::Category& sub1 = 
    log4cpp::Category::getInstance(std::string("sub1"));

Questo potrebbe essere invocato da qualsiasi luogo. Ciò consente di astrarre la connessione effettiva del codice alla console (o ad altri logger). Potresti fare cose come configurare un logger remoto (si registra su qualcosa che ascolta sulla rete) in modo da poter avere un'intera schermata di registrazione in corso su un altro computer (e su un file) mentre testi il gioco - senza dover aprire una console locale per acquisire tali informazioni.

    
risposta data 14.09.2013 - 00:54
fonte

Leggi altre domande sui tag