ErrorAccumulator come pattern OO

1

Nelle ultime due settimane ho visto un paio di istanze di persone che passavano un tipo ErrorAccumulator di oggetto in funzioni che aggregano gli errori come stringhe all'interno della funzione, quindi dopo che la funzione restituisce gli errori vengono ripetuti e registrati. Per me questo mi sembra un cattivo design OO perché modifichi lo stato di un oggetto all'interno di una funzione come un effetto collaterale. Perché non archiviare tutti gli stati in un oggetto di contesto? O meglio ancora registra gli errori all'interno della funzione?

Fondamentalmente la mia domanda è ErrorAccumulator un pattern o anti-pattern?

    
posta ford prefect 17.06.2016 - 15:33
fonte

4 risposte

5

Basically my question is ErrorAccumulator a pattern or anti-pattern?

Con alcune eccezioni, un design può essere buono o cattivo a seconda del contesto (alcuni disegni sono orribili, non importa come li usi). Un motivo può rendere davvero unico un disegno, ma può essere applicato erroneamente in un altro design per peggiorarlo. Il contesto conta .

In generale, è una buona idea che le funzioni non modifichino i loro parametri. Ecco come funzionano le funzioni matematiche e rende il codice più chiaro a causa di un minor numero di effetti collaterali.

Tuttavia: devi guardare ogni oggetto e il suo scopo. Quando vedo ErrorAccumulator vedo un oggetto progettato da modificare per un capriccio. Solo per il suo nome, mi dice "Sono un secchio per lanciare i tuoi errori, e puoi scaricarli più tardi."

Or better yet just log errors inside of the function?

Ci sono alcuni buoni motivi per non che lo fanno in questo modo, ma qui ci sono alcuni problemi che sono intrecciati.

  • Gli errori di registrazione funzionano correttamente se il codice può recuperare da un errore stesso e gli errori possono semplicemente passare a un file di registro e non all'utente.
  • Le eccezioni potrebbero essere migliori se il codice non può essere ripristinato dall'errore stesso, ma il codice più in alto nello stack delle chiamate può fare qualcosa di utile.
  • Accumulare errori in un oggetto può essere una buona idea se il codice può recuperare dagli stessi errori, ma è necessario creare un elenco di tutti gli errori da mostrare all'utente come un'unica unità.

Riguardo all'ultimo punto, un buon modo per visualizzarlo è un modulo web. Diversi campi devono essere convalidati: forse alcuni consentono solo numeri, altri devono seguire uno schema specifico (ad esempio, abbinare un'espressione regolare). In questo caso, può essere sensato usare qualcosa come quel ErrorAccumulator per compilare un elenco di errori, che può quindi essere stampato come una unità da visualizzare all'utente.

Basically my question is ErrorAccumulator a pattern or anti-pattern?

Torna a questa domanda: entrambi. Se usato correttamente, può risolvere un problema specifico nel software. Se usato in modo errato, può risolvere il problema in modo errato e creare confusione.

    
risposta data 17.06.2016 - 16:25
fonte
5

Why not just store all state in a context object?

Quindi, invece di passare lo stato intorno all'oggetto stesso, dove è opportunamente incapsulato, preferiresti usare una variabile globale?

Or better yet just log errors inside of the function?

Ora le tue funzioni hanno assunto una dipendenza dal logger. Raccogliere errori nell'oggetto non richiede questo, perché è possibile registrare gli errori in seguito, quando hai terminato di chiamare le tue funzioni.

To me this feels like bad OO design because you are modifying the state of an object inside of a function as a side effect.

Potrebbe non piacerti, ma succede sempre.

Considera questo esempio: trasferire denaro da un conto corrente a un altro. Il tuo denaro non sa come muoversi da solo, né i tuoi account. Devi trasferire un agente (un cassiere, nel caso di persone, un oggetto di trasferimento nel caso del software) per spostare i soldi. Ci sono ottime ragioni per questo:

  1. Puoi avvolgere il tutto in una transazione, in modo che il denaro non venga creato o perso artificialmente (il debito si verifica ma il credito non lo è, ecc.)

  2. Puoi fare cose come la conversione di valuta durante il trasferimento. Un dollaro non ha idea di quanto vale in euro.

Ulteriori letture
Unità di lavoro

    
risposta data 17.06.2016 - 16:14
fonte
0

È un cattivo modello di design. Perché una funzione chiamata sum (int x, int y) dovrebbe prendere un terzo argomento e diventa sum (ErrorAccumulator ea, int x, int y)? È molto controintuitivo. inoltre supponiamo che esista una funzione foo () che non ha questo parametro e non registra errori, piuttosto che la necessità di registrare gli errori in quella funzione sorge: devo modificare quella firma di funzione e TUTTE le chiamate a quella funzione nel mio codice. E se non avessi un'istanza di ErrorAccumulator da passare a foo () in quello particolare zona di codice? Creo una nuova istanza, ma tutti gli errori registrati prima non ci sono la nuova istanza e se voglio tutti gli errori devo unire queste due istanze o, in alternativa, devo assicurarmi che la stessa istanza sia disponibile in tutto il mio sistema.

Fortunatamente non devi reinventare la ruota. Esistono framework per la registrazione di tali log4j che lo fanno esattamente quello che ti serve in un modo più intelligente e più flessibile: usano un intelligente pasticcio di fabbrica singleton così in qualsiasi momento hai la giusta istanza del logger, forniscono meccanismi semplici per registrare o non registrare le cose in modo programmatico in modo da poter registrare errori, informazioni, messaggi e cose in base al tuo esigenze e forniscono un livello di astrazione che ti consente di accedere a stream di stringhe, file, server remoti ecc. Anche se si sta già effettuando il login in una stringa e si desidera modificare e registrare in un file puoi farlo senza modificare una singola riga di codice, semplicemente modificando un file conf.

Ma dal momento che ErrorAccumulator non è solo una scelta di design scadente, è anche invasivo, ora per passando da ErrorAccumulator a un altro logger probabilmente dovrai refactare il tuo intero codice ...

    
risposta data 17.06.2016 - 17:37
fonte
-1

To me this feels like bad OO design because you are modifying the state of an object inside of a function as a side effect.

Perché è così male? Il termine "effetto collaterale" deriva dalla programmazione funzionale, che ha paura dello stato perché cerca di far finta che la programmazione sia un problema di matematica, ei problemi matematici non hanno uno stato, quindi tutto ciò che non si adatta al paradigma della "matematica problema" deve essere un "effetto collaterale" indesiderato.

OO, d'altra parte, è uno stile di programmazione imperativo . La programmazione imperativa è un paradigma completamente diverso che non ha paura dello stato. Tratta la programmazione come una ricetta, piuttosto che un problema di matematica: si prendono i dati e si cambia nella forma desiderata attraverso una serie di azioni prescritte. In OO, gli effetti visibili dall'esterno non sono una questione "laterale"; sono l'intero punto. Quindi non preoccuparti.

    
risposta data 17.06.2016 - 16:56
fonte

Leggi altre domande sui tag