lunes, 3 de noviembre de 2014

Programación en Haxe: Estructura.

Cualquier lenguaje de programación necesita una estructura ordenada dentro del código para que al ejecutarse (o incluso cuando se compila) no produzca errores. Haxe no es la excepción a esto y se deben respetar ciertas reglas.

Vamos a ir conociendo Haxe a través de ejemplos, pero a su vez incorporando varios recursos externos para familiarizarnos con las funcionalidades que nos ofrecen.



El primero de ellos, es una nueva librería que debemos incorporar a nuestra biblioteca: HaxeUI

Esta librería contiene controles estándar (cuadros de texto, botones, construcciones de listas, etc.) muy similares a lo que un programador puede ver en Visual Studio por ejemplo. Existen muchas librerías con recursos similares para haxe, pero esta es una de las mejores que he encontrado.

Como siempre, lo primero que debemos hacer es instalarla: 

$> haxelib install haxeui

Nota: Si vienen siguiendo el blog, habrán visto que haxe hace uso de librerías externas casi de forma obligatoria. La mayoría son de dominio público y se encuentran en constante desarrollo. Para mantenerse al día con ellas, sugiero que de vez en cuando busquen actualizaciones. Esto puede hacerse fácilmente invocando haxelib con el parámetro upgrade.


Con cada actualización que haxelib encuentre, preguntará que hacer: Actualizar (y/n/a) que significa y (yes - Sí), n (no), a (abort - abortar).
Quizás antes de actualizar una librería sería aconsejable revisar las notas de las actualizaciones. Lamentablemente, para casi todas ellas nos encontraremos con que están escritas en inglés. 

Una vez instalada, abrimos FlashDevelop y comenzamos un proyecto nuevo (OpenFL). 

Mi idea, para comenzar, es un reproductor de audio. Vamos a ir por partes con el código para que se entienda que es lo que sucede en cada paso del programa.

En esta entrada, veremos un poco más en profundidad como está organizada la estructura de un proyecto.

Entonces: FlashDevelop -> Project -> New Project -> OpenFL project

Esta vez, en el explorador del proyecto nos vamos a encontrar con una estructura un poco distinta de la vista en el capítulo anterior.


Lo primero que vamos a notar es que tenemos una carpeta llamada "assets". Dentro de esta carpeta se van a alojar todos nuestros recursos que no pertenecen a una librería. Imágenes, sonidos, archivos de configuración, videos, animaciones, tipografías, etc.

Luego vemos que hay dos archivos nuevos: "openfl-readme.txt" y "application.xml"

El primero es simplemente un archivo de texto introductorio a la librería OpenFL. Describe varios aspectos generales de como debe usarse, formas de depuración, etc.

El segundo, contiene toda la información que el compilador va a utilizar para construir nuestro proyecto. Veamos que contiene haciendo doble click en él.

Desde ya que por la extensión sabemos en que código se encuentra..cosa que no vamos a tratar aquí. Para información sobre XML, pueden consultar la wiki.

Muchas de las librerías que vamos a ver, soportan XML para dar parámetros a sus funciones así que vamos a toparnos con él muy seguido.

El primer cambio que vamos a realizar en este archivo es el color de fondo a blanco (#ffffff) y los fps a 30 reemplazando la línea de código correspondiente.


<window background="#ffffff" fps="60" />

Además, vamos a introducir la librería que instalamos.


<haxelib name="haxeui" />


Nuestro código quedará mas o menos similar a este:





Guardamos el archivo y por el momento lo dejamos. Es momento de empezar a escribir algo de código en Haxe y para ellos abrimos el archivo "main.hx" que se encuentra dentro de la carpeta "src".

Vamos a borrar todo el contenido del archivo que esté por debajo del primer segmento de comentarios quedándonos algo similar a esto:





Como ya hemos visto anteriormente, todo programa en Haxe (asimismo cualquier otro lenguaje) va a necesitar un punto de partida (o entrada). Desde donde va a comenzar el programa y que caminos va a tomar, dependiendo de lo que nosotros le ordenemos.


También hemos visto que al ser un lenguaje orientado a objetos, cada estructura de código que escribamos, debe tener una forma especialmente determinada.

Haxe conoce 7 sistemas estructurales. Veamos la primera de ellas que vamos a usar.

Class:

La instancia (u objeto) class es la estructura de datos más utilizada en un programa escrito en Haxe. Cada clase debe ser definida con un identificador (un nombre), una ruta implícita y encerrado entre llaves ({..}) el código (o expresiones) perteneciente a su tipo. 

Comenzaremos entonces creando nuestra primer clase, que es a su vez el punto de entrada de nuestro programa. La clase main.


Inmediatamente debajo, escribiremos nuestro segundo sistema estructural que Haxe conoce: La función.

Una función por lo general es un compuesto de código al cual se le dan ciertos argumentos para que procese información y al terminar nos devuelva un resultado.
Cada función (o método) están identificadas por la palabra clave "function".

Deben poseer un nombre, pueden o no poseer argumentos que van a encerrarse dentro de paréntesis (), y por último pueden contener el tipo de dato que van a devolver al finalizar. Un ejemplo:

function resta (minuendo:float, sustraendo:float): float resultado{
        resultado = minuendo - sustraendo;
        return resultado;
}
                   

En este caso vamos a crear (dentro de la clase Main), la función con el mismo nombre (solo que esta vez todo en minúsculas). 


Puede observase que flashDevelop las ha diferenciado con colores distintos. si los nombres coincidieran en este caso, obtendríamos un error al ejecutar el programa (pueden probarlo con solo renombrar la función a "Main").

Vemos que también hay dos palabras claves delante de "function": ellos se conocen como modificadores de acceso. 

Por ahora dejaremos de hablar de estos dos modificadores para no generar confusión (los veremos más adelante). Lo importante es que este es el punto de entrada del programa.


Volvamos hacia el inicio del archivo ya que necesitamos incorporar a nuestro programa algunos módulos externos de la librería HaxeUI.

El uso de "import":

Es un atajo básicamente. Como vimos en entradas anteriores, cada módulo en haxe comparte el nombre con el archivo donde se encuentra. 

Si nosotros quisiésemos usar un módulo que no esta declarado en nuestro programa, deberíamos de utilizar la ruta completa de acceso al mismo para que el compilador lo encuentre. Por ejemplo si quisiéramos crear un nuevo objeto tipo botón la expresión completa sería algo como:

var busca:haxe.ui.toolkit.controls.Button = new haxe.ui.toolkit.controls.Button();

Al hacer uso de la instrucción import, toda la ruta hasta llegar al tipo definido externamente puede resolverse de forma más corta:

var busca:Button = new Button();


Cualquier ruta declarada con import tiene el siguiente orden de búsqueda por el compilador: paquete1.paquete2.paqueteN.modulo.tipo

Hay que tener en cuenta cuando se importan modulos externos, los nombres que le damos a las variables para que el compilador no encuentre un conflicto con declaraciones ambiguas.


En nuestro ejemplo, vamos a comenzar por importar el paquete de herramientas básicas de HaxeUI llamado Toolkit y el conjunto de colores que va a usar nuestro programa.

Entonces, incorporamos al código un par de nuevas líneas:

Como puede verse en la imagen, el uso de import, nos ha facilitado la tarea de escribir toda la ruta al momento de declarar una nueva instancia del objeto.

Incluso es mucho más simple de ver cuando se tienen muchas líneas de código.

Lo que hemos hecho básicamente dentro de la funcion main hasta ahora es declarar la paleta de colores que va a utilizar HaxeUI con todos los controles que agreguemos. Podríamos crear nuestro propio conjunto o estilo de colores, pero no tiene sentido en este momento. Para más información sobre ello, pueden consultar el enlace que se encuentra al principio (en inglés).

La segunda línea dentro de la función, llama a otra función (dentro del módulo toolkit, que se encarga de inicializarlo y dejarlo listo para usarse.

Si ejecutamos el código en este momento, no observaremos resultado alguno. En la próxima entrada, le damos forma a nuestra interfaz.