Hay varios "patrones de diseño" que se pueden utilizar en muchas lógicas de negocios. Esos patrones de diseño se prueban y, si se usan cuando corresponde, pueden ahorrar mucho tiempo, además de, en la mayor parte de los casos, crear una lógica de negocios más eficaz. Este caso práctico se centra en un patrón de diseño.
Patrón de diseño de contadores de actualización
Este patrón de diseño es útil en casi todas las lógicas de negocios, que están pensadas para medir el tiempo entre determinados eventos. Los ejemplos de dichas lógicas de negocios son las lógicas de negocios para medir la disponibilidad, el tiempo de inactividad, el tiempo medio entre errores, el tiempo medio de restauración, el tiempo medio de respuesta, el tiempo medio de resolución, el porcentaje de componentes con una disponibilidad menor que X, el número de casos no resueltos puntualmente, etc.
El elemento común de todas esas lógicas de negocios es que su resultado depende de la marca de tiempo de los diversos eventos que reciben.
Una regla general para decidir si su lógica de negocios se puede beneficiar de este patrón de diseño sería: si las lógicas de diseño dependen de la marca de tiempo de los diversos eventos que la reciben, lo más probable es que deba utilizar este patrón de diseño.
Esqueleto de este patrón de diseño
El código de la lógica de negocios que utiliza este patrón se puede dividir en dos partes: un marco y una implementación. El marco contiene el código que en la mayoría de los caso es fijo y no cambia para las diversas lógicas de negocios. Esta parte es la misma para el cálculo de disponibilidad y el número de tickets no resueltos a tiempo. La implementación contiene código que es específico de cada lógica de negocios.
Se recomienda poner estas dos partes del código en módulos de lógica de negocios separados y reutilizar el módulo del marco en una métrica diferente.
Este es el código del marco:
Dim g_PrevEventTimestamp
Sub OnLoad(time)
g_PrevEventTimestamp = time
InitializeStatusVariables
End Sub
Sub OnRegistration(Dispatcher)
' Si hay una copia separada de las variables de estado
' para cada recurso registrado depende del registro
' recursos para los que debería fijar valores iniciales
' variables de estado de los recursos recientemente agregados aquí
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
A continuación, se presenta un esqueleto del módulo de implementación:
' Definir las variables de estado aquí. Puede ser una
' variable global simple o varias variables globales complejas
' dependiendo de la lógica de negocios
Dim g_StatusVar_1, g_StatusVar_2, ... ,g_StatusVar_n
' Definir los contadores aquí.
' Puede ser una variable global simple o varias
' variables globales complejas dependiendo de la lógica de negocios
Dim g_Counter_1, g_Counter_2, ... , g_Counter_n
Sub InitializeStatusVariables ()
' Establecer los valores iniciales a las diversas variables de estado
End Sub
Sub InitializeCounters ()
' Establecer los valores iniciales a los diversos contadores
g_Counter_1 = 0
g_Counter_2 = 0
'…
g_Counter_n = 0
End Sub
Function CalculateResult ()
' Calcular el resultado. El resultado debería depender
' del valor de los contadores. No debería depender
' del valor de las variables de estado. No se debería
' cambiar los valores de los contadores o
' las variables de estado
End Function
Sub UpdateStatus(method, eventDetails)
' Actualizar el valor de las variables de estado basándose en
' el parámetros (y posiblemente en el valor anterior de
' las variables de estado)
End Sub
Sub UpdateCounters(diff)
' Actualizar los valores de los contadores basándose en su
' anterior valor, en el valor de las variables de estado
' y en el valor del parámetro diff.
' En muchos casos este cálculo está basado también en
' el valor de 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
Para explicar mejor este patrón de diseño, a continuación se presenta un ejemplo de la implementación de este patrón para calcular la disponibilidad. Este ejemplo supone que hay eventos de actividad e inactividad que se manejan por dos controladores de eventos separados en la lógica de negocios. La disponibilidad se define como el porcentaje de tiempo durante el cual el sistema está activo a partir del tiempo total en la ranura de tiempo. Se supone que el estado del sistema es el estado del último evento recibido (activo o inactivo).
Aquí está el código de la implementación (el código del marco no se cambia):
' Estado variable
Dim g_Status
' Contadores.
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
Hay varias variaciones de este patrón. Una de las variaciones más comunes es cundo un contador de tiempo separado se debería mantener para entidades diferentes. Por ejemplo, cuando se mide el tiempo de solución, debería mantenerse un contador separado para cada ticket abierto. En este caso cuando se maneja un evento que es relevante solamente para un ticket es más eficaz actualizar solamente el contador de ese ticket. Cuando un evento común se maneja (como OnPeriodEnd u OnTimeslotEnter) los contadores de todos los tickets se deberían actualizar.
Nota: Esta variación del patrón requiere mantener una copia separada de la variable global g_PrevEventTimestamp para cada ticket.
Algunos buenos ejemplos del uso de este patrón se pueden ver en nuestro contenido predeterminado. Tenga en cuenta que este patrón se utiliza de forma un poco diferente en el contenido predeterminado y que la separación entre el marco y la implementación no es tan obvia allí.
|
Copyright © 2013 CA.
Todos los derechos reservados.
|
|