miércoles, 21 de noviembre de 2012

Optimización de llamadas dinámicas

Cuando programamos una aplicación para Smart Devices en GeneXus tenemos la posibilidad de utilizar llamadas dinámicas a objetos, lo que nos brinda una gran flexibilidad a la hora de desarrollar las funcionalidades de la aplicación.

Por ejemplo, podemos tener en un evento algo como lo siguiente :

Event 'MiEvento'
    Composite
        &objectName = GetObjectToCall.udp(&param1, &param2)
        call(&objectName)
    EndComposite
EndEvent

donde &objectName es una variable Character y GetObjectToCall es un procedimiento donde resolvemos la lógica sobre que objetos llamar.

Este esquema si bien nos trae muchas ventajas a la hora de desarrollar, tiene una desventaja importante y es que necesita procesamiento "server side" para determinar a que objeto llamar. O sea, si o si se necesita conectarse al servidor para continuar con la ejecución de la aplicación, no teniendo efecto el caché por ejemplo y haciendo que cualquier problema con la conexión haga que la aplicación deje de funcionar.


Veamos una forma de evitar esta situación con un ejemplo.

En la aplicación de la Liga MVD tenemos un panel donde se muestra información sobre un equipo en particular y en una de las pantallas se listan los partidos de dicho equipo, tanto los ya jugados como los que restan por jugar.


Es este panel se quiere que :

  • Si se hace Tap sobre un partido que ya se jugó: se muestre un panel con el detalle del partido, resultado, jugadores, goles, tarjetas, etc.
  • Si se hace Tap sobre un partido que todavía no se jugó: se muestre un panel con los detalles de la fijación del partido, cancha, día y hora y botones para poder agendarlo, avisar a un contacto o ubicar la cancha en los mapas.
  • Si se hace Tap en la fecha en que el equipo tiene fecha libre: no se hace nada.
Detalle de un partido ya jugado y de un partido pendiente.

Sin dudas que aqui tenemos un caso típico donde necesitamos utilizar llamadas dinámicas y para eso programamos la default action de la grilla de la siguiente manera:

Event 'Ver Partido'
    Composite
        &objectToCall = GetCallPartido.udp(EquipoId, JornadaNumero)
        call(&objectToCall)
    EndComposite
EndEvent

Donde el procedimiento GetCallPartido recibirá el código del equipo (&EquipoId) más la jornada seleccionada (&JornadaNumero) y nos devolverá en una variable Character el objeto a llamar (&objectToCall), y tendrá el siguiente código:

for each
where PartidoEquipoL = &EquipoId or PartidoEquipoV = &EquipoId
where PartidoJornadaNumero = &JornadaNumero
    if PartidoEstado = EstadoPartido.Jugado
        &objectToCall = 'sd:PartidoJugadoDetalle?' + PartidoId.ToString()
    else
        &objectToCall = 'sd:PartidoPendienteDetalle?' + PartidoId.ToString()
    endif
when none
    &objectToCall = ''  // Asi indicamos que no llame a nada
endfor

Ahora bien, con esta programación tenemos el problema mencionado: cada vez que haga Tap en una linea de la grilla se va a ejecutar el procedimiento del lado del servidor y por lo tanto necesito si o si tener conexión, incluso en el caso en que no tiene que llamar a nada. ¿Cómo evitamos esto?

La solución es cargar el llamado a realizar en la grilla y trasladar ese procesamiento "server side" del procedimiento GetCallPartido al evento Load de la grilla (que siempre se ejecuta "server side") y dejar la action 'Ver Partido' con código que se ejecute 100% del lado del dispositivo.
Los cambios que hay que realizar al código detallado anteriormente son:
  1. Agregar la variable &objectToCall a la grilla de partidos y ponerle Visible = false o incluirla en una celda con tamaño 0dip.
  2. Cargar la variable llamando al procedimiento en el evento Load

    Event Load
        &objectToCall = GetCallPartido.udp(EquipoId, JornadaNumero)
    EndEvent
  3. En la action 'Ver Equipo' simplemente hacer un call a la variable.

    Event 'Ver Partido'
        call(&objectToCall)
    EndEvent

    Esta action para funcionar no precisa ejecutar nada "server side" ya que ya tiene el valor de la variable cargada en la grilla y por lo tanto aunque no haya conexión el llamado se va a realizar igual. 
De esta manera optimizamos la experiencia del usuario en paneles que utilicen llamadas dinámicas, haciendo que la aplicación no sea tan "vulnerable" a problemas en la conexión con el servidor.

2 comentarios:

  1. que tipo es la variable objectToCall, si tengo un business component, en una aplicacion web, el resultado serai el mismo?

    ResponderEliminar