Argomento precedente: Case study 15: metriche di gruppoArgomento successivo: Case study 17: funzionalità integrata


Case study 16: modelli di progettazione di business logic

Sono disponibili diversi modelli di progettazione, utilizzabili in molte business logic. I modelli di progettazione sono testati e il loro impiego, quando applicabile, consente di guadagnare molto tempo e nella maggior parte dei casi di creare una business logic più efficace. Questo case study esamina in particolare un modello di progettazione.

Modello di progettazione dei contatori di aggiornamento

Questo modello di progettazione è utile quasi in ogni business logic progettata per misurare il tempo tra determinati eventi. Esempi di tale business logic sono business logic per la misurazione di disponibilità, tempi di inattività, tempo medio tra due errori, tempo medio di ripristino, tempo medio di risposta, tempo medio di risoluzione, percentuale di componenti con disponibilità inferiore a X, numero di casi non risolti in tempo, ecc.

La parte in comune tra tutte queste business logic è che il rispettivo risultato dipende dal valore di data/ora di vari eventi ricevuti.

Una regola pratica per stabilire se la business logic possa trarre vantaggio dal modello di progettazione sarebbe: se la business logic dipende dal valore di data/ora dei diversi eventi ricevuti, molto probabilmente è necessario utilizzare questo modello di progettazione.

Struttura di questo modello di progettazione

È possibile suddividere il codice di business logic che utilizza questo modello in due parti: un framework e un'implementazione. Il framework contiene il codice che nella maggior parte dei casi è fisso e non cambia per le diverse business logic. Questa parte è la stessa per il calcolo della disponibilità e del numero di ticket non risolti in tempo. L'implementazione contiene il codice specifico per ciascuna business logic.

Si consiglia di impostare queste due parti del codice in moduli di business logic distinti e di riutilizzare il modulo del framework in metriche diverse.

Di seguito viene riportato il codice del framework:

Dim g_PrevEventTimestamp

Sub OnLoad(time)
     g_PrevEventTimestamp = time
     InitializeStatusVariables
End Sub

Sub OnRegistration(Dispatcher)
     ' Se è presente una copia separata di variabili di stato 
     ' per ogni risorsa registrata a seconda delle risorse 
     ' registrate è necessario impostare i valori iniziali sulle
     ' variabili di stato delle risorse appena aggiunte qui
End Sub

Sub OnPeriodStart(time)
     InitializeCounters
End Sub

Sub OnPeriodEnd(time, completePeriod)
     HandleEvent (time)
End Sub

Sub OnTimeslotEnter(time)
     HandleEvent (time)
End Sub

Sub OnTimeslotExit(time)
     HandleEvent (time)
End Sub


Function Result()
     Result = CalculateResult()
End Function

Sub HandleEvent(Time)
     Dim diff
     diff = TimeDiff( "s",Time,g_PrevEventTimestamp)
     UpdateCounters(diff)
     g_PrevEventTimestamp = Time
End Sub

Di seguito è riportata la struttura di un modulo di implementazione:

' Definire le variabili di stato qui. Può trattarsi di una 
' variabile globale semplice o di tante variabili globali complesse
' a seconda della business logic
Dim g_StatusVar_1, g_StatusVar_2, ... ,g_StatusVar_n

' Definire i contatori qui. 
' Può trattarsi di una variabile globale semplice o di tante
' variabili globali complesse a seconda della business logic
Dim g_Counter_1, g_Counter_2, ... , g_Counter_n

Sub InitializeStatusVariables ()
     ' Impostare i valori iniziali per le diverse variabili di stato
End Sub

Sub InitializeCounters ()
     ' Impostare i valori iniziali per i vari contatori
     g_Counter_1 = 0
     g_Counter_2 = 0
     '...
     g_Counter_n = 0
End Sub

Function CalculateResult ()
     ' Calcolare il risultato. Il risultato deve dipendere
     ' dai valori dei contatori. Non deve dipendere
     ' dal valore delle variabili di stato. Non deve 
     ' modificare i valori dei contatori o le variabili 
     ' di stato
End Function

Sub UpdateStatus(method, eventDetails)
     ' Aggiornare il valore delle variabili di stato in base
     ' ai parametri (e possibilmente al valore precedente delle 
     ' variabili di stato)
End Sub

Sub UpdateCounters(diff)
     ' Aggiornare i valori dei contatori in base al loro
     ' valore precedente, al valore delle variabili di stato
     ' e al valore del parametro diff.
     ' In molti casi questo calcolo si basa anche sul
     ' valore di Context.IsWithinTimeslot
End Sub

Sub OnEvent_1(eventDetails)
     HandleEvent (eventDetails.Time)
     UpdateStatus(“OnEvent_1”,eventDetails)
End Sub

Sub OnEvent_2(eventDetails)
     HandleEvent (eventDetails.Time)
     UpdateStatus(“OnEvent_2”,eventDetails)
End Sub

'...

Sub OnEvent_n(eventDetails)
     HandleEvent (eventDetails.Time)
     UpdateStatus(“OnEvent_n”,eventDetails)
End Sub

Per spiegare meglio questo modello di progettazione, di seguito viene fornito un esempio dell'implementazione del modello per il calcolo della disponibilità. Questo esempio presuppone la presenza di eventi per stati UP (Attivo) e DOWN (Non attivo) gestiti da due diversi gestori di eventi nella business logic. La disponibilità è definita come la percentuale di tempo durante il quale il sistema è attivo rispetto al tempo totale nel periodo di applicazione. Si presuppone che lo stato del sistema sia lo stato dell'ultimo evento ricevuto (UP (Attivo) oppure DOWN (Non attivo)).

Di seguito viene riportato il codice dell'implementazione (il codice del framework non è stato modificato):

' Variabile di stato
Dim g_Status
' Contatori.
Dim g_UpTime, g_TotalTime

Sub InitializeStatusVariables ()
     G_Status = “UP”
End Sub

Sub InitializeCounters ()
     g_UpTime = 0
     g_TotalTime = 0
End Sub

Function CalculateResult ()
     If g_TotalTime = 0 Then
          CalculateResult = Null
     Else
          CalculateResult = g_UpTime/g_TotalTime*100
     End If
End Function

Sub UpdateStatus(method, eventDetails)
     If method = “OnUP” Then
          G_Status = “UP”
     Else
          G_Status = “DOWN”
     End If
End Sub

Sub UpdateCounters(diff)
     If Context.IsWithinTimeslot Then
          G_TotalTime = g_TotalTime + diff
          If g_Status = “UP” Then
               G_UpTime = g_UpTime + diff
          End If
     End If
End Sub

Sub OnUp(eventDetails)
     HandleEvent (eventDetails.Time)
     UpdateStatus(“OnUp”,eventDetails)
End Sub

Sub OnDown(eventDetails)
     HandleEvent (eventDetails.Time)
     UpdateStatus(“OnDown”,eventDetails)
End Sub

Esistono diverse varianti di questo modello. Una delle varianti più comuni si ha quando un contatore di tempo separato deve essere sottoposto a manutenzione per diverse entità. Ad esempio, durante la misurazione del tempo di soluzione, un contatore separato deve essere sottoposto a manutenzione per ogni ticket aperto. In questo caso, durante la gestione di un evento pertinente solo a un ticket, è più efficiente aggiornare solo il contatore di tale ticket. Quando viene gestito un evento comune (ad esempio OnPeriodEnd o OnTimeslotEnter), è necessario aggiornare i contatori di tutti i ticket.

Nota: la variante del modello richiede la conservazione di una copia separata della variabile globale g_PrevEventTimestamp per ciascun ticket.

È possibile riscontrare alcuni esempi ottimali di utilizzo di questo modello nel contenuto predefinito. Tenere presente, tuttavia, che nel contenuto predefinito questo modello è utilizzato in modo un po' diverso e che la distinzione tra framework e implementazione non è così ovvia.