« Junio 2007 | Inicio | Agosto 2007 »

Julio 27, 2007

Hello World con AIR y Aptana

Abrimos nueva categoría en el blog, dedicada a AIR, con un post sencillo, en el que vamos a instalar todo lo necesario para comenzar a desarrollar aplicaciones AIR basadas en html y javascript.

Por "todo lo necesario" se entiende las siguientes tres cosas:

  1. AIR runtime.
  2. AIR SDK.
  3. Aptana.

Una vez descargados tanto el runtime como el SDK se debe proceder a su instalación. La instalación del runtime la realiza un instalador

Instalador Air 1

Mientras que la del SDK ha de hacerse a mano. En mi caso particular, he copiado los archivos que se encontraban en el dmg, en una carpeta dentro de mi estructura de directorios dedicada al código fuente. En concreto, la ruta del SDK será: /Users/ctarda/Subversion/airSDK

Una vez instalados el runtime y el sdk, es el momento de instalar y arrancar Aptana. Al terminar de arrancar, se presenta una pantalla de bienvenida, con enlaces directos a las descargas del runtime y el sdk, enlaces que ya no son necesarios.

Sin embargo, sí hay que instalar el plugin de AIR para Aptana. Al hacer clic en el paso rotulado con un 3 en la pantalla de bienvenida, se pasa a la típica pantalla de descarga e instalación de plugins de Eclipse.

Instalador Support

Una vez seleccionado el plugin de AIR, no hay más que hacer clic en siguiente, y seguir las instrucciones. Tras la instalación, será necesario reiniciar el workspace de Aptana.

Tras el reinicio, hay que configurar el entorno para indicarle la localización del SDK. Se puede conseguir haciendo clic en la opción correspondiente de la pantalla de bienvenida, o en el menú Ventana-Preferencias, seleccionando en la ventana que se abre Aptana-Air SDKs. Debe añadirse la ruta del SDK previamente instalado.

Configsdk

Ya ha llegado el momento de crear un nuevo proyecto. En este caso, el nombre del proyecto ha sido HelloWorld, y el framework JS seleccionado ha sido prototype

Nombre Proyecto

Seleccionado Prototype

A continuación, Aptana genera los ficheros necesarios para que el proyecto pueda ser ejecutado en el runtime AIR. Si se hace una pequeña modificación en el código fuente:
Codigo

Y se ejecuta el proyecto:
Ejecutar

Se puede comprobar cómo todo funciona como se espera.

Funcionando

Ahora es cuando ya se puede empezar a trabajar.

Modelo-Vista-Controlador en AS3

El objetivo:
Mi objetivo es mostrar un ejemplo de implementación del modelo-vista-controlador, que sirva para ilustrar algunas de las novedades más importantes en la última revisión (aunque en este caso casi debería hablarse de reinvención) de ActionScript.

Para ello, voy a implementar uno de las dos aplicaciones de ejemplo que solemos utilizar habitualmente: un reloj. En este caso, un reloj muy sencillo, que va a mostrar una cuenta creciente de segundos, pero que también va a proveer un botón para poder pausar su operación. Por favor, tómese la aplicación como una prueba de concepto, como un vehículo, una herramienta para intentar facilitar la comprensión de lo verdaderamente importante, el idiom.

Reloj Funcionando
Como puede verse en la imagen, el desarrollo de interfaces no es el punto fuerte de los aquí presentes.

La arquitectura
El modelo-vista-controlador se ha revisado por aquí con anterioridad. Para no repetirme demasiado, simplemente me voy a permitir mostrar el siguiente gráfico que permite comprender en su totalidad la arquitectura:

Mvc Diagrama

El concepto es sencillo. Se divide la aplicación en tres capas. Una de ellas (la vista) será la encargada de gestionar la interfaz y todo lo relacionado con la interacción entre la aplicación y el usuario, otra (el modelo) será la encargada de hacer el trabajo real de la aplicación, y la última (el controlador) sirve para desacoplar ambas, de forma que, si fuera necesario, una vista pueda ser actualizada por varios modelos, o un modelo pueda proveer de datos varias vistas.

La comunicación entre el controlador y la vista se hace por push en ambos sentidos. Entre el modelo y el controlador, sin embargo, se hace por push cuando es el controlador el que necesita del modelo, y por eventos cuando es el modelo el que quiere notificar algo a la(s) vistas.

Se puede discutir sobre si ésta implementación es la canónica del mvc o no, pero, sinceramente, eso es, por un lado, tema para otro post diferente, y por otro, una discusión similar a la del sexo de los ángeles. Mi opinión personal es que los patrones, como prácticamente todo en esta vida, desde la ropa al sillín de la bicicleta, deben adaptarse a las necesidades y gustos del que los utiliza. En mi caso, ésta es la implementación que más me satisface, la que mejores resultados me da, la que más fácilmente puedo implementar en diversos lenguajes, y por tanto, la que yo utilizo.

Los detalles de implementación
De la arquitectura anterior puede desprenderse que la cadena de eventos de la aplicación será la siguiente:

  1. Creación del controlador
  2. Creación de la vista, y paso de una referencia de la misma al controlador
  3. Creación del modelo desde el controlador
  4. Inicialización del sistema de eventos para las notificaciones emitidas por el modelo
  5. Arranque del modelo.

El controlador, por tanto, dada su función de capa de abstracción entre el modelo y la vista, deberá mantener una referencia a ambos. Además, deberá ser capaz de escuchar los eventos emitidos por el modelo.

La gestión de eventos
Una de las novedades de AS3 es la forma en la que se gestionan los eventos. Por fin, se ha racionalizado y estandarizado, y ya no hace necesario escribir a mano un sistema propio y racional de gestión de eventos, como ocurría hasta la fecha.

Básicamente, todo evento que se quiera emitir, debe extender de la clase flash.events.Event

La clase en la que especialice el evento a emitir simplemente debe llamar al construcor de su superclase, pasándole como parámetro una cadena de texto con el nombre por el que se quiera reconocer al evento creado.

Por tanto, en el ejemplo del reloj que estoy construyendo, si quisiera que se emitiera un evento desde el modelo, con el valor del tiempo transcurrido en el reloj hasta ese momento, lo podría hacer de la siguiente manera:

Evento

En el constructor de mi evento, paso dos valores como parámetro: el nombre del evento para el que voy a utilizar la instancia concreta de la clase, y el valor que quiero encapsular en dicho evento. Para facilitar en lo posible ese encapsulamiento, también proporciono un método público (getValue( ) ) que me permitirá utilizar ese valor en otros ámbitos de mi aplicación.

Paso el nombre del evento como parámetro, para, fundamentalmente, ilustrar mi ejemplo. En cualquier caso, al arrancar el modelo de la aplicación, voy a emitir un evento con un nombre distinto al que emitiré con cada pulsación del reloj. ¿Por qué? Básicamente porque me apetece, porque no me parece deban manejarse la inicialización del reloj y las pulsaciones del mismo con el mismo evento, porque no son la misma cosa.

Por eso, en el modelo voy a declarar dos constantes diferentes que voy a utilizar para crear los dos eventos. Puede no ser el mejor lugar para hacerlo, ciertamente, pero creo que para un ejemplo como éste, con sólo dos eventos, no es necesario complicarse más:

Modelo1

En la implementación del método start( ) (el que se manda ejecutar desde el controlador cuando se arranca la aplicación) puede verse la forma en la que se crea el evento llamado onStartEvent, que puedo construir de dos maneras: utilizando una instancia de la clase TickEvent, y pasando a esa clase el valor de counter en ese momento (que al iniciarse el reloj es cero), o simplemente como un evento genérico, sin más especialización de su nombre. En este caso, sigo el segundo camino, y hago que sea la vista la que presente un cero como valor inicial. ¿Mal hecho? Sí. Pero como soy consciente de haberlo hecho mal, siempre lo puedo refactorizar...

En las dos últimas líneas de la captura anterior se pude observar cómo funciona el mecanismo de escucha de eventos, que puede verse como una mezcla de las delegaciones y de la escucha de eventos utilizada en AS2. Al registrarse a un emisor de eventos, se elige el nombre del evento a escuchar (en este caso, el declarado en la clase flash.utils.Timer con la constante TIMER) y se elige el callback que escuchará el evento (en este caso el método onTimeTick).

Ontimetick

Al recibirse la notificación del evento, que es del tipo TimerEvent, el modelo de la aplicación emite otro evento, hacia aquellos que se hayan registrado para escucharle, que es una instancia de TickEvent, esta vez, con nombre onTimeTick.

Para que el modelo pueda emitir eventos, debe extender de flash.events.EventDispatcher, como así ocurre.

El controlador, que ha sido el responsable de crear el modelo, está registrado a los eventos que éste emite:

Controlador Listener

Eventos a los que se registra, utilizando para identificarlos las constantes que contienen sus nombres, y que fueron declaradas en el modelo.

El resto del flujo de eventos de la aplicación es sencillo. Con cada pulsación del reloj agregado al modelo (la instancia de flash.utils.Timer), se emite un evento que recibe el controlador, evento del que se extrae el valor del temporizador, para ser trasladado a la vista, que es la que lo presenta en pantalla:

Alavista

La vista dibuja un gráfico para ser utilizado como botón. Como ese gráfico sólo se va a utilizar para capturar los clics que se hagan sobre él, no tiene sentido que sea un movieclip, sino que basta con que sea una instancia de Sprite:

Elsprite

Como puede verse, la forma de gestionar los eventos de ratón es la misma que con el resto de eventos. Una vez creados el Sprite y un campo de texto para presentar el valor del temporizador, se añaden al dom, y listo.

¿Qué se ha conseguido con esta arquitectura? Aislar la funcionalidad real de la aplicación (el temporizador) en una sola capa, en la que no se maneja nada relacionado con la interfaz ni con la interacción con el usuario. De esa forma, se tiene bien encapsulada esa funcionalidad, y se gana en modularidad, portabilidad y cohesión mientras que se reduce el acoplamiento con el interfaz. ¿Que se quiere cambiar completamente al interfaz para hacer que parezca un reloj de manecillas? Ningún problema, se cambia la vista y solucionado.

El código completo del ejemplo puede descargarse en este enlace. Debería compilar sin problemas con Flash CS3. Trastea con él, léelo, verás que no es tan complicado como lo he hecho sonar.

Julio 18, 2007

No somos recursos

Somos personas. Algo que parece obvio, pero que desgraciadamente se olvida enseguida.

Y como personas que somos, queremos exactamente lo mismo que quiere todo el mundo: algo de respeto por nuestra persona, por nuestro trabajo, sentir que aprendemos algo, sentir que nuestro trabajo se valora un poco.

Si muchos departamentos de recursos humanos pasaran algo del tiempo que dedican a cuadrar Projects imposibles de cumplir preocupándose por hacer sentir a los machacas que su trabajo se valora, todos saldríamos ganando. Empezando por ellos, que son los que al final facturan lo que nosotros, los recursos, hacemos.

Julio 10, 2007

Código open source para Mac, ordenado por autor

Una lista de código, reutilizable y open source, ordenada y agrupada por el autor del mismo.

Mac reusable source code by author name

Julio 06, 2007

Aptana

Aptana es un entorno gratuito y open source, orientado al desarrollo de aplicaciones web basadas en AJAX.

Entre las funcionalidades del mismo están las pistas de código para JavaScript, HTML o CSS, o el potente debugger JavaScript.

En la última versión del entorno, se incluye un plugin para probar aplicaciones destinadas al iPhone, y soporte para el desarrollo de aplicaciones AIR.

Aptana es mutiplataforma, y se puede descargar en versiones para Windows, Mac OS X, Linux, y como plugin de Eclipse.

Más información en la web de Aptana.