上一主题: 案例研究 15:组群的度量标准

下一主题: 案例研究 17:内置功能

案例研究 16:业务逻辑设计模式

存在多个可以用于多种业务逻辑的“设计模式”。 这些设计模式已进行测试,在适当时使用它们可以节省大量时间,并可在多数情况下创建更高效的业务逻辑。 此案例研究重点介绍其中一种设计模式。

更新计数器设计模式

在用于度量特定事件之间时间的几乎每种业务逻辑中,此设计模式都十分有用。 此类业务逻辑的示例为用于度量可用性、停机、故障平均间隔时间、平均还原时间、平均响应时间、平均解决时间、可用性少于 X 的组件百分比、未及时解决的案例数目等的业务逻辑。

所有这些业务逻辑的共同部分是它们的结果都取决于接收的各种事件的时间戳。

用于决定业务逻辑是否可以从此设计模式中受益的拇指规则为:如果业务逻辑取决于所接收的各种事件的时间戳,则很可能需要使用此设计模式。

此设计模式的基本架构

利用此模式的业务逻辑的代码可拆分为两部分:框架和实施。 框架包含在多数情况下得到修复且不会针对各种业务逻辑更改的代码。 此部分与可用性和未及时解决的故障单数目的计算相同。 实施包含特定于每种业务逻辑的代码。

建议将这两部分代码放入单独的业务逻辑模块中,并在其他度量标准中重复使用框架模块。

以下是框架代码:

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

以下是实施模块的基本架构:

' 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 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

为了更好地解释此设计模式,下面用一个示例来说明如何实施该模式来计算可用性。 此示例假定有“UP”(运行)和“DOWN”(停机)两种事件,由业务逻辑中的两个不同的事件处理程序来处理。 将可用性定义为时间百分比,其中系统在时间段的总时间中处于运行状态。 假定系统的状态为最后接收的事件的状态(UP 或 DOWN)。

以下是实施代码(框架代码不变):

' 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

在此模式上存在多个变量。 最常见的变量之一是需要为其他实体维护单个时间计数器的时间。 例如,在我们度量解决时间时,需要为每个打开的故障单维护单个计数器。 在处理仅与一个故障单相关的事件的情况下,只更新此故障单的计数器将更为有效。 在处理常见事件(例如,OnPeriodEnd 或 OnTimeslotEnter)时,需要更新所有故障单的计数器。

注意:此模式变量需要为每个故障单维护 g_PrevEventTimestamp 全局变量的单个副本。

在预定义内容中可以看到一些使用此模式的恰当示例。 但是切记在预定义内容中使用此模式稍微有些差异,并且框架和实施之间的分隔不是很明显。