存在多个可以用于多种业务逻辑的“设计模式”。 这些设计模式已进行测试,在适当时使用它们可以节省大量时间,并可在多数情况下创建更高效的业务逻辑。 此案例研究重点介绍其中一种设计模式。
更新计数器设计模式
在用于度量特定事件之间时间的几乎每种业务逻辑中,此设计模式都十分有用。 此类业务逻辑的示例为用于度量可用性、停机、故障平均间隔时间、平均还原时间、平均响应时间、平均解决时间、可用性少于 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 全局变量的单个副本。
在预定义内容中可以看到一些使用此模式的恰当示例。 但是切记在预定义内容中使用此模式稍微有些差异,并且框架和实施之间的分隔不是很明显。
| 版权所有 © 2012 CA。 保留所有权利。 | 就该主题发送电子邮件至 CA Technologies |