Program Design chiarezza e convenienza

3

Recentemente ho contestato al mio collega la seguente situazione:

Ho sviluppato un framework che elabora le risorse (in java, anche se non è molto importante). Va (semplificato, pseudo-codice) come questo:

class Algorithm {
    Processor processor = ...;
    execute() {
        forEach(Resource r : readResourceNamesFromFileSystem()) {
           DomainObject do = convertResourceToDomainObject(r);
           processor.process(do);
        }       
    } 

}

interface Processor {
     process(DomainObject do);
}

Class Algorithm è un punto di accesso al mio framework. La risorsa è una rappresentazione di alcuni contenuti nel filesystem (ha metodi per leggere i dati dal file e il nome del file, che è importante)

Classe DomainObject (la dichiarazione è omessa) è una rappresentazione java del contenuto del file rappresentato da Resource. DomainObject ha solo dati e non ha un nome file all'interno.

Classe Processore rappresenta il livello della business logic, DomainObject può essere elaborato, archiviato nel Database e così via.

I dati del contenuto sono forniti da altri, sappiamo solo che questi file contengono i dati che possono essere convertiti in DomainObject (s), che è un oggetto reale con cui lavoriamo nel framework. Archiviamo un DomainObject in un file.

Ora discutiamo sul nome del file. Il mio collega desidera che il nome del file venga propagato nel processore e potenzialmente a tutti i livelli perché è facile stampare il messaggio di registrazione / generare un'eccezione che contiene un nome file se qualcosa va storto durante l'elaborazione, o forse scrivere il messaggio come "l'oggetto dominio archiviato nel file ( qui__comes__filename ) è stato elaborato correttamente".

Vedo il punto del mio collega (convenienza) ma sono sicuro che rompe il design e l'incapsulamento perché il modulo del processore non dovrebbe realmente essere a conoscenza della "origine" di DomainObject (oggi li memorizziamo in file uno DomainObject per file, domani useremo forse qualcos'altro, qualcosa che non ha necessariamente un nome file).

Affermo che è meglio catturare l'eccezione nel metodo Algorithm.execute e rilanciare l'eccezione con un nome file / registrare il nome file. Il file di registro sarà meno leggibile ma l'incapsulamento non verrà interrotto.

Secondo me è un design contro la chiarezza. Potresti per favore condividere la tua opinione, chi ha ragione, chi ha torto? Dovrei sacrificare il design per la chiarezza dei log?

BTW Ho promesso al mio collega di fare questa domanda in modo da leggere insieme le possibili risposte:)

Grazie mille in anticipo e buona giornata

    
posta Mark Bramnik 07.07.2014 - 21:58
fonte

2 risposte

6

Individua l'eccezione al livello in cui fai hai il nome del file, incorpora il nome del file nel messaggio di errore e ripeti.

Questo è un classico esempio del perché le eccezioni sono progettate come sono; propagano lo stack di chiamate alla successiva clausola catch disponibile, in cui è possibile aggiungere nuove informazioni laddove è disponibile. Ciò evita la necessità di inquinare le tue classi propagando le informazioni di logging attraverso la tua gerarchia di classi.

Java manterrà la traccia dello stack originale .

L'intero punto di avere cose come stream oggetti è di astrarre dettagli come i nomi dei file. A stream non interessa da dove provengano i dati da cui proviene lo streaming, e alcune fonti di dati non hanno nemmeno nomi di file associati.

    
risposta data 07.07.2014 - 22:23
fonte
3

Se si utilizza un framework di registrazione come Log4j, è possibile utilizzare un contesto diagnostico nidificato (NDC) per archiviare il nome del file nel punto in cui è disponibile, quindi recuperarlo dall'NDC al momento della registrazione dei messaggi.

Logj4 NDC

Questo può essere ancora più utile perché puoi effettivamente scrivere un appender di log4j che gestisce i messaggi di log specialmente in base al contenuto NDC.

Il caso specifico che ho usato era un server web Jetty incorporato. Parti dell'URI in entrata hanno identificato il cliente, ad es.

http://domain/app/<customer-name>/otherstuff...

Il dispatcher della richiesta Jetty estraeva il valore di "nome cliente" dall'URI e lo memorizzava nel NDC di Log4j.

Era quasi banale scrivere un appender di log4j che, quando NDC conteneva un valore del nome del cliente, aggiungeva il messaggio a un file .log.

In questo modo disponevamo di un singolo file di registro coerente che conteneva tutte le informazioni diagnostiche in sequenza, inoltre avevamo i registri delle attività rilevanti (e privati) per ciascun cliente.

    
risposta data 09.07.2014 - 17:00
fonte

Leggi altre domande sui tag