Portar apps de escritorio a la web

Hay varias cosasa a tener en cuenta a la hora de crear una versión web de una aplicación de escritorio. Obviamente, no puedes utilizar el proyecto exactamente tal cual pero, con un diseño apropiado, sí es posible reutilizar (o incluso compartir) una cantidad significativa de código no relacionado con la interfaz de usuario (UI).

Esta entrada es una traducción al español del original disponible en la web de desarrolladores de Xojo y que se puede encontrar aquí.

Tipo de proyecto

En primer lugar, las aplicaciones de escritorio y las aplicaciones web tienen diferentes tipos de proyecto. No puedes cambiar el tipo de un proyecto de modo que para crear una aplicación web tendrás que crear un nuevo proyecto de aplicación web.

Interfaz de Usuario

La interfaz de usuario para una app web es completamente distinta a la interfaz de usuario de una app de escritorio. No todos los controles de una aplicación de escritorio tienen una equivalencia en controles Web (por ejemplo, el TabPanel), y no todas las características de los controles de escritorio están disponibles en los controles web (como pueda ser el ListBox). También hay unos cuantos controles web que no tienen un control de escritorio equivalente, como puede ser el Map Viewer.

Además, las appa web no tienen el concepto de una barra de mneú (Menu Bar), algo que está presente en prácticamente todas las apps de escritorio. Teniendo en cuenta estas diferencias es posible que precises reimplementar por completo la interfaz de usuario de una aplicación web usando para ello los controles disponibles de app web. Y cuando estés haciendo dicha operación también deberías de contemplar la necesidad de rediseñar ciertas cosas para que funcionen mejor en una app web.

Las páginas Web sustituyen a las ventanas

De modo general, cada ventana en una aplicación de escritorio puede rediseñarse como una página web en una app web. Se utiliza el método Show para mostrar diferentes páginas basadas en las acciones del usuario, similar al modo en el que se podrían mostrar ventanas adicionales. Recuerda que una app web sólo puede mostrar una página cada vez. Si tu app de escritorio precisaba mostrar varias ventanas abiertas de forma simultánea, entonces tendrás que repensar el diseño e implementar una alternativa.

Diálogos

En las aplicaciones de escritorio los diálogos pueden utilizar la clase MessageDialog o bien ser ventanas modales. En las apps web no están disponibles estas opciones. Para crear un diálogo en una aplicación web, has de añadir un Diálogo Web a tu proyecto e implementar sobre este el diseño que desees. Entonces has de añadir este diálogo web a la página o páginas sobre las que debería aparecer e invocarlo usando Show cuando sea preciso.

Cuando se cierre el diálogo se invocará su manejador de evento Dismissed, de modo que puedas determinar qué acción llevar a cabo.

A diferencia de los diálogos en las apps de escritorio, los diálogos web no son modales. Esto significa que se ejecutará el resto del código del método una vez que se invoque a Show para mostrar el diálogo.

Manejador de evento Show

En las aplicaciones de escritorio se suele utilizar con frecuencia el manejador de evento Open para realizar la configuración inicial de los controles o ventanas. En las aplicaciones web deberías utilizar en vez de ello el manejador de evento Shown.

Estilos

En las aplicaciones de escritorio, puedes modificar el estilo de un control cambiando sus propiedades de color, fuente, etc. Con las aplicaciones web puedes crear un Estilo Web con los ajustes que desees y aplicar dicho estilo al control.

Esto tienen la ventaja de que puedes utilizar el mismo estilo para todos los controles a lo largo y ancho de la app web. Si posteriormente necesitas cambiar algo en el estilo (por ejemplo el tamaño de la fuente), sólo has de hacerlo en un sitio (el estilo propiamente dicho) y dicho cambio se verá reflejado en todos aquellos controles sobre los cuales se haya aplicado en la app web.

También conviene que tengas en cuenta que puedes heredar los estilos web, permitiéndote así crear un nuevo estilo basado en las propiedades del estilo padre.

Usuarios múltiples

Una diferencia fundamental entre aplicaciones web y desktop es que las aplicaciones de escritorio están diseñadas para que las utilice sólo un usuario al mismo tiempo, mientras que las apps web están diseñadas para que sean utilizadas simultáneamente por varias personas.

Sesiones

El hecho de tener en cuenta múltiples usuarios significa que has de gestionar datos globales de forma diferente. En las aplicaciones de escritorio las propiedades y métodos públicos del obnjeto App son glonales para toda ala aplicación, lo cual suele resultar de utilidad.

En una aplicación web, el objeto App también es global para toda la aplicación, lo que significa que está disponible de forma global para todos los usuarios de la aplicación web. Por lo general este no será el comportamiento buscado. En vez de ello preferirás que los datos sean específicos para cada usuario (también conocido como Sesión) y que está conectado con la app web.

Por tanto, no querrás almacenar en el objeto App información global que es específica al usuario actual, como pueda ser el nombre de usuario y que se utiliza durante la conexión. En vez de ello, las aplicaciones web tienen un concepto denominado Sesión. Cada usuario que se conecta a la app web obtiene su propia sesión en forma de un objeto Session. Utiliza el objeto Session para gestionar información global que sea relevante sólo para el usuario. Por ejemplo, almacenar la nombre de usuario en una propiedad de Session significa que sólo es visible para dicho usuario.

Bases de datos

De igual modo, y en lo que respecta a las bases de datos, por los general las aplicaciones de escritorio mantienen una referencia global con la base de datos como propiedad del objeto App. En el caso de la aplicación web, deberías utilizar sin embargo el objeto Session para mantener la referencia a la base de datos. Cada usuario que se conecta a la aplicación web tendrá su propia conexión a la base de datos, de modo que las transacciones funcionen correctamente y que también se pueda aislar el acceso a la base de datos, y evitar también que sean visibles los datos de otros usuarios.

Por ejemplo, una aplicación de escritorio puede utilizar el manejador de evento App.Open para conectar con la base de datos una vez que se inicia la app, manteniendo la conexión como una propiedad pública DB a la que se pueda acceder desde cualquier parte de la aplicación como App.DB. En una app web deberías de realizar la conexión en el manejador de evento Session.Open y guardar la conexión en una propiedad pública DB de modo que se pueda acceder a esta desde la sesión como Session.DB.

En el caso de las aplicaciones de escritorio, si quieres permitir que múltiples usuarios puedan acceder a la base de datos (utilizando múltiples instalaciones de la aplicación desktop), entonces probablemente prefieras utilizar un servidor de bases de datos.

Con las aplicaciones web, es probable que no siempre quieras utilizar un servidor de base de datos. Dado que la aplicación web ya está funcionando sobre un servidor, en ocasiones SQLite es más que suficiente para gestionar cargas ligeras o medias de aplicaciones web.

Cookies

La mayoría de las apps precisan guardar las preferencias o ajustes de algún tipo. Con las apps web puedes hacerlo mediante el uso de las Cookies, una tecnología web que proporciona una vía para que los navegadores web puedan guardar ajustes que pueden ser solicitados por aplicaciones web. Por ejemplo, este código guarda el nombre de usuario como una Cookie:

Session.Cookie.Set("UserName") = UserNameField.Text

Log In

Anteriormente se mencionó brevemente el concepto de un nombre de usuario usado durante el acceso a la aplicación web. La mayoría de las aplicaciones web requieren del acceso por parte de un usuario, de modo que la app web sepa qué información debería de mostrar. Por lo general esta suele ser la primera página de la aplicacioón web. Esta información de acceso puede guardarse en la Session y almacenarse en Cookies para un acceso y recuperación rápidos.

Este código (en el manejador de evento Shownde la página) podría obtener la Cookie guardada y usarla para rellenar por omisión el campo correspondiente al nombre del usuario:

UserNameField.Text = Session.Cookie.Value("UserName")

Compartir código

Si tienes a mantenewr la mayor parte de tu código en los objetos de tu interfaz de usuario, entonces no podrás compartir el código entre los proyectos de escritorio y web. Pero si en vez de ello separas el código en clases que son llamadas por los objetos de la interfaz de usuario, entonces podrás compartir el código entre los proyectos de escritorio y web.

Por lo general se denomina esta práctica como el diseño de Modelo-Vista-Controlador. La Vista es la interfaz de usuario, ya sea web o de escritorio. Esta no se puede compartir. El modelo se corresponde con los datos. Este se puede compartir. El Controlador es la interface entre el Modelo y la Vista.

Usando este diseño en combinación con la compilación condicional te permite crear código que funciona tanto en apps desktop como web.

Ejemplo de Navegador

Este ejemplo sencillo utiliza una clase para abrir una nueva página web o una nueva ventana, en función del tipo de app.

Crea un nuevo proyecto desktop y añade una nueva clase, denominada Navigator. Añade un métood denominado ShownScreen2 con este código:

#If TargetWeb Then
WebPage2.Show
ElseIf TargetDesktop Then
Window2.Show
Endif

El anterior fragmento de código utilia compilación condicional para mostrar WebPage2 o bien Window2 en función de cual sea el tipo de app.

En Window1, añade un Button e incluye este código en su manejador de evento Action:

Dim n As New Navigator
n.ShowScreen2

Añade a continuación una nueva ventana (debería utilizar el nombre por omisión Window2). Deberías dar a esta ventana un título que indique “Ventana 2”, de modo que puedas saber cuando se ha abierto. Ejecuta el proyecto y haz clic en el botón de la ventana por defecto para ver como se abre Window2.

Now add a new Window (it should default to Window2 as the name). You should give this window a title that says “Window 2” so you know when it has opened. Run the project and click the button on the default window to see that Window2 opens.

Crea ahora un nuevo proyecto web. Añade un botón a WebPage1 y añade el mismo código a su manejador de evento Action:

Dim n As New Navigator
n.ShowScreen2

Copia ahora la clase Navigator desde el proyecto de escritorio al proyecto Web.

Por último, añade una segunda página web, denominada WebPage2. Proporciónale un título para que puedas saber cuando se abre. Ejecuta el proyecto y haz clic en el botón de la página web por defecto para ver como aparece la Página Web 2.

Acabas de crear una clase (muy sencilla) que puede utilizarse tanto en una app web como de escritorio. Esta técnica puede aplicarse a prácticamente lo que sea. El código que se refiere a objetos o características específicos de la web, deberían de incluirse en “#If TargetWeb”, y el código que es para las aplicaciones de escritorio debería de utilizar “#If TargetDesktop”.

You have now created a (very simple) class that can be used in either a desktop or web app. This technique can apply to just about anything. Code that refers to web-specific objects or features should be included in “#If TargetWeb” and code that is for desktop apps should use “#If TargetDesktop”.

Aunque estas usando la mismas clase Navigator, no estás compartiendo en realidad la misma clase exacta entre los dos proyectos. Los cambios realizados a Navigator en un proyecto no afectan al otro proyecto. Si quieres compartir exactamente la misma clase, de modo que los cambios realizados en un proyecto se reflejen en el otro, entonce necesitas usar un Item de Proyecto Externo, tal y como se describe en Compartir Código entre Proyectos.

2 comentarios en “Portar apps de escritorio a la web

  1. mauricio

    En la versión 2017R3 la asignación de la cookie no me funcionó asi:
    Session.Cookie.Set(“UserName”) = UserNameField.Text
    Por lo que tuve que usar:
    Session.Cookie.Set(“UserName”, UserNameField.Text)

    1. Javier Rodriguez

      Gracias Mauricio por tu aportación! Efectivamente, todo evoluciona a medida que Xojo lanza nuevas releases. Este tipo de apuntes son una gran ayuda para mantener actualizados los artículo! 😉

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *