Proyecto Ceres

El círculo de Deming es una estrategia de mejora continua de la calidad. También tenemos DMAIC y Seis Sigma. Parece por tanto que la mejora continua de la calidad es importante dentro de cualquier proceso productivo.

DMAIC

Parte de mi software más exitoso de cara al público han sido las extensiones que he ido desarrollando para Firefox. Ayudan a la gente y además gano un dinerillo. Recibes feedback fácilmente e incluso me han propuesto ideas de desarrollo de nuevos complementos. Es algo agradable si sale bien, pero no he tenido tiempo últimamente para diseñar nuevas extensiones o mejorar las existentes. Así que algunas extensiones dejaron de ser tan funcionales y decidí que requerían pasar por un proceso de mejora continua de calidad. El Proyecto Ceres.

DMAIC-2

Este proyecto busca actualizar las extensiones para una mejor experiencia de uso. El registro de cambios es voluminoso, aunque en muchos casos la solución adoptada para un complemento es válida para otro.

Lista de cambios

  • DivTranslate
    • La API de ScaleMT había dejado de funcionar. Ahora se usa APY.
  • mozCleaner
    • Errores de escritura
  • The Super Clock
    • Pequeño fallo que hacía que horas con un cero delante no ocupasen lo mismo que las demás. Por ejemplo, 21:04 era representado como 21:4.
  • Google+ Share
    • Arreglar un fallo molesto que hacía que desapareciese el icono en algunas ventanas. Gracias a ismirth por decírmelo. Se actualizó a Australis.
    • Traducción de Google+ Share a diversos idiomas
    • Gestión analítica
  • No más 900
    • Nuevo complemento
  • Google+ Share for Android
    • Actualizar rutas a los módulos de Addon SDK
    • No interrumpir en las selecciones de texto. Se ha cambiado el lugar donde aparece el botón para no quitar la opción de seleccionar texto de Firefox.
  • Google AdSense Earnings
    • Nuevo complemento
    • Módulo en npm de identificación con Google via OAuth2
  • Bc.vc shortener
    • Nuevo complemento
  • DivHTTP
    • Traducciones
    • Ahora viene con su propia copia de httpd.js, puesto que ha sido retirado de Firefox
  • Divel Notepad
    • Traducciones

El objetivo con esto es elevar la calificación que tengo en AMO por encima de las 3 estrellas sobre 5 actuales que tengo. He recibido malas críticas en algunos de estos complementos que me gustaría intentar remediar.

La gestión de la memoria en Rust

Finalmente ha sido publicada la versión 1.0 de Rust. El lenguaje diseñado por Mozilla basado en 3 principios:

  • Seguridad
  • Concurrencia
  • Rendimiento

Hoy voy a hablar del primer principio, la razón principal para querer ser un sustituto de C++. Porque C++ está bien, pero puedes liarla mucho si no sabes lo que haces.

Rust

El concepto de dueño

En Rust todo tiene un dueño. No puede haber más de uno ni ninguno, debe ser uno exactamente.

Hasta aquí todo es sencillo. Ahora pasaremos la variable A a otra función.

El programa compila y nos da el resultado, que es 9. En los lenguajes de bajo nivel las variables pueden usar memoria del stack o del heap. Un pequeño repaso sobre sus diferencias.

Stack
  • Se reserva su espacio en RAM cuando el programa arranca
  • Son más rápidas de acceder
  • No se les puede cambiar el tamaño
  • Son más seguras
Heap
  • Se debe reservar manualmente la RAM cuando queramos
  • Son más lentas de acceder
  • Pueden cambiar su tamaño en tiempo real
  • Son menos seguras. Pueden dar lugar a fugas de memoria.

En este último caso, la variable A cuyo dueño es main() le pasa la propiedad temporalmente a sumar(). La propiedad se devuelve a main() rápidamente y esta garantizado que así suceda. El compilador lo permite. Veamos ahora un ejemplo más complejo.

Veamos ahora un código más complejo

Por supuesto el código compila pero este de aquí abajo no y solo he cambiado una línea.

La razón es que cuando creamos la estructura de App por primera vez le prestamos config a la estructura app. Así la función main no le puede pasar la propiedad a backup porque ya se la prestó a app.

Referencias

Para solucionar este problema Rust usa las referencias. Así la propiedad de config seguirá siendo main() pero lo podrán usar las estructuras app y backup. Para usar referencias usamos el símbolo &.

La estrucura ahora acepta &Config en vez de Config. Es de decir usa una referencia en vez de un valor. Sin embargo esto no compilará. El compilador normalmente deduce si es posible hacer una referencia a algo no existente, un fallo común en C++. En caso de tener dudas no compilará. Rust es bastante inteligente pero no es mágico. En el caso de la estructura App, es necesario indicar que la propiedad config vivirá el mismo tiempo que la estructura.

He usado la anotación de tiempo llamada a. Puedes poner cualquier nombre pero a es muy corto.

Implementaciones y referencias

Voy a introducir un concepto de Rust que son las implementaciones. Para haceros una idea rápida, serían como clases de C++, pero solo alojan funciones.

He creado dos funciones para implementar App. Son idénticas salvo por un pequeño detalle, una toma el valor self (como this en C++) por referencia y la otra toma el valor directamente.

Compila y funciona. Cambiemos el orden.

Ya no compila. La razón es que cuando llamamos a delete() estamos prestando app entera. Ahora delete() es la dueña de app y cuando salimos de la función eliminamos app porque si su dueña ha muerto, app también debe morir (no es tan sangriento como pensais). Rust lo detecta y delete() será la última función que podemos llamar de app. Por cierto si os preguntais como funcionan las implementaciones en Rust (que no son clases), este código haría lo mismo llamando a funciones estáticas. Quizá así veais mejor como se pasa el concepto de dueños y préstamos.

Diversión con punteros en el heap

Todo estas variables eran del stack que siempre es la manera más sencilla de operar. Vamos ahora a ver como funcionaría esto con punteros. Los punteros operan como variables en el stack que hacen referencia a partes de la memoria que están en el heap. En Rust podemos operar con punteros con máxima seguridad pues todo lo aplicable a variables en el stack sigue siendo válido. Solo hay un dueño y podemos hacer referencias, aunque quizá necesitemos marcar el tiempo de vida manualmente.

Ahora el valor 42 estará en el heap y con puntero podremos acceder a él. Sin embargo como es lógico, no podemos operar directamente con él.

Para operar el valor directamente tenemos que derreferenciarlo. Se usa *

Así que esta operación sería correcto. Nótese el uso de mut para permitir editar el valor. En Rust por defecto las variables no son mutables. Ese privilegio tiene que ser declarado por adelantado.

Como curiosidad mencionar que la macro println! (en Rust si algo termina con ! es una macro) acepta puntero o *puntero indistintamente ya que se da cuenta si es necesario derreferenciar o no.

El problema final

¿Qué pasaría si copiamos un puntero en otro? Pues como un valor en el heap solo puede tener un dueño, la propiedad será del último puntero.

Como curiosidad, este es un curioso método para bloquear en un determinado momento el acceso de escritura a nuestro puntero aunque es fácil volver a obtener el acceso a escritura con un nuevo cambio de dueño.

Conclusiones

Podemos ver que es un lenguaje que presta mucha atención a la seguridad. C++ es mucho más liberal en ese sentido y Mozilla cree que es un problema a la hora de desarrollar grandes aplicaciones. ¿Qué te ha parecido? Si tienes alguna duda no titubees y pregunta.

Crea tu propio lenguaje de programación

Esta entrada la escribí en DesdeLinux hace ya un tiempo y la quiero conservar aquí. La entrada no es la original sino que la he modificado para que siga vigente – MAYO DE 2015

LenguajesProgramacion

Después de escribir el primer artículo sobre cómo crear tu propio sistema operativo, alguien me dijo que si podía hacer un artículo sobre cómo crear un lenguaje de programación. Al principio no hice mucho caso, pero ahora y por otros caminos he aprendido bastante más sobre la creación de los lenguajes de programación. Así pues, vamos a hacer un lenguaje de programación básico, fácilmente empotrable en otros programas y que funcione con una máquina virtual que también diseñaremos. Hoy nos toca hacer la máquina virtual más básica.

Probablemente te preguntes: “¿una máquina virtual? ¿Pero eso no es muy difícil y además ralentiza los programas?” Al contrario, una máquina virtual simple es muy sencilla y relativamente rápida. He elegido Rust como lenguaje para la máquina virtual. Pero, ¿qué es Rust?

Rust es un lenguaje de programación que está enfocado en la seguridad en las ejecuciones, así que utilizándolo será prácticamente imposible que alguien consiga cerrar la máquina virtual. Es un lenguaje compilado en desarrollo creado por Mozilla. Servo, el sustituto de Gecko, se está desarrollando en él. Todavía puede cambiar su sintaxis pero el código que voy a usar va a mantenerse hasta la primera versión estable.

Rust se instala en Linux de manera sencilla. Antes se podía usar un PPA pero ahora el script de RustUp es muy bueno y se encarga de todo.

¿Cómo funciona una máquina virtual?

Si sabes como funciona el mundo en ensamblador es exactamente igual, con el stack o la pila. Si no, te lo explico. Imaginémonos el siguiente código:

El ordenador no entiende lo que significa 2+3, ni tampoco sabe qué orden hay que seguir. Los ordenadores funcionan con pilas o stacks en los que se van acumulando datos y se van sacando continuamente. Ese código en nuestra máquina virtual debería ser algo parecido a esto:

Básicamente, pondríamos el 2 en la pila en lo alto, el 3 también. ADD sacaría (es decir, lo elimina de la pila y obtiene su valor) los 2 últimos elementos de la pila y añadiría el resultado en lo alto de la pila. PRINT cogería el último elemento de la pila y lo usaría para mostrárnoslo. Ahora hagamos eso en Rust.

Ahora es cuando deberías descargarte el código fuente que está en GitHub. Voy a empezar por el archivo vm.rs

Primeramente deberemos definir un lenguaje para el Bytecode, podríamos usar uno ya existente como el de Java o el CLR de .NET/Mono, pero vamos a crear nosotros uno más básico.

Usamos notación hexadecimal para cada instrucción. Para hacer la traducción entre el código hexadecimal y la instrucción voy a usar la librería (crate en el argot de Rust) de enum_primitive. Antes se podía usar #[derive(FromPrimitive)] pero en Rust 1.0 no está disponible.

Ahora debemos hacer una función que ejecute cada una de esas instrucciones. Para ello debemos leer un byte y compararlo con las instrucciones que tenemos en la enumeración. Si se encuentra alguna que exista se debe ejecutar su acción.

Eso hacemos para leer cada byte individualmente y para ejecutarlas:

Como ven, diferenciamos si antes se nos dio la orden de PUSH (nuestra orden INTEGER), el siguiente byte será llevado completamente a la pila. Ahí estamos usando dos funciones que no les he enseñado, self.pop() y self.push(), que se encargan obviamente de manejar el stack.

No son muy complejas, pero la función de pop tiene mecanismos de detección de errores. De hecho, en Rust, si quitásemos esos mecanismos nos daría un error de compilación. Ahora simplemente debemos llamar en un programa a Perin (nuestra máquina virtual) y que ejecute un bytecode.

Ese bytecode puede ser leído de un fichero, pero aquí para simplificar lo he almacenado en una variable. Si lo ejecutamos nos dará el resultado esperado:

Todo el código está disponible en GitHub bajo la Apache License 2.0: https://github.com/AdrianArroyoCalle/perin. Para compilar deben tener Cargo instalado y poner:

Fliuva, o como crear un servicio de analíticas

Ya hemos visto los motivos que tengo para diseñar un servicio de analíticas desde 0. Ahora veremos como lo he hecho.
Fliuva

No he tocado ningún CSS.

La base de datos

En un servicio de analíticas lo más importante son los datos, así que debemos de definir como almacenaremos la información. En principio Fliuva iba a estar centrado en analizar una única aplicación. Más tarde he pensado en un soporte multiaplicaciones pero no lo voy a desarrollar de momento. Usaría un espacio de nombres delante de todas las tablas y las peticiones GET.

Usuarios = Sesiones

En ciertos servicios de analíticas los usuarios y las sesiones son dos conceptos diferentes. En Fliuva sin embargo, y por razones de simplificar la estructura, ambos conceptos son idénticos y hablaremos de ellos como sesiones.

Tablas

Será necesario tener una tabla de eventos.

Events

  • CATEGORY: Categoría del evento
  • SUBCATEGORY: Subcategoría del evento
  • NAME: Nombre del evento
  • DESCRIPTION: Descripción del evento
  • DATA: Datos del evento
  • ID: Identificador
  • TIME: Hora en que se produjo
  • SESSION: Sesión a la que pertenece el evento

[sql]

CREATE TABLE IF NOT EXISTS EVENTS(ID INT NOT NULL AUTO_INCREMENT, CATEGORY TEXT, SUBCATEGORY TEXT, NAME TEXT, DESCRIPTION TEXT, DATA TEXT, TIME DATETIME, SESSION TEXT, PRIMARY KEY (ID) )

[/sql]

Y ya con esta tabla tendremos para almacenar muchos datos. Los campos CATEGORY, SUBCATEGORY, NAME, DESCRIPTION y DATA sirven unicamente para organizar eventos y subeventos en categorías. Los nombres de los campos son triviales. DESCRIPTION no guarda realmente la descripción sino que podemos definir otro subevento. Con 5 campos para categorizar eventos superamos a Google Analytics que tiene CATEGORY, ACTION, LABEL y VALUE. Además VALUE debe ser numérico mientras que en Fliuva todos son de tipo texto (en la práctica, cualquier cosa).

Código de seguimiento

¿Cómo introducir datos en la base de datos desde nuestra aplicación? Con una pequeña llamada GET a /collect. Yo la he definido en un fichero llamado collect.js

Y se llama muy fácilmente

Si estamos en HTML5, necesitaremos una librería de cliente para poder realizar las llamadas

Así, simplemente hay que llamar a sendEvent. Llamar a login no es necesario siempre que rellenes el valor de sessionStorage.__fliuvaSession correctamente.

Análisis de datos

Ahora debemos analizar los datos. Primero debemos obtener los valores a analizar. La llamada a /get devuelve un fichero JSON con la información completa. En un futuro lo ideal sería espeficicar intervalos de fechas.

Y en el cliente tratamos los datos. Aquí es donde debemos nosotros mismos crear las estadísticas según las métricas que hayamos definido. Yo solo voy a poner una métrica universal, usuarios por día.

Que se corresponde a este pequeño HTML

Visualizar cada sesión por separado es posible con la llamada a /session/NOMBRE_DE_SESION

Y para un rápido procesamiento he decidido usar Jade con JavaScript en el servidor. Y entonces session.jade queda

Juntando piezas

Por último, la aplicación se tiene que iniciar en algún lado. Server.js contiene el arranque

Y así en un pis pas hemos hecho una aplicación de seguimiento y analíticas en JavaScript. Ahora toca empezar a diseñar estadísticas con los datos que tenemos a nuestra disposición y por supuesto cuando tengamos los datos a obrar en consecuencia.