AppDNA

Informes de Forward Path agrupados

En este tema se proporciona una descripción general de la funcionalidad avanzada de Forward Path que puede utilizar para agrupar aplicaciones por categorías definidas en el script (como la idoneidad para la implementación en una plataforma determinada) o por el grupo de aplicaciones AppDNA al que pertenecen las aplicaciones. Puede agregar valores de aplicación en el nivel de grupo (por ejemplo, para crear subtotales para cada grupo) y crear totales en el nivel de informe. Esto significa, por ejemplo, que si los grupos de aplicaciones representan unidades de negocio, puede crear un informe de Forward Path que agrupa las aplicaciones por unidad de negocio y muestre los subtotales de cada una.

Información general

La imagen siguiente muestra un fragmento de un informe de Forward Path en el que las aplicaciones se han agrupado en función de su estado de RAG para los informes de Windows 7 y App-V. Para cada grupo, se muestra el coste total de la corrección, junto con un recuento de las aplicaciones del grupo. Puede expandir cada grupo para ver las aplicaciones dentro. La fila total en la parte superior muestra los totales de todo el informe.

Imagen del informe Forward Path

Construiremos el caso de Forward Path que generó este informe en los ejemplos siguientes. Para que los ejemplos sean lo más simples posible, utilizaremos un coste de remediación codificado para cada aplicación. En la vida real, probablemente calcularía esto en función de la complejidad de la aplicación y la corrección que se requiere. Para ver un ejemplo que calcula los costes de esta manera, consulte Usar variables de la calculadora de esfuerzo en un caso de Forward Path.

Las funciones del caso

El caso de un informe de Forward Path agrupada suele implementar las siguientes funciones estándar de Forward Path de avance:

  • Initialize(): AppDNA llama automáticamente a esta función una vez al inicio del script. Normalmente, esta función inicializa variables.
  • ForwardPath(): Esta es la función estándar que deben implementar todos los casos de Forward Path. AppDNA llama a esta función una vez por cada aplicación que se selecciona al ejecutar el informe. En un informe de Forward Path agrupado, esta función crea categorías (denominadas grupos de informes) en las que se colocan las aplicaciones. Los grupos de informes se pueden crear mediante la lógica del código o pueden basarse en los grupos de aplicaciones que las aplicaciones ya pertenecen.
  • ProcessGroups(): AppDNA llama a esta función una vez por cada grupo de informes generado por la función ForwardPath(). Esta función define las columnas de informe de nivel de grupo y los valores que contienen.
  • GetGroupColumnSummary(): AppDNA llama a esta función una vez por cada columna definida en la función ProcessGroups(). Normalmente, esta función define los totales de nivel de informe.
  • OnProcessingComplete(): Esta es una función opcional que AppDNA llama una vez después de que todo el resto del procesamiento esté completo. Puede utilizar esta función para realizar cualquier procesamiento final antes de que se muestre el informe.

El siguiente diagrama muestra cómo AppDNA llama a las funciones al ejecutar el informe. El diagrama va seguido de la especificación de cada una de las funciones avanzadas, junto con un ejemplo que juntos crean el informe que se muestra en la sección Overview anterior.

Funciones avanzadas

Nota: Algunos de los ejemplos de este tema utilizan la notación de subrayado (_) para dividir líneas largas en dos o más líneas. Esto es para que los fragmentos de código de ejemplo se procesen correctamente cuando se incluyen en un PDF. Vea la Biblioteca MSDN para más información sobre esta notación.

Initialize()

Si se especifica en el caso, AppDNA llama automáticamente a la función Initialize() una vez al inicio del script. La función Initialize() debe tener la siguiente firma:

Public Overrides Sub Initialize()
   ' Enter your code here.
End Sub

En este ejemplo vamos a utilizar la función Initialize() para inicializar variables que vamos a utilizar para almacenar valores de aplicación para que puedan ser agregados a nivel de grupo. Sin embargo, primero debemos declarar las variables que queremos usar a lo largo del caso. Debido a que utilizaremos estas variables en más de una función, las definiremos al inicio del script (antes de la función Initialize()), así:

' Declare a Dictionary variable to store the remediation
' costs for each application in the group.
Private Dim costs As Dictionary(Of String, List(Of Integer)) _
   = New Dictionary(Of String, List(Of Integer))

' Declare string variables that store the names of the
' report groups.
Private Dim win7group As String = "Windows 7"
Private Dim appvgroup As String = "App-V"
Private Dim othergroup As String = "Retire"

En este ejemplo, hemos declarado una variable de diccionario llamada costes. Consulte la Biblioteca MSDN para obtener documentación de esta clase de.NET estándar. La variable de diccionario puede almacenar una colección de claves y valores. En este ejemplo, la clave es una cadena (que usaremos para almacenar el nombre del grupo de informes) y el valor es una lista de enteros (que usaremos para almacenar los costes de corrección para todas las aplicaciones del grupo de informes). Consulte la Biblioteca MSDN para obtener documentación de la clase List.

Además del diccionario, hemos declarado tres variables de cadena para almacenar los nombres de los tres grupos de informes que vamos a crear.

Ahora estamos listos para implementar la función Initialize(). Aquí está:

Public Overrides Sub Initialize()
   costs.Add(win7group, New List(Of Integer))
   costs.Add(appvgroup, New List(Of Integer))
   costs.Add(othergroup, New List(Of Integer))
End Sub

En este ejemplo, simplemente hemos agregado un elemento a nuestra variable de diccionario de costes para cada uno de nuestros tres grupos de informes. Hemos especificado las claves de elemento mediante las tres variables de cadena que declaramos anteriormente para almacenar los nombres de los grupos de informes.

ForwardPath()

La función ForwardPath() es la función estándar que todos los casos de Forward Path deben implementar. La función ForwardPath() debe tener la siguiente firma:

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output
      ' Enter your code here.
End Function

En este ejemplo, separaremos las aplicaciones en tres grupos de informes: agregamos aplicaciones que tienen un estado verde de Windows 7 RAG al grupo de informes “Windows 7”, agregamos aplicaciones que tienen un estado verde de App-V RAG al grupo de informes “App-V”, y agregamos el resto de las aplicaciones a un grupo de informes “Retirar”. Para cada aplicación, agregaremos un número aleatorio codificado en el diccionario para representar el coste de remediar la aplicación:

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output

   Dim result As New Output()

   ' Is the application green for Windows 7?
   If (currentApplication.Modules.Windows7.RAG = RAG.Green) _
     Then
      result.Outcome = "Windows 7 OK"
      result.RAG = RAG.Green
      result.Cost = 33

      ' Add the application to the "Windows 7" group.
      result.ReportGroups.Add(win7group)

      ' Add the remediation cost to the dictionary variable.
      costs.Item(win7group).Add(33)
   Else

      ' Is the application green for App-V?
      If (currentApplication.Modules.AppV.RAG = RAG.Green) Then
         result.Outcome = "App-V OK"
         result.RAG = RAG.Green
         result.Cost = 170

         ' Add the application to the "App-V" group.
         result.ReportGroups.Add(appvgroup)

         ' Add the remediation cost to the dictionary variable.
         costs.Item(appvgroup).Add(170)
      Else

         ' The application is not green for Windows 7 or App-V.
         result.Outcome = "Not suitable for migration."
         result.RAG = RAG.Red
         result.Cost = 713

         ' Add the application to the "Retire" group.
         result.ReportGroups.Add(othergroup)

         ' Add the replacement cost to the dictionary variable.
         costs.Item(othergroup).Add(713)
      End If
   End If

   result.Display.SourcePath.Visible = false

   ForwardPath = result

End Function

Tenga en cuenta que hemos usado If… Entonces… Declaraciones else para dividir las aplicaciones en los tres grupos de informes según el estado de RAG para los informes de Windows 7 y App-V. Podríamos haber basado los grupos de informes en el grupo de aplicaciones al que pertenecen las aplicaciones. Un ejemplo posterior de este tema le mostrará cómo hacerlo.

Nota: Es posible agregar la misma aplicación a más de un grupo. Si lo hace, cuando ejecute el informe, la aplicación aparecerá debajo de cada grupo al que se haya agregado y sus valores se agregarán en los totales de cada grupo. Esto puede provocar que los valores de la aplicación se agreguen al total del informe más de una vez. Según el informe, esto podría ser engañoso. Depende de usted como autor del script asegurarse de que las aplicaciones no se agreguen a más de un grupo a menos que sea su intención.

ProcessGroups()

Si se especifica en el caso, AppDNA llama a la función ProcessGroups() para cada grupo de informes generado por la función ForwardPath(). Normalmente se utiliza la función ProcessGroups() para definir las columnas que aparecen en el nivel de grupo en el informe Forward Path directa.

La función ProcessGroups() debe tener la siguiente firma:

Public Overrides Sub ProcessGroup(group As _
   ForwardPathReportGroup)
      ' Enter your code here.
End Sub

Observe que el objeto ForwardPathReportGroup se pasa a esta función. Representa el grupo de informes actual. Tiene dos propiedades: Name, que es unCadenaque almacena el nombre del grupo, y CustomColumns, que es un diccionario de cadenas. La propiedad CustomColumns se utiliza para especificar los nombres de las columnas que se muestran en el nivel de grupo y lo que contienen.

Aquí hay un ejemplo:

Public Overrides Sub ProcessGroup(group As _
   ForwardPathReportGroup)

   ' 1. Define a report group column to show the total
   ' cost for the applications in the group and format it
   ' as currency.
   group.Columns.Item("Cost").Value = _
      costs.Item(group.Name).Sum()
   group.Columns.Item("Cost").Format = "{0:C}"
   group.Columns.Item("Cost").Culture = "en-US"

   ' 2. Define a report group column to show the number of
   ' applications in the group.
   group.Columns.Item("Count").Value = _
      costs.Item(group.Name).Count

   ' 3. Define a report group column that has a link to
   ' further information.
   group.Columns.Item("Link").Value = _
   "<a target=""_blank"" href=""http://www.google.com"">More information</a>"

End Sub

Observe que hemos definido tres columnas:

  1. Esto define la columna Coste, que muestra el coste total de corrección de las aplicaciones de cada grupo. Para obtener el coste total, estamos mediante el método List.Sum() para agregar todos los valores de coste almacenados para el grupo en la variable de diccionario de costes. La clase List tiene otras funciones de agregación que puede utilizar para obtener el valor promedio, mínimo o máximo (por ejemplo) almacenado para el grupo. Consulte la Biblioteca MSDN para obtener documentación de la clase List.

    Observe que hemos establecido la propiedad Format en la columna en {0:C} (que especifica que el valor es una moneda). Y hemos establecido la propiedad Culture en un valor de en-US para especificar que el símbolo de moneda es el símbolo del dólar estadounidense. Consulte Ordenar y dar formato a los informes de Forward Path para obtener más información sobre el formato de la salida.

  2. Esto define la columna Recuento, que muestra el número de aplicaciones de cada grupo. Esta vez estamos mediante el método List.Count() para obtener el número de elementos (que representan aplicaciones) almacenados para el grupo en la variable de diccionario de costes.

  3. Esto define la columna Enlace, que incluye código HTML que define un hipervínculo codificado. Este es un ejemplo demasiado simplista que demuestra que puede incluir código HTML en la columna.

Nota: AppDNA genera automáticamente una columna que muestra el nombre del grupo. Esto se llama la columna “Grupo”.

GetGroupColumnSummary()

Si se especifica en el caso, AppDNA llama automáticamente a la función GetGroupColumnSummary() para cada columna definida en la función ProcessGroups (), más la columna “Group” generada automáticamente (que almacena el nombre del grupo). La función GetGroupColumnSummary() debe tener la siguiente firma:

Public Overrides Function GetGroupColumnSummary(groupColumnName _
   As String) As String
      ' Enter your code here.
End Function

Observe que el nombre de la columna se pasa a la función como una cadena y la función devuelve una cadena, que es el texto que se inserta en la columna correspondiente en la fila total del informe.

Utilice la función GetGroupColumnSummary() para definir los valores de nivel de informe. Por ejemplo:

Public Overrides Function GetGroupColumnSummary(groupColumnName _
   As String) As String

   If groupColumnName = "Group" Then

      ' Put the text "Total" in the automatically-generated
      ' "Group" column.
      GetGroupColumnSummary = "<b>Total</b>"

   Else If groupColumnName = "Cost" Then

      ' Declare a variable to store the total cost.
      Dim sum As Decimal = 0

      ' Iterate through the costs variable to get the total cost.
      For Each key As String In costs.Keys
         sum += costs.Item(key).Sum()
      Next

      ' Format the total as currency.
      GetGroupColumnSummary = _
         String.Format(New _
            System.Globalization.CultureInfo("en-US"), _
            "{0:C}", sum)

   Else If groupColumnName = "Count" Then

      ' Declare a variable to store the overall count.
      Dim count As Integer = 0

      ' Iterate through the costs variable to get the total
      ' count.
      For Each key As String In costs.Keys
         count += costs.Item(key).count()
      Next

      GetGroupColumnSummary = String.Format(count)

   Else

      ' Leave the "Link" column blank.
      GetGroupColumnSummary = ""

   End If

End Function

AppDNA llama a esta función una vez para cada columna de grupo que definimos en la función ProcessGroups(), más la columna “Grupo” generada automáticamente. Por lo tanto, usamos un If… Entonces… Declaración else para probar qué columna se está procesando. Veamos lo que estamos haciendo para cada columna:

  1. Esta es la columna Grupo generada automáticamente. Para esta columna, simplemente estamos generando el texto "Total". Observe que hemos incluido el texto en <b></b> etiquetas. Estas son etiquetas HTML estándar que especifican que el texto debe mostrarse en negrita. Puede usar cualquier código HTML en cualquiera de las columnas.

  2. Esta es la columna Coste. Para obtener el total para el informe, declaramos una variable de trabajo. Luego iteramos a través de todos los elementos de la variable del diccionario de costes globales y agregamos sus valores totales a la variable de trabajo, que luego devolvemos.

    El valor devuelto es una cadena. Hemos utilizado el método String.Format() para dar formato al valor de coste como una moneda y hemos utilizado laCultureInfoclase para especificar el símbolo de moneda del dólar estadounidense. Consulte la Biblioteca MSDN para obtener documentación sobre el formato de cadenas.

  3. Para la columna Recuento, hemos utilizado una técnica similar para generar un valor total para el informe.

  4. Hemos dejado la columna Enlace en blanco.

Esto nos lleva al final del código en el caso que se utilizó para generar el informe de Forward Path que se muestra al principio de este tema. Más adelante en este tema aprenderemos cómo crear grupos de informes basados en el grupo de aplicaciones AppDNA al que ya pertenecen las aplicaciones.

OnProcessingComplete()

Si se especifica en el caso, AppDNA llama automáticamente al OnProcessingComplete() una vez que se haya completado el resto del procesamiento. Puede utilizar esta función para realizar cualquier procesamiento final antes de que se muestre el informe.

La función OnProcessingComplete() debe tener la siguiente firma:

Public Overrides Sub OnProcessingComplete()
   ' Enter your code here.
End Sub

Agrupar por el grupo de aplicaciones AppDNA

En esta sección, vamos a cambiar el caso para agrupar las aplicaciones según lagrupo de aplicacionesa la que ya pertenecen. Si alguna aplicación no es miembro de un grupo, aparecerá en una categoría Desagrupada.

Dentro del caso, puede averiguar a qué grupo pertenece una aplicación, a través de la propiedad Application.Groups. Las aplicaciones pueden pertenecer a más de un grupo. Tal como se indicó anteriormente, si agrega todos los grupos al informe, la aplicación aparecerá debajo de cada grupo al que pertenece. En consecuencia, dependiendo de cómo se autoría el script, existe la posibilidad de que los costes de corrección de aplicaciones se puedan agregar al total del informe más de una vez.

Estas funciones contienen comentarios detallados que explican cómo funcionan.

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output

   Dim result As New Output()

   If (currentApplication.Modules.Windows7.RAG = RAG.Green) Then
      result.Outcome = "Windows 7 OK"
      result.RAG = RAG.Green
   Else
      ' If the RAG for Windows 7 is not green,
      ' check if it's green for App-V
      If (currentApplication.Modules.AppV.RAG = RAG.Green) Then
         result.Outcome = "App-V OK"
         result.RAG = RAG.Green
      Else
         result.Outcome = "Not suitable for migration."
         result.RAG = RAG.Red
      End If
    End If

   ' We're temporarily using a hard-coded cost.
   result.Cost = 713

   ' Iterate through the groups to which the application
   ' belongs.
   For Each group As String In currentApplication.Groups

      ' Add the application to the corresponding report group.
      result.ReportGroups.Add(group)

      ' Check whether the group has already been added to our
      ' global dictionary variable.
      If costs.ContainsKey(group) Then

         ' Add the application's cost to the global variable.
         costs.Item(group).Add(713)
      Else

         ' Add the group to the global variable and then
         ' add the application's cost.
         costs.Add(group, New List(Of Integer))
         costs.Item(group).Add(713)

      End If
   Next

   ForwardPath = result

End Function

Public Overrides Sub ProcessGroup(group As ForwardPathReportGroup)

   If costs.ContainsKey(group.Name) Then
      group.Columns.Item("Count").Value = _
         costs.Item(group.Name).Count
      group.Columns.Item("Cost").Value = _
         costs.Item(group.Name).Sum()
      group.Columns.Item("Cost").Format = "{0,-10:C}"
      group.Columns.Item("Cost").Culture = "en-US"
      group.Columns.Item("Link").Value = _
      "<a href=""http://www.google.com"">More information</a>"
   End If

End Sub

Ocultar la visualización de grupos

A veces es posible que quiera mostrar un informe agrupado sin la agrupación. Para ello, utilice la propiedad ForwardPathReportSettings.DisplayGroups. Esta propiedad se establece automáticamente en true cuando se incluye código de control de grupo en el caso. Sin embargo, puede establecerlo explícitamente en falso en su caso para ocultar la visualización de los grupos en el informe.

El objeto Settings (que es de tipo ForwardPathReportSettings) está disponible en todo el caso. Normalmente se establece la propiedad en la función Initialize(), así:

Settings.DisplayGroups = false

Para volver a mostrar el grupo, basta con comentar esta línea.

Informes de Forward Path agrupados