Scrive il progresso da un lungo processo in corso

5

Abbiamo alcuni processi a lunga esecuzione che possono essere eseguiti fino a un'ora e fino a 6 ore.

Alcuni processi vengono avviati manualmente e l'utente vuole vedere qual è lo stato di avanzamento del processo.

Senza entrare in molti dettagli dei dettagli reali, potresti pensare a:

  • Recupero dei dati
  • Aggiorna le informazioni del cliente
  • rimuovi i dati falsi
  • crea file esterni
  • crea pdf

Ovviamente questo processo consiste in un sacco di classi diverse, e talvolta voglio che quelle singole classi scrivano progressi.

Ad esempio: quando mi interessano solo i progressi generali, potrei scrivere i progressi dalla facciata di livello superiore, ma voglio anche scrivere progressi nel servizio che crea i pdf, in modo che anche la classe e le sottoclassi abbiano scrivere progressi.

La mia domanda è: come posso scrivere i progressi di tutte quelle classi riguardo lo stesso processo di 'base' senza passare qualche tipo di processo da una classe all'altra?

Ciò che ho pensato è la creazione di una classe di servizio di logging che si occupi della registrazione e del passaggio da una classe all'altra, ma sembra così brutto dare a ogni singola classe il servizio di registrazione.

In secondo luogo, ho pensato di creare una classe di logging statica per il logging (che trovo comune nelle applicazioni per la normale registrazione degli errori) ma devo ancora passare il processId intorno

In terzo luogo ho pensato di creare una factory da chiamare da ogni classe, ma poi devo ancora passare il processId intorno

Quarto ho pensato di iniettare la classe loggingservice in ogni classe, ma poi devo ancora passare il processId in giro e sembra un tipo sbagliato di dipendenza per una classe, una dipendenza per un logger.

Quindi sto cercando il numero 5, o i motivi per cui 1,2,3 o 4 sono comunque una buona idea e gli svantaggi che vedo non sono rilevanti o importanti.

    
posta Michel 23.03.2015 - 13:29
fonte

4 risposte

4

Solitamente lo faccio lasciando che ogni classe di lunga durata implementa un'interfaccia, ad es. LongRunning , con un solo metodo reportProgress() . Il tuo servizio di registrazione verrebbe semplicemente informato dell'esistenza di corridori così lunghi, periodicamente ne interroga il loro stato e quindi riferirà sullo stato generale del mondo in qualsiasi modo lo ritenga opportuno.

Il tuo codice aziendale deve ancora essere intercalato con le istruzioni di registrazione in questo modo, ma altrimenti le tue classi esistenti non devono adattarsi a qualcosa di esterno, e questa è la cosa più importante a mio avviso: non cambiare il codice commerciale che già fa il suo lavoro per motivi estranei.

    
risposta data 23.03.2015 - 13:34
fonte
7

Hai ragione sul fatto che tutte queste soluzioni sporcano il tuo codice con il codice di registrazione / reporting che interrompe la separazione delle preoccupazioni. Questo tipo di problema è esattamente il motivo per cui Programmazione orientata agli aspetti esiste:

Wikipedia (sottolineatura mia):

Aspect-oriented programming entails breaking down program logic into distinct parts (so-called concerns, cohesive areas of functionality). Nearly all programming paradigms support some level of grouping and encapsulation of concerns into separate, independent entities by providing abstractions (e.g., functions, procedures, modules, classes, methods) that can be used for implementing, abstracting and composing these concerns. Some concerns "cut across" multiple abstractions in a program, and defy these forms of implementation. These concerns are called cross-cutting concerns.

Rilevante anche: Preoccupazione trasversale

Essenzialmente, vuoi qualcosa che possa toccare tutti gli aspetti della tua applicazione in uno scenario particolare. Nel tuo caso, tale registrazione è una preoccupazione trasversale.

Non posso aiutarti con i dettagli di implementazione in quanto la tua domanda non menziona una lingua o una piattaforma. Ma molte lingue offrono la programmazione orientata agli aspetti in modo nativo, o ci sono framework che assistono con questo processo.

Esempi:

risposta data 23.03.2015 - 13:48
fonte
0

Invece di pensare al logging (ad esempio la tua applicazione che dice qualche sistema di registrazione, forse usando syslog (3 ) su Linux, che cosa sta succedendo) potresti pensarlo diversamente: la tua applicazione potrebbe essere un server per richieste in cui viene interrogato il suo stato.

Quindi potresti persino rendere la tua app qualche JSONRPC server (e dovrai anche codificare il piccolo client della riga di comando per interrogalo).

Potresti anche fare in modo che la tua app diventi un server web specializzato (ad esempio, utilizzando una libreria di server HTTP come libonion , ecc. vedi questo elenco ) ed esegui il query con le solite tecnologie del browser.

In questi giorni, per un'applicazione in grado di eseguire un'intera giornata lavorativa, abiliterei alcune tecnologie del server web al suo interno. Anche una stampante economica è oggi in grado di fornire il proprio stato attraverso un'interfaccia web.

Le tue classi interne potrebbero dare il loro stato, ad es. aggiornando alcune variabili "globali" o dati a livello di applicazione, ecc ... (Naturalmente usate i mutex per i problemi di sincronizzazione).

La prospettiva orientata all'aspetto dalla risposta di durron597 è ancora pertinente. Se la tua applicazione è un grosso codice C o C ++ compilato da GCC, potresti prendere in considerazione l'utilizzo di MELT per personalizzare il compilatore per tale aspetto (orientato all'aspetto ) scopi. Ma questo sarebbe specifico per il compilatore, richiederebbe una settimana di sforzi, ecc.

A proposito, non sono sicuro che uno stato quernario esternamente debba essere a grana fine. Credo che aggiornare tale stato ogni dozzina di secondi sia sufficiente (non sto pensando a un aggiornamento periodico, ma a uno stato a grana grossa). Quindi probabilmente non devi toccare una grande quantità di codice. YMMV.

Qualunque cosa tu faccia, devi progettarla abbastanza presto. I wikipages su continuazioni , applicazione checkpointing , persistenza potrebbe essere rilevante.

    
risposta data 23.03.2015 - 14:39
fonte
0

So che questo è un vecchio post ma comunque ... per rispondere alle preoccupazioni del codice "sporco" nella risposta accettata, considera il modello del visitatore.

Aggiornare il metodo reportProgress () per acquisire un parametro visitor che contiene il codice specifico per i report per ciascuna istanza concreta, quindi l'istanza concreta chiama il metodo visitor appropriato.

In questo modo puoi mantenere il codice della tua business logic separato dal tuo codice di registrazione / reporting. Sarai anche in grado di fornire diverse implementazioni di registrazione come visitatori diversi.

    
risposta data 11.01.2017 - 21:55
fonte

Leggi altre domande sui tag