Vorheriges Thema: Fallstudie 15: Geclusterte MetrikenNächstes Thema: Fallstudie 17: Integrierte Funktionalität


Fallstudie 16: Designmuster der Business-Logik

Es gibt mehrere "Designmuster", die in vielen Business-Logiken verwendet werden können. Diese Designmuster sind geprüft und ihre Verwendung, dort wo es möglich ist, kann viel Zeit sparen und in vielen Fällen zu einer effizienteren Business-Logik führen. Diese Fallstudie befasst sich schwerpunktmäßig mit solch einem Designmuster.

Designmuster "Zähler aktualisieren"

Dieses Designmuster ist in beinahe allen Business-Logiken hilfreich, die dafür vorgesehen sind, die Zeit zwischen bestimmten Events zu messen. Beispiele für derartige Business-Logik sind: Verfügbarkeitsmessung, Ausfallzeit, mittlere Zeit zwischen Ausfällen, mittlere Reparaturzeit, durchschnittliche Antwortzeit, durchschnittliche Bearbeitungszeit, Prozentsatz von Komponenten mit einer Verfügbarkeit kleiner als X, Anzahl von nicht rechtzeitig gelösten Fällen usw.

Diese Arten von Business-Logik haben gemeinsam, dass ihr Ergebnis vom Zeitstempel verschiedener Events abhängt, die sie empfangen.

Eine Faustregel dafür, ob Ihre Business-Logik von diesem Designmuster profitieren kann, ist: Wenn Ihre Business-Logik vom Zeitstempel der verschiedenen Events abhängt, die sie empfängt, sollte sie dieses Designmuster verwenden.

Aufbau dieses Designmusters

Der Code einer Business-Logik, die dieses Muster nutzt, besteht aus zwei Teilen: einem Rahmen und einer Implementierung. Der Rahmen enthält Code, der in den meisten Fällen vorgegeben und für die verschiedenen Arten von Business-Logik gleich ist. Dieser Teil ist für die Berechnung der Verfügbarkeit und der Anzahl von nicht rechtzeitig gelösten Tickets gleich. Die Implementierung enthält Code, der spezifisch für jede Business-Logik ist.

Es wird empfohlen, diese beiden Codeteile in separaten Business-Logik-Modulen zu nutzen und das Modul des Rahmens in unterschiedlichen Metriken wiederzuverwenden.

Code des Rahmens:

Dim g_PrevEventTimestamp

Sub OnLoad(time)
     g_PrevEventTimestamp = time
     InitializeStatusVariables
End Sub

Sub OnRegistration(Dispatcher)
     ' If there is a separate copy of status variables 
     ' for each registered resource depend on the registered
     ' resources you should set initial values to the
     ' status variables of the newly added resources here
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

Aufbau des Implementierungsmoduls:

' Define your status variables here. This can be one 
' simple global variable or many complex global variables
' depending on the business logic
Dim g_StatusVar_1, g_StatusVar_2, ... ,g_StatusVar_n

' Define your counters here. 
' This can be one simple global variable or many
' complex global variables depending on the business logic
Dim g_Counter_1, g_Counter_2, ... , g_Counter_n

Sub InitializeStatusVariables ()
     ' Set initial values to the various status variables
End Sub

Sub InitializeCounters ()
     ' Set initial values to the various counters
     g_Counter_1 = 0
     g_Counter_2 = 0
     '…
     g_Counter_n = 0
End Sub

Function CalculateResult ()
     ' Calculate the result. The result should depend on
     ' the values of the counters. It should not depend on
     ' the value of the status variables. It should not 
     ' change the values of the counters or the status 
     ' variables
End Function

Sub UpdateStatus(method, eventDetails)
     ' Update the value of the status variables based on
     ' the parameters (and posibly on the old value of the 
     ' status variables)
End Sub

Sub UpdateCounters(diff)
     ' Update the values of the counters based on their
     ' previous value, on the value of the status variables
     ' and on the value of the diff parameter.
     ' In many cases this calculation is also based on the
     ' value of Kontext.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

Um dieses Designmuster besser zu erklären, finden Sie hier ein Beispiel für die Implementierung dieses Musters für die Berechnung der Verfügbarkeit. In diesem Beispiel wird davon ausgegangen, dass Events für UP und DOWN vorhanden sind, die von zwei separaten Event-Routinen in der Business-Logik verarbeitet werden. Die Verfügbarkeit wird als Prozentsatz der Zeit angegeben, in der das System während der Gesamtzeit im Zeitfenster betriebsbereit ist. Der Status des Systems ist der Status des letzten empfangenen Events (UP oder DOWN).

Code der Implementierung (Code des Rahmens ist gleich):

' Status variable
Dim g_Status
' Counters.
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

Es gibt einige Variationen dieses Musters. Eine der gängigsten Variationen ist, dass ein separater Zeitzähler für unterschiedliche Entitäten verwaltet werden soll. Beispiel: Wenn Sie die Bearbeitungszeit messen möchten, sollte ein separater Zähler für jedes offene Ticket verwaltet werden. Wenn ein nur für ein Ticket relevantes Event verarbeitet wird, ist es in diesem Fall effizienter, nur den Zähler dieses Tickets zu aktualisieren. Wenn ein gängiges Event verarbeitet wird (wie "OnPeriodEnd" oder "OnTimeslotEnter"), sollten die Zähler aller Tickets aktualisiert werden.

Hinweis: Für diese Mustervariation muss eine separate Kopie der globalen Variable "g_PrevEventTimestamp" für jedes Ticket verwaltet werden.

Einige gute Beispiele für die Verwendung dieses Musters finden Sie in unseren vordefinierten Inhalten. Beachten Sie, dass dieses Muster in den vordefinierten Inhalten anders verwendet wird und die Trennung zwischen Rahmen und Implementierung nicht so deutlich ist.