È possibile mantenere il codice di registrazione completamente al di fuori della logica aziendale?

7

Con l'aiuto di AOP, posso rimuovere il codice di registrazione dalla mia logica aziendale. Ma penso che possa essere usato solo per registrare cose semplici (vale a dire il metodo di registrazione entry / exit e i valori dei parametri).

Tuttavia, cosa succede se devo registrare qualcosa nella mia logica aziendale? per es.

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      Log.Warn("user is not existed");        //<----------------- Log A
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   Log.Info("Step 1 is completed");            //<----------------- Log B

   //Step 2
   while(true)
   {
       //do something
   }
   Log.Info("Step 2 is completed");            //<----------------- Log C

}

Il precedente metodo di esempio potrebbe non essere abbastanza chiaro, quello che voglio mostrare qui è che il metodo dovrebbe essere trattato come l'unità più piccola dal punto di vista del dominio. Non dovrebbe essere diviso in parti più piccole.

È possibile spostare oltre 3 codici di registrazione fuori dal metodo? Qual è la migliore pratica per tale situazione?

    
posta Charlie 16.03.2017 - 02:19
fonte

8 risposte

1

Sure!

Ma nella mia esperienza, ci sono due tipi generali di utile registrazione:

Tutto log: log costruiti tramite le API di profilazione. Buono per identificare problemi di prestazioni e segnalazione di eccezioni. Molto rumoroso.

Log evento aziendale : registri richiamati in business logic. Qualunque cosa possa interessare l'azienda. Rumore minimo Solo eventi logici, "business" degni di nota. Buono per l'auditing e KPI's ...

Quindi, suggerirei vivamente due cose. Innanzitutto, fai ciò che fanno gli altri strumenti di monitoraggio, come New Relic, e usa il. API di profilazione NET 1 . In secondo luogo, registra gli eventi di business logici nella tua logica aziendale . Tenere traccia di determinati eventi è business logic.

E, normalmente, non suggerirei AOP per entrambi i tipi di registrazione 2 . Nella mia esperienza, o vuoi tutto , il che significa che stai usando un profiler, o vuoi eventi logici / aziendali. E in quest'ultimo caso, penso che sia più semplice invocare il logger nella logica di business.

1. Ma seriamente, risparmia te stesso migliaia di ore e usa solo uno strumento di profilatura esistente ...

2. Ovviamente, questo presuppone che tu condivida la mia opinione sul fatto che un aspetto non è un ottimo posto per nascondere le regole aziendali!

    
risposta data 17.03.2017 - 16:13
fonte
8

Certo, puoi usare facilmente AOP per questo. Semplicemente refactor le parti

  • Ottieni utente dall'ID
  • passaggio 1
  • passaggio 2

in metodi separati (come avresti dovuto fare per rendere il tuo codice più pulito). Ora puoi facilmente configurare il tuo framework AOP per registrare le chiamate al metodo di tua scelta ( come mostrato qui ). L'eccezione può essere registrata direttamente dal chiamante, non è necessario utilizzare AOP per ottenere questo fuori dalla logica di business.

Per la tua modifica:

I want to show here is that the method should be treated as the smallest unit from the domain point of view. It shouldn't be divided into smaller pieces

Perché non dovrebbe? Se, in un "contesto logico aziendale", si desidera registrare "qualcosa" che vale la pena registrarsi, e se questo "qualcosa" può essere dato un nome ragionevole, nella maggior parte dei casi avrà senso rifattorizzare il codice in un metodo su propria. Se si desidera utilizzare AOP, sarà necessario strutturare il codice in un modo che probabilmente avrebbe dovuto strutturarlo indipendentemente dal requisito di registrazione. Puoi interpretarlo come uno svantaggio di AOP, o puoi interpretarlo come un vantaggio, poiché ti fornisce un feedback in cui la struttura del codice può essere migliorata.

    
risposta data 16.03.2017 - 08:31
fonte
2

Con l'ausilio di alcuni schemi comuni è possibile estrarre il codice di registrazione dalla logica aziendale. Tuttavia potresti non trovare che valga la pena di farlo

Ad esempio, utilizzando listener (esegui manualmente uno o utilizzando bus eventi ecc.), il tuo codice sarà simile a

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      listener.OnUserNotFound(userId);
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   listener.OnStep1Finished(......);

   ...

}

Implementando la registrazione nel listener, la logica di registrazione non è più nella logica aziendale.

Tuttavia potresti scoprire che questo non è sempre realistico in quanto potresti non essere sempre in grado di definire un evento significativo della tua logica.

Un altro approccio è attraverso meccanismi come Dtrace in Solaris che consentono di iniettare nei processi in esecuzione (credo che ci sia modo di fare cose simili in C #?) in modo che le registrazioni e le raccolte statistiche possano essere definite su runtime. Tuttavia ci sono altri svantaggi.

    
risposta data 16.03.2017 - 05:30
fonte
2

Un altro approccio consiste nel mettere il log aziendale e la registrazione tecnica a parte. Quindi possiamo richiamare la registrazione aziendale "Audit" e applicare una serie specifica di regole aziendali come le regole di archiviazione e di elaborazione come Business Activity Monitoring.

D'altra parte, il logging tecnico, o semplicemente "Logging", è un mezzo di ultima istanza per lasciare una traccia di problemi tecnici. Dovrebbe essere asincrono, veloce, tollerante alla mancata persistenza del messaggio di log. Inoltre, i messaggi di log devono passare attraverso il minor numero di proxy possibile per essere vicini all'origine del problema.

La logica di The Logging è abbastanza variabile ed è strettamente connessa con l'implementazione, quindi hai davvero bisogno di separarlo dal codice?

La logica di The Audit dovrebbe essere considerata una logica di dominio e gestita di conseguenza.

Ad esempio, in Hexagonal Architecture potrebbe esserci una porta di controllo insieme alle porte Client, Storage e MQ (e, possibilmente, Metrics and Control). Sarebbe una porta secondaria, cioè l'attività su questa porta è innescata dal core business, piuttosto che dai sistemi esterni.

    
risposta data 16.03.2017 - 06:12
fonte
2

A meno che la registrazione non faccia parte dei requisiti aziendali, è meglio, come dici tu, tenerla completamente fuori dal codice.

Questo significa che non vuoi davvero registrare cose del tipo "passaggio 1 completo". Anche se potrebbe essere inizialmente utile per il debug, in produzione genererà solo gigabyte di spazzatura che non guarderai mai.

Se Step1Complete è una sorta di evento aziendale che richiede ulteriori azioni, può essere esposto attraverso un buon vecchio evento senza forzare l'inserimento di un ILogger o simili nella tua classe

    
risposta data 16.03.2017 - 07:28
fonte
1

Modi per evitare la registrazione direttamente in una classe o un metodo:

  1. Genera un'eccezione e fai il tuo login su un blocco catch più in alto dell'albero delle chiamate. Se è necessario acquisire un livello di registro, è possibile generare un'eccezione personalizzata.

  2. Esegui chiamate a metodi già strumentati per la registrazione.

risposta data 16.03.2017 - 03:56
fonte
1

È davvero necessario separare la registrazione dalla logica aziendale? La registrazione eseguita è in corrispondenza della logica aziendale scritta e quindi ha senso essere nella stessa classe / funzione. Ancora più importante, facilita la leggibilità del codice.

Tuttavia, nel caso in cui si desideri veramente separare la registrazione dalla logica aziendale, è consigliabile prendere in considerazione l'idea di generare eccezioni personalizzate e inoltrare tali eccezioni per la registrazione.

    
risposta data 16.03.2017 - 06:20
fonte
0

No, non in c #

OP, la risposta alla tua domanda specifica è no, non in c #. Potrebbero esserci altri linguaggi AOP più nativi, ma tutti gli approcci ad AOP in c # che ho visto possono applicare solo comportamenti aspecifici nel contesto di un join point , significa che deve esserci un flusso di controllo tra un blocco di codice e l'altro. I comportamenti attesi non verranno eseguiti nel mezzo di un metodo, tranne ovviamente chiamando un altro metodo.

Potresti "riconoscere" alcuni bit di registrazione

Detto questo, puoi estrapolare alcune preoccupazioni legate alla registrazione, ma non scrivere il registro. Ad esempio, un punto di divisione eseguito alla voce di un metodo potrebbe configurare un contesto di registrazione e generare tutti i parametri di input, e in uscita potrebbe rilevare eccezioni o eseguire il commit di un registro sull'archiviazione permanente, quel genere di cose.

La scrittura scrittura non è un aspetto, comunque

Vorrei aggiungere che la scrittura dei registri non è in realtà una preoccupazione trasversale, comunque. Almeno non eseguire il debug della registrazione. La mia prova è che non si può scrivere un requisito trasversale che spieghi completamente ciò che questo aspetto dovrebbe fare: è specifico per ogni caso, perché lo scopo di scrivere il log è riflettere ciò che sta accadendo con il logica, e la logica in ogni metodo dovrebbe essere ragionevolmente unica (vedi DRY ).

In altre parole, esiste una dipendenza logica inestricabile tra la scrittura dei registri e le cose scritte. Non puoi generalizzarlo.

Ma il controllo è

Se si dispone di una sorta di requisito di registrazione funzionale (ad esempio registrazione degli accessi a supporto di un requisito non-recessione ) quindi alcuni potrebbero argomentare (e sono d'accordo) che se ti trovi a dover eseguire queste scritture di registro nel mezzo di un metodo, non hai strutturato il tuo codice in un modo che sia coerente con il pensiero orientato all'aspetto. In tal caso, dovresti estrarre il codice in metodi separati finché non ottieni il livello di granularità di cui hai bisogno.

    
risposta data 17.03.2017 - 17:48
fonte

Leggi altre domande sui tag