lunes, 27 de julio de 2015

1.6. Desarrollo de aplicaciones para dispositivos móviles.

El desarrollo de aplicaciones destinadas a dispositivos móviles, desde el punto de vista de la Ingeniería del Software, no debe diferir sustancialmente de los pasos a dar cuando se construyen aplicaciones para ordenadores de sobremesa o estaciones de trabajo.  Así, podríamos establecer los siguientes pasos previos:

Análisis de requerimientos.

El analista de turno deberá determinar, normalmente con varias entrevistas con los usuarios, las necesidades que estos tienen y los requerimientos que se les pedirán a la aplicación. Por ejemplo, en el caso de un análisis para una aplicación que se ejecutará en un dispositivo móvil, algunos de estos requerimientos generales pueden ser la facilidad de uso, que se pueda ejecutar en teléfonos móviles, PDAs y paginadores, que permita una conexión a una entidad mayor para obtener datos actualizados o devolver otros, o también, que sea capaz de almacenar cierta información de manera persistente.

Diseño de la aplicación. 

Es muy importante en este tipo de aplicaciones el crear programas separados por cada uno de los posibles usos que se le dé a la aplicación. De esta manera cada programa será más pequeño y se adaptará mucho mejor a las características de los dispositivos móviles.  Por tanto, a la hora del diseño nos plantearemos esta tarea seriamente, pues finalmente serán varias las ventajas de hacerlo así. Ya en la fase de implementación se tendrá que establecer un mecanismo que controle las diferentes aplicaciones.

 En cuanto al diseño del interfaz de usuario, debemos decidir  la correspondencia entre la aplicación y la pantalla. Los diseñadores en esta fase no deben considerar cómo los usuarios operarán con el dispositivo para llevar a cabo una tarea, o cómo se notificará a la aplicación las acciones del usuario. Se deben concentrar sólo en el objetivo de la pantalla y en la tarea que permitirá llevar a cabo.  Sun recomienda en esta etapa que se haga un "story board" conteniendo en cada viñeta los requerimientos para la pantalla correspondiente. En otra fase se decidirá qué tipo de controles vamos a utilizar para realizar entradas de datos y cómo vamos a presentar la información. En este punto, las características generales en cuanto a pantalla del dispositivo pueden marcar claramente el tipo de diseño de interfaz: lo que en uno se puede disponer en una única pantalla, en otro podremos necesitar varias.

El almacenamiento persistente es un aspecto a tener en cuenta en nuestro diseño. La pregunta a responder es: ¿qué datos deben sobrevivir a la finalización de la aplicación y estar disponibles para la siguiente vez que se vaya a ejecutar? Otra cuestión, que no se debe plantear en esta fase sino en la de implementación es qué utilizar para realizar ese almacenamiento. Una primera respuesta es aquel formato que se emplee para enviar y recibir datos entre el dispositivo J2ME y el sistema externo. Con esto evitamos una fase de conversión de formatos. Si el dispositivo posee sistemas de ficheros, entonces podemos optar por la creación de un fichero con una estructura más o menos compleja y usar las bibliotecas de Java para acceder a ellos. Otra alternativa también puede ser emplear sistemas de gestión de bases de datos relacionales, aunque en el caso de tener que tener que almacenar un gran volumen de datos y realizar gran cantidad de accesos.

Finalmente, debemos tener en cuenta dentro del diseño aspectos relacionados con la conectividad y con la entrada / salida, ya que son puntos muy importantes que van a determinar la portabilidad de la aplicación.  Por tanto, en este momento deberemos tomar decisiones en un nivel de abstracción alto, que luego se concretarán cuando determinemos claramente el tipo de dispositivo y sus prestaciones.

Implementación de la aplicación.

Esta etapa vendrá marcada por la elección del lenguaje, plataforma y herramientas de desarrollo (depuradores, entornos integrados,...). Con J2ME, teniendo en cuenta tipo de dispositivo con el que vamos a trabajar, decidiremos la configuración y perfil más adecuados.

Los pasos a seguir en esta fase hasta instalar el programa en el dispositivo serían los siguientes:
  • Escritura del código.
  • Compilación de la aplicación.
  • Eliminación de información de clases innecesaria (obfuscate). Esta etapa es opcional y en ella se renombran clases, métodos, interfaces, con objeto de hacerlo ambiguo. Un paquete obtenido de esta fase lo protege de la descompilación y de la ingeniería hacia atrás. Además, reduce el tamaño de los ficheros de clase, dando lugar a ficheros JAR más pequeños.
  • Ejecución del preverificador para añadir la información de "clase verificada" a los ficheros de clase.
  • Empaquetamiento de la aplicación: creación del fichero JAR y JAD.
  • Ejecución en un emulador apropiado.
  • Instalación en el dispositivo y ejecución. En este caso existen dos modos de hacerlo: en el primero, se descargará la aplicación a través de una conexión de red, se cargará en memoria, se ejecutará la aplicación, y finalmente se eliminará cualquier traza de ésta en el dispositivo; en la segunda, y siempre que el dispositivo lo permita, se instalará físicamente. En el entorno J2ME, Java Application Manager (JAM) es un gestor que controla la descargar, instalación, lanzamiento y desinstalación de aplicaciones en el dispositivo.

Algunos consejos para desarrollar aplicaciones con J2ME pueden ser los siguientes:
  • Evite ejecutar tareas computancionalmente intensivas en el dispositivo. Cuando sea posible, la alternativa más sencilla es hacer que una posible aplicación servidora en una máquina servidora sea la haga el cálculo y que la aplicación que corre en el dispositivo sólo se encargue de la gestión del interfaz y de mínimas operaciones.
  • Simplifique la aplicación, es decir, dejarla tan simple como sea posible, eliminando características superfluas. Esta decisión básicamente debe realizarse en tiempo de diseño. Si se va a necesitar un requerimiento sólo de vez en cuando, entonces lo mejor es desarrollar una segunda aplicación auxiliar que la contenga, dando la oportunidad a los usuarios a que puedan eliminar dicha aplicación si no la necesitan.
  • Escriba aplicaciones más pequeñas (Smaller is better) ya que consumirá menos memoria, requerirá menos tiempo de instalación y de inicialización al ser ejecutada. Un aspecto para alcanzar este fin es el de reducir el número de clases de la aplicación.
  • Utilice menos  memoria en tiempo de ejecución. Para ello podemos considerar el uso de tipos escalares en sustitución de objetos más complejos siempre que sea posible, como son int y boolean, por ejemplo, ya que cada vez que construimos un tipo, el constructor entra en funcionamiento reservando el espacio de memoria requerido para alojarlo. También otro consejo en este sentido es alojar objetos cuando realmente sea necesario (lazy instantiation). Así, cuando vayamos a utilizar un objeto podemos preguntar previamente si ha sido creado o simplemente apunta a null.
  • Libere los recursos del programa tan pronto como se acaben de utilizar.  Una vez que se finalice el uso de conexiones a bases de datos, a la red, a ficheros, etc., liberarlos, ya que dejaremos libre la memoria que implica su gestión y se pondrán a disposición de otras aplicaciones.
  • Reutilice objetos en lugar de continuamente crearlos y abandonarlos.  La idea, por tanto, es escribir métodos de inicialización  de objetos y también de dejarlos en un estado neutro para posteriormente poder emplearlos en otros menesteres.
  • Evite excepciones cuando se pueda, ya que redundará en la reducción del tamaño de los ficheros de clase y el número de objetos que se alojen en memoria. Siempre que se pueda solventar el problema de otra forma es mejor.
  • Utilice variables locales, ya que es más lento acceder a un miembro de una clase que a una variable local.  Por ejemplo, si accedemos a una variable miembro dentro de un bucle una y otra vez, será conveniente asignar el miembro a una variable local, que se almacenará en la pila, y acceder continuamente a ella.  También es útil esta técnica para operar con elementos de un vector en vez de acceder directamente por medio del vector.
  • Evite concatenación de cadenas de caracteres debido a que se emplea un par de llamadas a métodos de la clase String más la del constructor correspondiente. Esto lo tenemos que tener más en cuenta, aún si cabe, si se hace en un bucle.
  • Emplee hilos. Por norma general, todas aquellas operaciones que lleven más de una décima de segundo deberían ejecutarse en un hilo separado, de tal forma que no se bloquee el interfaz de usuario, aspecto muy importante en los dispositivos móviles.

No hay comentarios.:

Publicar un comentario