Blog

Temas: Dart
Juan Mellado, 19 Enero, 2014 - 12:11

DartSSRP (SQL Server Resolution Procotol) es un protocolo de Microsoft que permite descubrir todas las instancias de base de datos SQL Server que se encuentran disponibles en una red o en un servidor concreto. Proporciona los nombres de los servidores disponibles, los nombres de las instancias que se encuentran ejecutándose en dichos servidores, sus versiones, y los parámetros de conexión que un cliente necesita para poder conectarse a dichas base de datos.

El protocolo se basa en enviar un mensaje a través de UDP a una dirección IP tipo broadcast/multicast para obtener todas las instancias de base de datos que se encuentran en una red, o a una dirección IP de un servidor concreto conocido para obtener las instancias que se encuentran ejecutándose en dicho servidor.

Cuando un mensaje SSRP enviado desde un cliente llega a un servidor SQL Server, este responde con otro mensaje en el que se listan todas las instancias de base de datos que hay en el servidor. En dicho mensaje de respuesta se incluyen todos los protocolos de comunicación soportados por cada una de las instancias, así como los parámetros concretos de conexión para cada protocolo que un cliente necesita conocer para poder abrir una conexión. Por ejemplo, si una instancia admite conexiones a través de TCP/IP, en el mensaje de respuesta se retorna el número del puerto TCP en el que está escuchando la instancia. O, por ejemplo, si la instancia admite conexiones a través de una pipe, en el mensaje de respuesta se retorna el nombre de la pipe que mantiene abierta la instancia.

Además de esto, el protocolo también permite obtener el número de puerto TCP en el que se encuentra escuchando el SQL Server DAC (Dedicated Administrator Connection), que es un servicio especial de SQL Server que permite conectarse directamente a una instancia, sobre todo para realizar labores de administración y diagnóstico, y que es totalmente independiente del resto de conexiones ordinarias que se abren habitualmente para ejecutar sentencias SQL contra base de datos.

dart-ssrp es una librería cliente que implementa este protocolo y he escrito en Dart, como viene siendo mi norma últimamente, ya que sigo encontrando muy atractiva y productiva la experiencia de desarrollo con este lenguaje. En la práctica no creo que el paquete sea de mucha utilidad, es más bien un ejercicio de programación, en particular con UDP, que es un protocolo que Google ha añadido en la última release de Dart, concretamente la 1.1.1.

El protocolo es bastante sencillo de implementar, ya que los mensajes que se intercambian son muy simples. La parte más complicada que he encontrado en la especificación es el formato que utiliza para intercambiar cadenas de caracteres. La especificación se basa en el uso de MBCS (MultiByte Character Set), sin especificar ningún estándar de representación en concreto, y presuponiendo además que el codepage de la máquina del cliente y del servidor es el mismo. Dart utiliza UTF-16 para representar internamente las cadenas de caracteres, así que la solución ideal sería realizar una conversión de UTF-16 a MBCS para las cadenas enviadas desde el cliente al servidor, y de MBCS a UTF-16 para las cadenas enviadas desde el servidor al cliente. Los algoritmos están descritos en [MS-UCODEREF], pero es bastante material por si solo como para hacer otra librería. De momento me he conformado con transformar directamente los code units de UTF-16 en arrays de bytes y viceversa. UPDATE: Después de escribir esta entrada en el blog he estado buscando un rato y he visto que la clase SystemEncoding parece hacer exactamente lo que necesito.

En otro orden de cosas, comentar que en estos últimos tres meses he trabajado en otros tres proyectos personales distintos. Uno de ellos lo publiqué hace un par de meses (dart-fed), aunque nunca he hablado de él en el blog. Y de los otros dos, uno está en una fase muy temprana de desarrollo, y el otro aunque está casi terminado posiblemente no salga nunca de mi disco duro, ya que el código no está todo lo bien escrito que me gustaría. Ya veremos.

Temas: Personal
Juan Mellado, 15 Septiembre, 2013 - 19:15

VelitaOcho años de blog, que se dice pronto. A primera vista parecería que este último año ha sido un poco flojo, ya que apenas he publicado seis posts, pero teniendo en cuenta que la mitad de ellos fueron para anunciar nuevos proyectos terminados, la verdad es que no me puedo quejar.

- dart-solitaire: Una versión del clásico juego del solitario escrito en Dart. Hace años, cuando la gente pensaba que JavaScript sólo servía para validar formularios, programé este juego en JavaScript. Me pareció una buena idea hacer una nueva versión en Dart para compararla con la de JavaScript y aprovechar la ocasión para añadir opciones que nunca llegué a implementar la primera vez. Esta vez incluso añadí el famoso efecto de final de partida con las cartas rebotando. Espero ver más "juegos HTML5" implementados en Dart en el futuro.

- dart-odbc: Un binding de Dart a ODBC. Es decir, una librería que permite utilizar ODBC desde Dart, de forma que las aplicaciones en Dart puedan conectarse a cualquier base de datos que tengan un driver ODBC, algo que tienen prácticamente el 100% de las base de datos hoy en día. Hacer un wrapper sobre esta librería para ofrecer una API más sencilla, y más "Dart-oriented", sería un proyecto interesante, sobre todo por que de momento Google no parece tener intención de desarrollar su propio ORM para Dart.

- dart-neuquant: Una librería para reducir el número de colores de una imagen sin reducir la calidad de la misma utilizando una red neuronal. Este proyecto fue un desarrollo rápido, ya que prácticamente es un port a Dart de la versión original de la librería que estaba escrita en C. Los resultados son impresionantes, es capaz de reducir una paleta de cientos de miles de colores en otra de apenas 256 colores escogiendo las tonalidades más adecuadas que hacen que la imagen original con la nueva paleta se vea prácticamente igual, aunque ocupando mucho menos espacio por supuesto.

En definitiva, un buen año, tanto técnica como personalmente. Hace ya un año que cambié (otra vez) de ciudad de residencia, y la verdad es que lo estoy disfrutando.

Juan Mellado, 9 Junio, 2013 - 13:23

Hoy he liberado los fuentes de dart-neuquant, un port a Dart del clásico algoritmo Neuquant de Anthony Dekker (1994), que utiliza una red neuronal para convertir una imagen RGBA de 32 bits a otra equivalente de 8 bits. Es decir, que analiza la paleta con los distintos colores presentes en una imagen, que en el caso de 32 bits pueden ser millones, y genera una nueva paleta equivalente a la original, pero de tan sólo 256 colores.

Aunque a priori pueda parecer que el resultado no debería ser bueno, por la diferencia de colores y tonalidades que se pierden, en realidad es todo lo contrario. Por ejemplo, la imagen de la izquierda tiene 68.289 colores distintos, mientras que la de derecha sólo 256, y sin embargo ambas lucen muy similares.

dart-neuquant

Naturalmente hay que tener en cuenta que he reunido las dos imágenes en un única en formato JPG, lo que desvirtúa un tanto el resultado real. Aún así, se puede observar como algunas regiones de la imagen de la derecha presentan ciertos problemas de banding, es decir, que hay un salto brusco de colores en vez de un degradado suave. Esto se observa más en las regiones curvadas, como en algunas partes del caballo por ejemplo. La forma habitual de arreglar esto es aplicando dithering, que consiste en juntar pixeles de distintos colores para que parezca otro color, aunque el autor del algoritmo comenta que esto hace que la medida del error entre la imagen original y la generada crezca.

El algoritmo da más importancia a la componente verde (la G de RGB), ya que el ojo humano es capaz de detectar un rango más amplio de este tipo de tonalidades que del resto. Lo que no es de extrañar ya que es el color que más abunda en la naturaleza. Por lo que el resultado resulta más "agradable" en este sentido.

El proyecto ha ido bastante rápido, ya que el código C original a portar no era muy extenso. La principal dificultad ha estado en que utiliza aritmética entera, con rotaciones en vez multiplicaciones por ejemplo, por lo que he tenido que estar muy atento para que el resultado en cada paso fuera el mismo tanto en Dart como en JavaScript. En la actualidad, casi una década después de cuando se implementó el código original, creo que sería más práctico utilizar aritmética decimal, e incluso puede que más eficiente.

Lo que resulta curioso es que no tenía en mente hacer este proyecto, ha sido un poco de rebote, empecé resolviendo un error en una librería JavaScript que ni siquiera conocía, y he acabado implementando una versión en Dart.

Temas: Dart
Juan Mellado, 19 Marzo, 2013 - 12:49

DartNuevo mes, nuevo proyecto que publico. ¡Ojala fuera así siempre!. Esta vez se trata de dart-odbc, un binding a ODBC para Dart. Es decir, una librería que permite utilizar el API de ODBC directamente desde Dart. Mi objetivo inicial era conectarme a una base de datos Oracle y hacer un par de consultas, pero al final he acabado exponiendo todo el API completo.

Con esta librería es posible conectarse desde un programa escrito en Dart a cualquier base de datos que tenga un driver ODBC. Y como hoy en día prácticamente todas las base de datos tienen un driver ODBC, pues equivale a decir que permite conectarse a cualquier base de datos. En mis pruebas he conseguido conectarme a servidores Oracle, MySql, PostgreSQL y SQL Server.

En lo referente a la parte técnica, comentar que este proyecto tiene dos partes, por un lado una parte escrita en Dart, que expone las funciones del API para que se puedan llamar desde aplicaciones escritas en Dart, y por otro lado una parte escrita en C++, que actúa como puente entre el API de Dart y el API de ODBC, que está escrito en C.

El invento funciona gracias a que Dart permite llamar a funciones contenidas dentro de una librería externa escrita en C. Es decir, que permite llamar a funciones contenidas dentro de una DLL (Windows), una .so (Linux) o una .dylib (Mac). Es bastante similar al funcionamiento de la palabra reservada "native" de Java o los "DllImport" de C#. De hecho, en Dart también se utiliza la misma palabra reservada "native" para denotar funciones que están implementadas en librerías externas.

Además de eso, el equipo de desarrollo de Dart ha publicado el API de bajo nivel para que pueda ser llamado desde fuera de la VM. Es decir, existe un "dart_api.h" y un "dart.lib" que se pueden incluir en cualquier proyecto y hacer las mismas cosas que normalmente se hacen desde Dart, como crear objetos, acceder a atributos, o invocar métodos. Se puede crear un objeto Dart desde C y devolverlo como resultado de la función C que se está ejecutando, por ejemplo. O recibir un objeto Dart como argumento y acceder a sus atributos.

ODBC es un API de muy bajo nivel, así que la librería está más orientada a ser utilizada por desarrolladores de frameworks que de front-ends. No obstante, con una buena capa de abstracción, a la manera de JDBC por ejemplo, podría utilizarse en ambos mundos.

De momento, sin wrappers de por medio, el código Dart resultante es muy similar al que normalmente se escribe en C:

// Allocate an environment handle.
var hEnv = new SqlHandle();

sqlAllocHandle(SQL_HANDLE_ENV, null, hEnv);

// Set ODBC version to be used.
var version = new SqlPointer()..value = SQL_OV_ODBC3;

sqlSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, version, 0);

// Allocate a connection handle.
var hConn = new SqlHandle();

sqlAllocHandle(SQL_HANDLE_DBC, hEnv, hConn);

// Connect.
sqlConnect(hConn, "<DSN>", SQL_NTS, "<USUARIO>", SQL_NTS, "<CLAVE>", SQL_NTS);

// Allocate a statement handle.
var hStmt = new SqlHandle();

sqlAllocHandle(SQL_HANDLE_STMT, hConn, hStmt);

// Prepare a statement.
sqlPrepare(hStmt, "SELECT name FROM customers WHERE customer_id = ?", SQL_NTS);

// Bind parameters.
var customerId = new SqlIntBuffer()..poke(<CUSTOMER_ID>);

sqlBindParameter(hStmt, 1, SQL_PARAM_INPUT, customerId.ctype(),
                 SQL_INTEGER, 0, 0, customerId.address(), 0, null);

// Bind result set columns.
var name = new SqlStringBuffer(32);
var flags = new SqlIntBuffer();

sqlBindCol(hStmt, 1, name.ctype(), name.address(), name.length(), flags.address());

// Execute and fetch some data.
sqlExecute(hStmt);

sqlFetch(hStmt);

...

// Free statement handle.
sqlFreeHandle(SQL_HANDLE_STMT, hStmt);

// Disconnect.
sqlDisconnect(hConn);

// Free connection handle.
sqlFreeHandle(SQL_HANDLE_DBC, hConn);

// Free environment handle.
sqlFreeHandle(SQL_HANDLE_ENV, hEnv);

Estoy bastante satisfecho en términos generales con el funcionamiento de la librería, no obstante hay bastante margen aún para mejorar, particularmente en los siguientes puntos:

- Compilar la librería en otros entornos, además de en Windows. Actualmente sólo tengo la librería compilada en forma de DLL para Windows, para Win32 realmente, pero funcionando sin problemas en Win64. Me gustaría poder generar versiones para Linux o Mac. He echado la caña a ver si consigo que alguien pique y colabore. Añadir soporte para UNICODE también estaría bien.

- Mejorar el rendimiento. Aunque la librería no realiza ningún tipo de proceso pesado, es una mera intermediaria, hay un par de valores que pienso que podrían estar precalculados, en vez de calcularlos cada vez, como son el tamaño de las filas de los buffers y los offsets a las columnas. Actualmente se calculan por cada peek o poke que se realiza a los buffers.

- Revisar el uso de la memoria. Sobre todo a largo plazo, con un uso intenso y continuado, no sólo simples pruebas que se ejecutan y terminan de forma casi inmediata sin apenas consumir recursos. Le tengo echado el ojo a una utilidad que utiliza el equipo que está desarrollando Chrome para estos menesteres, y esta puede ser una buena excusa para probarlo.

- Estudiar la posibilidad de exponer las llamadas al API de ODBC de forma asíncrona. Esta posibilidad la evalúe al principio, pero la descarte rápidamente por que la documentación del API de Dart especifica que algunas cosas no pueden hacerse cuando se está funcionando en modo asíncrono, al no existir un "isolate" (hilo de ejecución) concreto durante la ejecución. Como no sabía donde me metía lo dejé pasar, pero ahora que sé lo que hace falta, es un tema que podría revisar en el futuro.

- Añadir ejemplos de uso. Todo el proyecto lo he realizado en base a pruebas, y prácticamente existe un test para cada función del API de ODBC. Lo que me gustaría incorporar es algún caso concreto de uso, como la típica aplicación de consola en la que escribes consultas SQL y te muestra los resultados por pantalla.

- Añadir más documentación. Una ventaja de este proyecto es que no tengo que explicar el API, hay mucha información disponible sobre ODBC. Pero quizás podría añadir alguna explicación más detallada acerca de cuando utilizar los objetos SqlBox y cuando los objetos SqlBuffer. Los primeros son para llamadas al API que devuelven un valor de forma inmediata ("dame el valor ahora"), mientras que los segundos son para cuando los valores se devuelven de forma diferida ("dame el valor cuando lo tengas").

En fin... ya estoy pensando en el siquiente proyecto.

Juan Mellado, 2 Febrero, 2013 - 14:49

Ayer liberé los fuentes de dart-solitaire, una versión escrita en Dart del clásico juego de cartas del solitario. No es un juego demasiado complejo, así que lo usé como excusa para empezar un nuevo proyecto y seguir probando este nuevo lenguaje de programación aún en desarrollo. En mi caso además tenía el aliciente añadido de que hace siete años escribí una versión del mismo juego directamente en JavaScript, en un época donde nadie apenas hacía desarrollos en JavaScript, y me venía estupendamente para comparar las formas de desarrollar en uno y otro lenguaje.

Demo online: http://www.inmensia.com/files/dart-solitaire/solitaire.html

Cuando me planteé volver a escribir este juego, además de implementar la mecánica básica, me propuse añadir algunas opciones que siempre había querido desarrollar, como la opción de "undo" para deshacer las jugadas por ejemplo. La manera tradicional de codificar esta opción es utilizando un patrón de diseño llamado "Command", y así es como lo he acabado implementando para no andar reinventando la rueda. Es curioso, casi podría decir que empecé el proyecto para implementar este tipo de cosas en vez del juego en si mismo.

El código puedo decir que prácticamente lo he escrito dos veces. La primera vez usé una solución basada en elementos HTML y CSS, donde las cartas por ejemplo eran elementos HTML de tipo DIV. Pero después de tener una versión funcionando empecé a pensar que me gustaría probar una solución basada en el uso de un CANVAS. Y dicho y hecho, empecé a cambiar todo el código que ya tenía escrito hasta conseguir una nueva versión basada en el manejo de sprites esta vez. Es ese tipo de cosas que uno sólo se plantea hacer en proyectos personales, donde no hay restricciones de tiempo, en los del trabajo no suele haber tanta libertad.

Una ventaja añadida de usar un canvas es que me permitía implementar de una forma sencilla el famoso efecto de la versión para Windows, donde al finalizar una partida las cartas salían disparadas una a una rebotando y dejando un rastro de si mismas. Recordaba haberlo visto hace poco en una demo tecnológica llamada Winning Solitaire de Ricardo Cabello, así que estudié el código, muy sencillo, y lo adapté para incorporarlo al juego. Da igual en que lenguaje esté implementado, sigue siendo un buen efecto de fin de partida.

El tener el efecto de las cartas rebotando implementado a menos me compensa de algunas carencias obvias, como no tener una música de fondo, algún efecto sonoro, o incluso alguna que otra animación al manejar las cartas. Suelo trabajar solo en estos proyectos, así que tengo mis limitaciones a la hora de añadir determinadas características "creativas". En algunas de ellas simplemente no me apetece trabajar, y para otras carezco del talento necesario. Al menos puedo sentirme orgulloso de haber podido hacer los gráficos, que aunque sean sencillos me han llevado bastante tiempo.

Aunque el juego utiliza imágenes en formato PNG, las originales son gráficos vectoriales en formato SVG hechos con Inkscape. Inicialmente utilizaba directamente las imágenes en formato SVG, pero me encontré con algunos problemas de incompatibilidad entre los dos o tres navegadores más populares con los que estuve probando, ya que cada cual dibujaba las imágenes según su propio criterio, y lo que es peor, en algunos casos el rendimiento era absolutamente pésimo. He liberado los gráficos vectoriales originales por si alguien puede reutilizarlos para algún desarrollo propio.

He añadido además un par de opciones al juego para poder cambiar el diseño del tablero y del frontal de las cartas. Así como el número de cartas que se sacan del mazo cada vez. Aunque esto último lo dejo hacer incluso en medio de una partida sin reiniciarla, lo que no es del todo correcto. Otras opciones que podrían añadirse serían por ejemplo cambiar el diseño del reverso de las cartas, jugar contra el tiempo, añadir un sistema de puntuación, o un histórico de partidas jugadas.

Los mensajes y cuadros de diálogo están hechos con un poco de CSS, con el que parece que jamás llegaré a sentirme totalmente cómodo. Inicialmente pensé en utilizar bootstrap, con el que incluso llegué a hacer unas pruebas que me gustaron mucho, ya que el resultado es muy profesional, y resulta muy fácil añadir animaciones y otros efectos con JavaScript. No obstante, al final quité la dependencia y todo el código, ya que me dió la impresión de que el proyecto acabaría teniendo más CSS y código en JavaScript que en Dart.

Un detalle que me gustaría incorporar en el futuro, ya que ahora mismo no estoy en condiciones de probar como a mi me gustaría, es la gestión de eventos de tipo "touch" para que el juego funcione en los móviles con pantalla táctil en vez de sólo con el ratón. El problema es del "drag and drop", que los móviles interpretan como un "gesto", en vez de como un "click y arrastrar sin soltar el botón" de un ratón tradicional.

Respecto a las pruebas, decir que apenas he probado en el PC de casa con las últimas versiones de Chrome (dev channel), Firefox (ga) e Internet Explorer (10 rc). Y como de costumbre, Internet Explorer es el que más lata ha dado, incluso la nueva versión.

Por último, comentar que actualmente prefiero desarrollar en Dart que JavaScript. Me siento más cómodo con el lenguaje, lo encuentro más productivo. Poder trabajar con una sintaxis y estructura de clases e interfaces como la que ofrecen los lenguajes orientados a objetos tradiciones es mucho mejor para mi que trabajar con los prototipos de JavaScript. Para ser un lenguaje que está aún en desarrollo, con muchas cosas que limar, y muchas librerías que desarrollar aún, tiene el plus de ofrecer una "experiencia de codificación" muy gratificante, algo que me resulta difícil de explicar con palabras o cuantificar de una manera más concreta.