Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

19 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
jueves, 27 de septiembre de 2007
Los que vamos evolucionando a la vez que lo hace la plataforma .Net (bueno, unos cuantos pasos por detrás ;-)), a veces se nos hace difícil superar nuestras costumbres y adaptarnos a nuevos métodos o utilidades que, sin duda, vienen para facilitarnos la vida y ofrecen mejores soluciones a problemas comunes que las que utilizamos de forma habitual.

Un ejemplo lo tenemos con los métodos estáticos xxx.Parse(), útiles para convertir de un string a un tipo valor, como puede ser int32 o boolean. Desde el principio de los tiempos usamos, para obtener un entero desde su representación como cadena, construcciones de tipo:
string num = "123";
int i = 0;
try
{
i = int.Parse(num);
}
catch (Exception ex)
{
// TODO: hacer algo...
}

Sin embargo, la llegada de .NET Framework 2.0 supuso la inclusión del método estático TryParse() en la práctica totalidad de tipos primitivos numéricos (en la versión 1.1 sólo existe en el tipo double), cuya forma más simple de utilización (y también más usual) dejaría el bloque try/catch anterior en uno más compacto y legible:

if (!int.TryParse(num, out i))
// TODO: hacer algo...
 
El método TryParse devuelve true si se ha podido realizar la transformación con éxito, dejando en la variable de salida que le indiquemos el valor parseado, en este caso un int.

Sin embargo, además de para evitarnos dolores en las articulaciones de los dedos, existen otros motivos para utilizar xxx.TryParse() en vez de xxx.Parse(): el rendimiento, sobre todo si se prevé que el número de fallos de conversión será relativamente alto en un proceso. De hecho es el método recomendado en la actualidad para realizar estas conversiones.

Según la prueba de rendimiento de TryParse publicada Microsoft, ejecutada sobre su propia plataforma, la utilización de este método aventaja de forma considerable al modelo try-parse-catch. Por ejemplo, realizando varias simulaciones de parsing de enteros sobre un conjunto de 100 cadenas de las cuales 5 son erróneas, el tiempo de proceso llegar a ser mil veces superior usando este último patrón; si asumimos 20 incorrectas (80% de cadenas correctas), el modelo tradicional puede tardar 4.000 veces más que usando TryParse.

Aunque lo normal no es efectuar un gran número de transformaciones de este tipo y esta diferencia de rendimiento podría entenderse despreciable, podría ser un factor a tener en cuenta cuando estas operaciones se realicen en contextos de gran carga de usuarios o concurrencia, como en sitios web de alto tráfico. Ojo pues a esas aplicaciones (o componentes) que hemos tomado de .NET 1.x y estamos reutilizando en las versiones superiores.

Por cierto, todo lo dicho, aunque los ejemplos están codificados en C#, es válido para Visual Basic .NET y cualquier otro lenguaje que compile sobre la plaforma .NET de Microsoft. A ver si un día tengo un rato y compruebo si el comportamiento en Mono es el mismo.
lunes, 24 de septiembre de 2007
Hace unas semanas Miguel de Icaza publicaba en su blog personal un par de ejemplos del tipo de pruebas técnicas que realizan cuando contratan personal, en este caso para el proyecto Mono.

La filosofía es bastante simple, y la verdad es que no carece de sentido: los aspirantes reciben por correo electrónico el "enunciado" de la prueba, y disponen de dos semanas para responder. Aunque el tiempo de respuesta puede parecer excesivo, está pensado para ser realizado por los aspirantes cuando vuelven a casa tras sus jornadas de trabajo o estudio.

Según Miguel, esta técnica le da mejores resultados que las tradicionales entrevistas cara a cara, donde una lectura del currículum y varias preguntas rápidas no permiten conocer en profundidad al candidato. No hay nada como ver planteamientos y código para saber el tipo de desarrollador que tenemos delante.

La prueba para trabajar en el ámbito de Windows.Forms consistía en desarrollar un Control (Widget) y responder una pregunta, y decía más o menos esto (traducción libre):


Desarrollo de un control

Debes implementar un pequeño motor de renderizado para un lenguaje de marcas basado en XML. Este lenguaje acepta las siguientes etiquetas:

<p>...</p>, para definir el inicio y fin de párrafos.

Los párrafos pueden contener en su interior los siguientes tags:

  • <b>...</b>, para poner en negrita el texto
  • <i>...</i>, para poner el texto en cursiva

  • <link>...</link>, para que el texto sea renderizado como un hiperenlace.
  • <blink>...</blink> para que el texto parpadee
El control debe exponer la siguiente propiedad, que permitirá al desarrollador modificar el contenido (en este lenguaje de marcas) de forma programática.

  string Markup { get; set; }
 
Por ejemplo:

  m = new MarkupControl ();
m.Markup = "<p>Hello <b>World</b>!</p>";
 
El control también debe exponer un evento que permita notificar de los clicks del usuario sobre los enlaces (etiqueta <link>), algo así como:

  delegate void LinkClicked (object sender, string link_text);
 
De esta forma, será posible suscribirse al evento usando un código como el siguiente:

  m.LinkClicked += my_clicked;
...

void my_clicked (object sender, string link_text)
{
Console.WriteLine
("The link {0} was clicked", link_text);
}
 
Debes enviar una aplicación completa que se ejecute correctamente en Linux, y debe hacerse uso del evento y la propiedad citados con anterioridad. Por ejemplo, estaría bien tener algo como:

void my_clicked (object sender, string link_text)
{
Console.WriteLine ("Link {0} pulsado", link_text);
((MarkupControl) sender).Markup = "<p>Nuevo <b>texto</b></p>";
}
 
Puntos extra: al usar <blink> será necesario actualizar la vista, se valorará si se evita el parpadeo usando buffers dobles o repintando sólo el área modificada.

Quiero una pequeña y sucinta implementación, pero es tu oportunidad para demostrar que puedes escribir código robusto, así que impresióname.

Pregunta

En nuestra implementación de corlib, en System/DateTime.cs tenemos una implementación no óptima del método TryParse, básicamente invocamos a Parse dentro de un bloque try/catch.

Explica:
  • ¿Por qué digo que nuestra solución no es óptima?

  • ¿Qué debería tener para hacerla más eficiente?

  • ¿Por qué el desarrollador que escribió el código no realizó lo más eficiente?

La trick-question es: ¿por qué el proceso más rápido no se realizó en primer lugar? Explícalo.

¿Que os parece? ¿Podríais entrar a trabajar en el equipo de Mono?
jueves, 20 de septiembre de 2007
Si eres de los que, como yo, piensan que la moda de los bordes redondeados la ha impuesto gente que odia a los programadores y diseñadores de webs, nunca te ha convencido introducir (X)HTML sin carga semántica sólo para poder incluir estas filigranas en las esquinas de los DIVS o elementos de bloque similares, o no soportas crear imágenes redondeadas para las esquinas, es posible que te interese Nifty Corners Cube.

Se trata de una librería Javascript para redondear los bordes de elementos de bloque sin necesidad de crear imágenes ni nada parecido, sólo usando CSS y scripting. Además, no es intrusiva: si un navegador no soporta scripts o se trata de una versión no contemplada, el usuario simplemente verá sus bordes como siempre. Buena pinta, eh?

Y la forma de usarlo, fácil. En primer lugar, una vez descargado el archivo .zip y extraído en un directorio de la web, se coloca la referencia al script sobre la página (X)HTML como siempre:

<script type="text/javascript" src="niftycube.js"></script>


Desde ese momento ya podemos invocar desde Javascript a las funciones de la librería para que actúen sobre los elementos cuya presentación queremos modificar, por ejemplo así:

// Esto hace que al div con id="box"
// se le redondeen los bordes con
// esquinas grandes (10px):

Nifty("div#box","big");



Esta llamada, o mejor dicho, todas las llamadas que necesitemos para ajustar los efectos de nuestra página, pueden situarse en el evento onload de la misma, como se muestra a continuación. De todas formas, la propia librería ofrece un método alternativo, a través de la función NiftyLoad(), para cuando esto no sea posible.


<script type="text/javascript">
window.onload=function(){
Nifty("div.redondeadoGrande","big");
Nifty("div.redondeadoPeque","small");
}
</script>


En la función Nifty, el primer parámetro es el selector CSS al que se aplicará el borde (o efecto) deseado. Si no tienes claro qué es un selector, podrías echarle un vistazo a este post (selectores CSS), este (selectores CSS-II-), y este otro (selectores CSS-III).

Así, si indicamos el selector "div.redondeado" estaremos aplicando el efecto a todos aquellos divs cuya clase sea la indicada (class="redondeado").

El segundo parámetro es una palabra clave, a elegir entre una larga lista de opciones, algunas de ellas combinables. Aunque en la web del autor viene muy bien explicado con ejemplos, :


PalabraSignificado
tlesquina superior izquierda
tresquina superior derecha
blesquina inferior izquierda
bresquina inferior derecha
topesquinas superiores
bottomesquinas inferiores
leftesquinas izquierdas
rightesquinas derechas
all (default)las cuatro esquinas
noneno redondear las esquinas (útil para usar las nifty columns
smallesquinas pequeñas (2px)
normal (default)esquinas normales (5px)
bigesquinas grandes (10px)
transparentpermite crear esquinas transparentes con alias. Se aplica automáticamente cuando el elemento no tiene un color de fondo especificado.
fixed-heightse aplica cuando el elemento tiene un alto fijo especificado en su CSS
same-heightParámetro para nifty columns: todos los elementos identificados por el selector CSS tienen el mismo alto. Si el efecto se utiliza sin bordes redondeados, este parámetro se puede usar en conjunción con la palabra clave none.


En la web del autor hay multitud de ejemplos de uso que demuestran lo fácil que puede llegar a hacernos la vida. Por cierto, también he encontrado una versión en español.

Por último, comentar que la librería se distribuye bajo licencia GNU GPL, y lo podéis descargar en esta dirección.

Hala, a disfrutarlo.



Editado [2/11/07]: Si usas ASP.NET, es posible que te interese NiftyDotNet, un componente que encapsula Nifty Corners Cube para hacer aún más sencillo su uso.
martes, 18 de septiembre de 2007
A raíz de los posts sobre los tipos anulables en .NET (introducción a los nullables y uso tipos anulables con enumeraciones), mi amigo Javi me hizo una pregunta que sólo un friki como él sería capaz de formular ;-): ¿cómo afecta el uso de tipos anulables a la serialización de clases?

Aunque sospechaba la respuesta, he hecho un par de pruebas a través de las cuales, ahora sí, puedo asegurar que no afectan en nada, es decir, el sistema controla perfectamente la forma en que se serializan y deserializan este tipo de valores.

El comportamiento es el siguiente: cuando el tipo anulable contiene un valor no nulo, la serialización la delega en el tipo subyacente. Si es un int?, se realizará la serialización por defecto para el int. Usando un serializador XML, un ejemplo de salida sería:


<?xml version="1.0" encoding="utf-16"?>
<int>10</int>

 

En cambio, cuando se trata de serializar el valor null, el sistema genera una etiqueta que indica este hecho, de la misma forma que lo haría si estuviéramos haciéndolo para un tipo referencia. Un ejemplo de salida XML sería:


<?xml version="1.0" encoding="utf-16"?>
<int xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:nil="true" />

 

En fin, que hoy hemos aprendido una cosa más. Y que no falte. :-)
domingo, 16 de septiembre de 2007
Vía The Server Side acabo de enterarme de la existencia de Quaere, una implementación para Java del proyecto LINQ de Microsoft, creada por Anders Norås.

Se trata de un DSL (Domain Specific Language, lenguaje específico de dominio) que permite integrar dentro de código Java sentencias muy parecidas a SQL para extraer información de arrays, colecciones y otros almacenes de información, de forma muy sencilla y potente. Gracias a la utilización de static imports y fluent interfaces, no es necesario usar preprocesadores o generadores de código intermedios, el código se compila directamente sobre javac importando las librerías de Quaere.

Y para que se entienda mejor el alcance del proyecto y cómo puede ayudarnos a desarrollar, unos ejemplos básicos tomados del blog del autor, que demuestran la potencia de esta extensión para gestión de datos:


// Obtiene los números menores de
// cinco del array:
Integer[] numbers =
{5, 4, 1, 3, 9, 8, 6, 7, 2, 0};

Iterable<integer> lowNums =
from("n").in(numbers).
where(lt("n", 5)).
select("n");



// Obtiene una colección
// de strings con los nombres de
// los productos:
List products =
Arrays.asList(Product.getAllProducts());

Iterable<String> productNames =
from("p").in(products).
select("p.getProductName()");

 
viernes, 14 de septiembre de 2007
De todos es sabido que las enumeraciones son un tipo valor, y se representan internamente como Byte, Int32 u otros tipos primitivos de la plataforma, lo que hace imposible la asignación de valores como null, concebido para los tipos referencia.

Así, en el siguiente ejemplo en C#:

Estado estado1 = Estado.Correcto;
Estado estado2 = null;

La segunda línea provoca el error en compilación "No se puede convertir null en 'ConsoleApplication1.Program.Estado' porque es un tipo de valor". Lógico, es igual que que si intentáramos asignar el maldito valor nulo a un integer.

Esto puede causar ligeras molestias para la gestión de valores "indeterminados", puesto que estaríamos obligados, por ejemplo, a utilizar otro miembro de la enumeración para representar este valor, como en el siguiente código en Visual Basic .Net:

Public Enum Estado
Indeterminado = 0
Correcto = 1
Incorrecto = 2
End Enum

Sin embargo, hay ocasiones en la que resulta más interesante poder disponer del valor nulo como una opción para las variables del tipo de nuestra enumeración. Por ejemplo, si estamos desarrollando componentes que leen de una base de datos donde la indeterminación se representa por un nulo, sería más natural poder trasladar esta particularidad al modelo de objetos.

Y para esto inventaros los tipos anulables, de los que ya publiqué un post hace tiempo (Nullable Types, o cómo convivir con los nulos). Dado que las enumeraciones son tipos valor, nada impide crear tipos anulables de enumeraciones:

' VB.NET
Dim estado1 As Nullable(Of Estado)
Dim estado2 As Nullable(Of Estado)
estado1 = Estado.Correcto
estado2 = Nothing

// C#
Estado? estado1 = Estado.Correcto;
Estado? estado2 = null;

 
miércoles, 12 de septiembre de 2007
Javascript, ese lenguaje tan de moda, nos permite manipular en cliente algunas propiedades de los utilísimos validadores de ASP.Net.

La función ValidatorEnable, proporcionada por la plataforma .Net en cliente y utilizable mediante scripting, nos permite habilitar o deshabilitar validadores de nuestros Webforms sin necesidad de hacer un postback. Un ejemplo de uso sería el siguiente:

function onOff(validatorId, activar)
{
var validator =
document.getElementById(validatorId);
ValidatorEnable(validator, activar);
}

El segundo parámetro sería el booleano (true o false) que indica si se desea activar o desactivar el validador. El primer parámetro es el ID en cliente del mismo, y podemos obtenerlo usando la propiedad ClientID del control; por ejemplo, imaginando que tenemos un validador de tipo RequiredFieldValidator llamado Rfv en nuestro Webform, una llamada a la función anterior sería algo así como:

function algo( )
{
onOff("<%= Rfv.ClientID %>", true);
}

 
lunes, 10 de septiembre de 2007
Hoy seguiremos jugado un poco más con las plantillas de Blogger, y estudiaremos cómo modificar la forma en que este gestor de blogs, sobre el que está montado Variable not found, muestra el mensaje al pie de los posts indicando el número de comentarios de cada entrada, que es bastante soso (al menos en las plantillas por defecto).

Por defecto Blogger nos deja configurar exclusivamente qué texto aparecerá detrás del número de comentarios, es decir, a lo más podríamos hacer que apareciera "3 comentarios, ¡comenta ya!" o mensajes así, pero nunca con lógica dependiente del número, lo cual resulta demasiado lineal y cutre para un blog de renombre como el nuestro ;-)

A lo largo de este post vamos a modificar la plantilla para hacer que se muestre un mensaje cuando no hay ningún comentario, otro distinto cuando hay sólo uno, y otro para el resto de los casos. Esto podríais después complicarlo todo lo que queráis, pero de momento con lo que vamos a ver será suficiente para que podáis empezar a jugar.

En primer lugar he de decir que, al igual que ocurría el otro día cuando tratamos el tema de modificar la forma de aparecer la lista de categorías en Blogger, lo más prudente es hacer una copia de seguridad de la plantilla, pues cualquier paso en falso puede tumbar nuestra bitácora. Por si no viste el post anterior, la forma de hacerlo era accediendo al panel de administración de la herramienta y pulsando el enlace "Descargar plantilla completa" que encontrarás en la pestaña "Plantilla", opción "Edición de HTML".

Una vez realizado el backup, podemos continuar sin peligro.

A continuación, marcamos la casilla "Expandir plantillas de artilugios", que nos permitirá acceder al código fuente completo de los Widgets, que son los elementos, bloques o controles que componen la interfaz de Blogger.

Una vez marcada esta casilla, podemos desplazarnos sobre el texto y buscar una porción de código similar a este, donde se ve claramente el comportamiento por defecto del gestor a la hora de mostrar el número de comentarios de una entrada:
  <b:if cond='data:post.numComments == 1'>
1 <data:commentLabel/>:
<b:else/>
<data:post.numComments/> <data:commentLabelPlural/>:
</b:if>


A simple vista se entiende el comportamiento por defecto del sistema, ¿no? Fijaos que se distingue cuando hay un único comentario para poner la etiqueta en singular, mientras que en resto de casos es en plural.

Si escudriñáis en el código de la plantilla, detectaréis que hay dos puntos donde aparece una porción similar. Uno de ellos es para indicar la presentación en la página principal de vuestro Blog, donde aparece la lista de los últimos posts; el otro es para la página individual de cada post. A efectos prácticos, lo que quiere decir es que podemos establecer reglas diferentes para cada caso, aunque por simplificar un poco el ejemplo no lo haremos aquí.

Pues bien, vamos a modificarlo ligeramente para animar al lector a participar en el blog con sus comentarios. Por cierto, no me gusta mucho moverme en el interior del textarea de Blogger. Prefiero llevarme el código a un editor de texto de mi equipo, y desde ahí manipularlo todo lo que quiera. Una vez he acabado de hacer los cambios, copio y pego sobre el cuadro de edición y listo; o si lo he salvado a mi disco, también podría subirse usando la opción de cargar o subir la plantilla disponible en la parte superior de la pantalla.

En cualquier caso, el nuevo código a incluir sería:
<b:if cond='data:post.numComments == 1'>
Ya hay 1 comentario, ¡participa!
<b:else />
<b:if cond='data:post.numComments == 0'>
No hay comentarios. ¡Sé el primero!
<b:else />
<data:post.numComments/> <data:commentLabelPlural/>:
</b:if>
</b:if>

Como se puede comprobar, si sólo hay un comentario lo indicamos y hacemos un llamamiento directo a la participación del usuario. Si no hay comentario alguno, animamos a ser el primero en comentar, y en el resto de los casos, hacemos como siempre.

Vamos, que ya no hay excusa para que en tu blog no haya participación. ;-D
jueves, 6 de septiembre de 2007
Visitando algunos blogs, me he fijado que aquellos que usamos Blogger sufrimos un pequeño problemilla a la hora de presentar la lista con las etiquetas principales de nuestros posts: mostramos todos los tags, por insignificantes que hayan sido, aunque sólo los hayamos tocado de refilón.

Personalmente, creo que la lista de etiquetas aportan una forma rápida y clara de ver de qué trata principalmente nuestro blog, y no es muy positivo tener una lista interminable de tags, la mayoría de ellos con una única entrada asociada.

Aunque Blogger permite dos formas de verlas, en orden alfabético o según su frecuencia, el resultado es igual de terrible. En el primer caso se entremezclan los tags significativos con los que no lo son; en el segundo, la lista de etiquetas importantes vendría seguida de la lista de tags sin peso, que alargan y hacen más pesada la página innecesariamente.

Sin embargo, el potente sistema de plantilla de Blogger permite "retocar" de forma sencilla este comportamiento. En este caso, vamos a hacer que sólo aparezcan en esta lista los tags que tengan más de una entrada, aunque de la misma manera podríamos hacerlo para incorporar otras lógicas más o menos complejas.

Vamos a ver cómo se hace.

En primer lugar, debemos acceder, desde el panel de Blogger a la opción "Plantilla", seleccionando la subopción "Edición HTML".

Importante antes de seguir: si no lo has hecho ya, no vendría mal realizar una copia de seguridad de tu plantilla actual. Puedes hacerlo simplemente pulsando el enlace "Descargar plantilla completa" que encontrarás en la zona superior de la página. De esta forma, si metes la pata podrás volver a dejarlo todo como estaba. :-)

Ahora, fíjate que aparece un cuadro de edición con el código fuente de la plantilla, aunque debes marcar la casilla "Expandir plantillas de artilugios" para tener acceso a las zonas que necesitamos retocar.

Como ayuda, si os es incómodo manipular el texto sobre el cuadro de edición de la web, podéis copiarlo y pegarlo en vuestro editor favorito. Una vez hechas las modificaciones en el código, se vuelve a pegar sobre Blogger y listo.

El siguiente paso es buscar un texto parecido al siguiente (en mi caso está casi al final del código fuente). Puede no ser igual, pero sí que debe ser muy parecido a:


<b:widget id='Label1' locked='false' title='Categorías' type='Label'>
<b:includable id='main'>
<b:if cond='data:title'>
<h2><data:title/></h2>
</b:if>
<div class='widget-content'>
<ul>
<b:loop values='data:labels' var='label'>
<li>
<b:if cond='data:blog.url == data:label.url'>
<data:label.name/>
<b:else/>
<a expr:href='data:label.url'><data:label.name/></a>
</b:if>
(<data:label.count/>)
</li>
</b:loop>
</ul>
<b:include name='quickedit'/>
</div>
</b:includable>
</b:widget>


A simple vista, se entiende que se trata del Widget (en mi caso su título es "Categorías") que muestra las etiquetas de los posts del blog, iterando sobre el conjunto de labels registrados (loop sobre data:labels), y montando una lista (ul) donde en cada elemento (li) se dibuja la etiqueta (label.name) y el número de veces que aparece (label.count).

Por tanto, lo que queremos hacer es realmente sencillo. Vamos a incluir en el interior del bucle un condicional que realice estas tareas sólo si el número de veces que se utiliza una etiqueta (label.count) es mayor de uno. El resultado, con el nuevo código resaltado es el siguiente:


<b:widget id='Label1' locked='false' title='Categorías' type='Label'>
<b:includable id='main'>
<b:if cond='data:title'>
<h2><data:title/></h2>
</b:if>
<div class='widget-content'>
<ul>
<b:loop values='data:labels' var='label'>
<b:if cond='data:label.count > 1'>
<li>
<b:if cond='data:blog.url == data:label.url'>
<data:label.name/>
<b:else/>
<a expr:href='data:label.url'><data:label.name/></a>
</b:if>
(<data:label.count/>)
</li>
</b:if>
</b:loop>
</ul>
<b:include name='quickedit'/>
</div>
</b:includable>
</b:widget>


Una vez realizado este cambio, podéis previsualizar el resultado usando el botón de "vista previa", y una vez esté todo a vuestro gusto podéis guardarla, pasando desde ese momento a estar activa. Si os aparece algún problema a la hora de previsualizar es posible que hayáis olvidado algún carácter a la hora de copiar y pegar el código: revisadlo detalladamente y seguro que solucionáis el problema. Si, a pesar de todo la cosa se os pone fea, volved a cargar la plantilla que habéis salvado previamente y todo volverá a su estado inicial.

El resultado podéis verlo a la derecha: mi lista de categorías sólo muestra aquellas que tienen más de una entrada. :-)

Espero que os sea de utilidad, o al menos de inspiración para hacer vuestros propios ajustes de Blogger.
miércoles, 5 de septiembre de 2007
Me acabo de encontrar en The Inquirer la siguiente noticia:


Microsoft anuncia Silverlight 1.0 ¡compatible con Linux!
La tecnología pretende competir con Adobe Flash ya ha llegado a su versión 1.0 y está disponible para su descarga y utilización en todo tipo de navegadores. Incluidos los de Linux a través del proyecto Moonlight y del acuerdo entre MS y Novell.

(Seguir leyendo...)



Parece que los chicos de Microsoft y los de Novell (desarrolladores principales de Mono) no se llevan nada mal.
martes, 4 de septiembre de 2007
Esto de que cada navegador utilice su propio dialecto derivado del CSS para indicar atributos, como la transparencia u opacidad de los elementos de una página, tiene su gracia... o mejor pensado, no tiene ninguna gracia.

Menos mal que en CSS-Tricks nos enseñan cómo definirla para que funcionen con prácticamente todos los browsers del universo conocido:
.transparente
{
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}


De esta forma, para hacer que un bloque div (por ejemplo) se convierta en semitransparente (al 50% según el ejemplo anterior), sólo habría que poner:

<div class='transparente'>
... lo que sea
</div>


Obviamente, el nivel de opacidad puede modificarse al valor deseado, siendo el 100% el máximo (totalmente opaco) y 0% el mínimo (totalmente transparente). Ojo, que en la primera línea (filter:alpha...) se usa el rango 0-100 y en las restantes este valor dividido entre cien, es decir, en un rango del 0 al 1.

Eso sí, supongo que los validadores CSS igual se quejan un poco. ;-)
domingo, 2 de septiembre de 2007
Hace unos días Miguel de Icaza hablaba en su blog de la inminente posibilidad de hacer funcionar ASP.Net Ajax sobre Mono, incluso comenta un mensaje de Onur Gumus a la lista de programadores de la plataforma explicando cómo hacerlo en la actualidad con versiones internas.

Todavía tendremos que esperar un poco para poder incorporarlo en producción, pero sin duda es una buena noticia para los que ya disfrutábamos de estas librerías en el framework de Microsoft y esperábamos ansiosamente su implementación en Mono.
¡Y ya estamos de vuelta! Parece que fue ayer cuando me despedía con la alegría de ver un mes de descanso por delante, y casi sin darnos cuenta ha llegado Septiembre, con todo lo que ello implica.

Pero no me refiero exclusivamente a cosas malas, que para recordarlas están los telediarios; también vienen nuevos proyectos, expectativas, ilusiones... todo un año por delante para seguir haciendo lo que nos gusta.

En cuanto a Variable not found, ¡queda oficialmente inaugurada la temporada 07-08!

Nos leemos.

miércoles, 1 de agosto de 2007
¡Por fin llegaron! Salvo un par de maletas pendientes de repasar, todo está listo para comenzar nuestra gira veraniega.

Variable not found, por tanto, quedará a su libre albedrío hasta primeros de Septiembre, momento en el que volveré con más energía que nunca, muy motivado por la evolución del blog y sobre todo por este mes de Julio que ha terminado con una actividad y unas estadísticas de visitas que no habría podido imaginar hace unos meses (debido principalmente al efecto Menéame, todo sea dicho).

Playas de El PortilEn cuanto a las vacas, aunque es posible que hagamos ciertos reajustes en la planificación (hasta en vacaciones hay de eso), tenemos previsto pasar unos cuantos días en El Portil, una pequeña localidad costera a caballo entre Cartaya y Punta Umbría, ambos en provincia de Huelva. Esto será a partir de hoy mismo, hasta finales de la semana que viene.

Después pasaremos unos días también en Sanlúcar de Barrameda, un pueblo de la costa de Cádiz que no tengo la fortuna de conocer, pero según cuentan es una maravilla.

Por último, también pretendemos ir de viaje familiar unos días. No sabemos cuándo. No sabemos a dónde. No sabemos cómo. Digamos que esta es la parte más emocionante del plan vacacional. ;-D.

Nos vemos por aquí a la vuelta.
lunes, 30 de julio de 2007
El pasado miércoles 25 en el blog oficial de Google Analytics publicaban "Notice of Brief Processing Delay", un post donde comentaban que durante el día habría algunos retrasos. No sé si tendrá que ver con esto o con el jolgorio prevacacional, pero me encuentro en mi blog un total de cero visitantes desde hace un par de días... ¡como en los viejos tiempos! :-D

Y aunque sé que es consuelo de tontos, alegra saber que le ocurre a más gente:

En fin, espero al menos que no borren los datos...


Actualización, martes 31 de Julio: ya hay noticias oficiales por parte de Google sobre este retraso:
domingo, 29 de julio de 2007
Hoy seguimos con la serie inspirada por Phil Haack en su post "19 Eponymous Laws Of Software Development" donde estoy recogiendo leyes que se aplican en el mundo del desarrollo del software y muchos otros ámbitos. La particularidad de estas leyes y principios es que han hecho famosos a sus autores, pues tienen el mismo nombre que ellos.

Ley de Conway

Cualquier software refleja la estructura organizacional de quien lo produjo
A pesar de que suena a guasa, la ley de Melvin Conway no puede ser más cierta. Una empresa con tres grupos de desarrollo tenderá a generar software distribuido en tres subsistemas, reflejo fiel de las relaciones entre los grupos participantes. Y por cierto, ¿habéis pensado alguna vez que el software que se hace en vuestra empresa es un desastre? ¿creéis que con esta ley podríais obtener alguna conclusión? ;-D

Principio de Kerchkhoff

En términos de criptografía, un sistema debería ser seguro incluso si todo sobre el mismo se conoce públicamente, salvo una pequeña porción de información
Es increíble que Auguste Kerckhoffs critógrafo alemán, enunciara en el siglo XIX este principio, base de todos los sistemas de criptografía de clave pública actuales.

Ley de Linus

Dados suficientes ojos, todos los errores son obvios
Pues sí, Linus Torvalds, uno de los más famosos artífices de Linux tal y como es conocido hoy en día, no sólo desarrollaba software, también emitía este tipo de aseveraciones. Aunque la frase fue cosa de Linus, fue Eric S. Raymond, un hacker a la antigua usanza, el que la popularizó y le dio el nombre de su creador.

Ley de Reed

La utilidad de grandes redes, y en particular las sociales, crecen exponencialmente con el tamaño de la red
David P. Reed, científico americano, enunció esto que parece obvio en los tiempos actuales dado el tamaño y utilización de este tipo de redes. En esta entrada de la wikipedia podéis encontrar una introducción del soporte teórico en el que se basa.

Ley de Moore

La potencia de los ordenadores se duplica cada dos años, reduciendo además su coste
Repetida hasta la saciedad en revistas de cacharreo, y constatada desde hace décadas, fue promulgada por Gordon Earl Moore quien, por cierto, es co-fundador de Intel, fijaos si lo tenía claro el muchacho, en 1965 (!). No sé si entonces utilizó la bola de cristal o es simplemente un genio, pero desde luego su ley es una referencia de la medida del avance en los ordenadores y demás dispositivos basados en tecnología similar, y un objetivo mínimo a cumplir.

Ley de Wirth

El software se ralentiza más deprisa de lo que se acelera el hardware
Brillante la frase de Niklaus Wirth, que allá por el año 1995, aún sin conocer Windows Vista, observó su entorno y predijo la situación actual: cada vez el software es más lento y pesado, a pesar de que según la Ley de Moore tendría que ser al contrario. Este señor, una eminencia, es conocido sobre todo por haber dirigido la creación de los lenguajes Pascal, Modula y algunos otros menos difundidos.

Ley de Zawinski

Todo programa intenta expandirse hasta que pueda leer emails. Aquél que no pueda ser expandido hasta ese punto, será sustituido por otro que sí tenga esa capacidad
Lo que más me ha llamado la atención de Jamie Zawinski aparte de su metafórica ley, es su página web personal. No os la perdáis, pues es bastante indicativa del tipo de individuo de que se trata, todo un friki. También es curioso que es propietario de un club nocturno en San Francisco, este sí que sabe.

Enlaces relacionados: leyes epónimas relacionadas con el desarrollo de software (I)
lunes, 23 de julio de 2007
El siempre sorprendente Phil Haack nos regaló hace unos días un post sobre leyes relacionadas con el desarrollo de software en su post "19 Eponymous Laws Of Software Development". Del artículo me llamaron la atención dos cosas: primero, ¿qué diantres es un epónimo? y segundo, las leyes objeto del post; algunas eran muy conocidas, otras menos, pero en cualquier caso, son perlas dignas de tener en cuenta.

Un epónimo es el nombre de una persona o lugar que cede su nombre a una época, pueblo, unidad, ley, etc. Son epónimos por ejemplo "Diesel", cedido por Rudolf Diesel, inventor de este tipo de motores, o "Hamburguesa", infame trozo de carne picada cuyo nombre le fue cedido por su lugar de origen. Para los curiosos, en esta dirección encontraréis muchos más epónimos.

Solventada esta primera duda, pasamos a ver las leyes epónimas a las que Phil hace referencia. De las diecinueve originales he seleccionado las que me han resultado más interesantes y cercanas, añadiendo algo de información sobre sus autores, orígenes o curiosidades sobre las mismas. Me tendréis que perdonar por esto, pero voy a partir el post en dos entregas para no hacerlo demasiado largo.

Ley de Postel

Sé conservador en lo que hagas y liberal en lo que aceptes de los demás
Esta frase, de Jonathan Bruce Postel, también llamada Principio de Robustez, es la piedra filosofal del protocolo TCP, y está recogida en la RFC 793, sección 2.10, de septiembre de 1981.

Ley de Parkinson

El trabajo se extiende siempre hasta rellenar la totalidad del tiempo disponible para completarlo
Esta ley fue postulada inicialmente en 1955 por C. Northcote Parkinson en The Economist y más tarde entró a formar parte de su libro, basado principalmente en las experiencias de la administración británica.

Principio de Pareto

Para muchos fenómenos, el 80% de las consecuencias derivan del 20% de las causas
Wilfredo Pareto fue un estudioso de la economía y sociología del siglo XIX, y se fijó que el 80% de las propiedades y riqueza estaban repartidas entre el 20% de la población, enunciando su famoso principio. A partir de ahí, se piensa que esta proporción es cierta en múltiples ocasiones, hasta en el número de bugs en el código fuente de un software, o el tiempo de desarrollo de funcionalidades.

Revelación de Sturgeon

El noventa por ciento de cualquier cosa es una porquería
Theodore Sturgeon era un autor de ciencia ficción americano que escribió esta frase defendiendo a este tipo de literatura de críticos que opinaban que el 90% era basura. Hay un corolario que dice "La revelación de Sturgeon es cierta salvo para la porquería, donde el 100% es porquería".

El principio de Peter

En una jerarquía, todo individuo tiende a subir hasta alcanzar su nivel de incompetencia
Seguro que todos conocéis ejemplos de ello: un fabuloso desarrollador es ascendido a directivo en una empresa, la cual gana un gestor pésimo y pierde un programador excelente. Doble penalización. Lawrence J. Peter, pedagogo de profesión, ya lo enunció en 1968 en el libro El principio de Peter.

Ley de Hofstadter

La realización de un trabajo siempre dura más de lo esperado, incluso habiéndose tenido en cuenta la Ley de Hofstadter
Esta genial y recursiva Ley creada por el científico, filósofo y académico estadounidense Douglas Hofstadter es absolutamente cierta. Y si no, pensad un poco, ¿cuántas veces habéis estimado un desarrollo, lo habéis incrementado de forma considerable por los imprevistos y aún así os habéis quedado cortos?

Ley de Murphy

Si algo puede ir mal, lo hará
La famosa ley, también enunciada en forma de tostada que recurrentemente cae con la mantequilla hacia abajo, fue dictada por Edward A. Murphy, Jr., mientras trabajaba para la fuerza aérea americana como ingeniero, diseñando un sistema de cohetes experimental. Sería lógico pensar que el experimento acabó en tragedia, pero parece ser que la creación y consideración de esta ley les ayudó a evitar graves desastres en sus pruebas.

Ley de Brook

Incluir trabajadores a un proyecto retrasado hará que vaya aún más lento
Fred Brooks postuló esta ley en su famoso libro The Mythical Man-Month: Essays on Software Engineering como resultado de su experiencia en IBM. Existen variantes y corolarios como "Una señora es capaz de tener un hijo en nueve meses, pero este plazo no puede disminuir por muchas mujeres embarazadas que pongamos a ello". Simplemente genial.

Bueno, ya vale por hoy, pero amenazo con prometo seguir pronto.
jueves, 19 de julio de 2007
Hace tiempo ya, oí hablar sobre el libro The Mytical Man-Month, de Frederick P. Brooks, donde se asegura que los mejores programadores rinden hasta 10 veces más que los que se encuentran en el lado opuesto, los peores. Otras fuentes, como "Facts and Fallacies of Software Engineering" llegan a indicar que la diferencia puede ser incluso de 28 a 1.

Sin duda, la productividad en el desarrollo es algo más que tirar muchas líneas de código por día; ya lo comenta Charles Connell en su artículo It's not about lines of code, donde explica por qué la productividad no puede ser medida en esos términos, de hecho, ¿muchas líneas de código implican un trabajo bien hecho? ¿y si se trata de un nido de bugs?

Así, a lo largo de su artículo, Charles va definiendo y añadiendo características que debería presentar el código creado hasta llegar a una posible unidad de medida de la productividad, líneas de código limpio, simple, correcto y bien documentado por día, para finalmente llegar a la conclusión de que tampoco es del todo apropiado: ¿qué ocurre si un buen desarrollador es capaz de crear una función en 100 líneas de código perfecto y salir de la oficina a la hora habitual, mientras que otros realizan el mismo buen trabajo en 2000 líneas de código trabajando hasta altas horas de la madrugada? ¿quién es más productivo?

La conclusión de Charles es que la productividad de un desarrollador es justamente su habilidad para resolver problemas de forma rápida. La ingeniería del software trata precisamente de eso, de aportar soluciones a los usuarios que usarán el sistema desarrollado, todo lo demás sobra. Sin embargo, como él mismo indica, es realmente difícil medir estas capacidades utilizando indicadores habituales como número de líneas de código, bugs provocados o tiempo de trabajo en la oficina.

Partiendo de esto, en "10 Developers For The Price Of One", Phil Haack, cuyo apellido seguro que lo predestinó a dedicarse a la informática, escribe sobre este tema centrando la medida de la productividad de los desarrolladores en torno al concepto TCO (Total Cost of Ownership), o Coste Total de Propiedad (CTO), e introduce algunas características propias de los buenos desarrolladores que hace que este factor sea óptimo.

La primera de ellas es la asunción de un proyecto como propio, la autosuficiencia en la resolución de problemas, tomar el control, resolver y asumir el avance del mismo como un objetivo personal. De esta forma se libera a los responsables de estar tan pendientes de estos aspectos y se recurre a ellos sólo cuando surgen problemas de entidad y con objeto de plantear una solución. Un desarrollador que escribe código rápido no es productivo, pues requiere de tiempo de los demás, y sobre todo, de aquellos que por sus responsabilidades disponen de menos tiempo.

La segunda hace referencia a la escritura de código con pocos errores. Un mal programador que escriba código muy rápidamente es un generador de bugs a una velocidad proporcional, lo que provocaría un mayor gasto de tiempo del equipo de testeo y control de calidad, así como del propio equipo de desarrollo en la corrección de los errores. Como comenta Phil, de nada vale ir rápido hacia la dirección equivocada.

En la tercera, se introduce el concepto de la creación de código mantenible. Y no sólo pensando en el mantenimiento futuro del software, sino durante el propio desarrollo inicial. Me ha gustado mucho su visión sobre esto, textualmente, Tan pronto como una línea de código sale de la pantalla y volvemos a ella, estamos en modo mantenimiento de la misma". Un código bien escrito, comprensible y limpio puede ahorrar mucho tiempo en el presente y futuro.

En cuarto lugar, comenta que los buenos desarrolladores hacen más con menos código, son capaces de identificar cuándo deben y cuándo no deben escribir software y utilizar componentes o elementos existentes. El reinvento de la rueda, no es beneficioso para nadie, y los buenos programadores suelen y deben esquivarlo.

Teniendo todos estos aspectos en cuenta, Phil retoma el concepto TCO indicando que todos estos factores son importantes a la hora de evaluar la productividad de un desarrollador en tanto en cuanto que influyen en el coste total de tener a un programador en la empresa, y no sólo fijándose en el coste directo que representa su nómina. Por ello asegura que intenta contratar, aunque no siempre lo consigue, al mejor desarrollador que encuentra en cada momento puesto que si es capaz de hacer más con menos código, escribir de forma inteligible, fácilmente mantenible y con menos errores, incrementará la productividad de sus compañeros, directivos y colegas. Por el contrario, un mal desarrollador puede disminuir la productividad de su entorno por los motivos anteriormente expuestos. Por este motivo puede justificarse la relación de 28 a 1 en la productividad entre unos y otros.

Estoy absolutamente de acuerdo con estas apreciaciones, un desarrollador no puede ser evaluado únicamente teniendo en cuenta aspectos cuantitativos como la cantidad de líneas de código que es capaz de generar: si lo que buscas es velocidad a la hora de teclear, contrata a un mecanógrafo, leche. Y aunque para cerrar un proyecto hace falta escribir líneas, tanto o más importante es la calidad con que esto se haga o tener capacidad para decidir cuándo hay que reutilizar en vez de escribir.

Quizás, por poner alguna pega, echo en falta un par de factores que a mi entender son fundamentales para aumentar la productividad en el desarrollo, y están relacionadas con la visión global introducida en el artículo citado anteriomente.

En primer lugar, la capacidad de comunicación bidireccional, es decir, ser tanto capaz de entender los mensajes de los usuarios, de analistas, comerciales o cualquier otro grupo de interés, como transmitir claramente mensajes, problemas o cuestiones siempre adaptándose a su interlocutor. Esta es, en mi opinión, una habilidad difícil de encontrar y que puede repercutir de forma muy negativa en la productividad global de un equipo de trabajo. ¿Quién no ha tenido que desechar código por culpa de un malentendido?

En segundo lugar, es fundamental la facilidad de integración en equipos de trabajo. Los desarrolladores trabajando en islas son difíciles de ver, la complejidad del software actual hace que en casi cualquier proyecto tengan que intervenir varias personas colaborando de forma muy estrecha. Además, en una máquina perfecta de producción de software la información y conocimientos fluyen con facilidad, lo cual influye en la productividad de cada uno de los componentes de la misma.

Curiosamente, ninguna de estas dos habilidades son técnicas... Sin duda esto de la productividad es un tema tan interesante como complejo, ¿eh?

martes, 17 de julio de 2007
Como en internet hay de todo, a alguien se le ha ocurrido desarrollar una bonita web en Flash con un curioso jueguecillo: se nos van mostrando consecutivamente fotografías de personajes (concretamente diez), y debemos identificar cuál de ellos es un inventor de lenguajes de programación y cuál es un asesino en serie (!).

Y es que es verdad que algunos tienen unas pintas... Pero bueno, seguro que si en vez de hacerlo con informáticos lo hacen con cualquier otro tipo de profesionales les habría quedado igual de bien, aunque probablemente perdería el morbo que tienen los programadores y su fama de ser gente rara, muy rara, y con un físico acompañando a su presunta personalidad.

La dirección es: http://www.malevole.com/mv/misc/killerquiz.

He acertado 9 sobre 10, se ve que identifico bien a mis colegas... (me refiero a los programadores, claro ;-)). ¿Y tú? ¿Qué nota has conseguido?
viernes, 13 de julio de 2007
A partir de ayer mismo, por cortesía de Armonth (fundador de SigT), tengo el honor de compartir cartel con los grandes maestros en Planet Webdev, un agregador de blogs sobre programación e internet de lo más recomendable por la cantidad, y sobre todo la calidad, de los autores que colaboran en el proyecto.

Por citar sólo a algunos, podemos encontrar a Anieto2k, Javier Pérez, InKiLiNo, Boja, Xavier, y así hasta 30 figuras de este mundillo.

Espero contribuir desde Variable not found a difundir información y compartir conocimientos y experiencias sobre esta profesión que tanto nos apasiona.
lunes, 9 de julio de 2007
Después de celebrar el primer año de vida del blog le debía un regalito: tener su propio nombre de dominio, que no podía ser otro que http://www.variablenotfound.com/.

Y ya que estaba de obras, he aprovechado para incluir utilidades para feeds de mano de Feedburner, con un interesante conjunto de herramientas para la suscripción que espero faciliten la vida a más de uno.

En ambos casos el cambio ha resultado sencillísimo. Ha bastado la inclusión de un registro CNAME en el panel de control DNS del dominio para declararlo como alias de un servidor Google y la modificación en un parámetro de la configuración Blogger para que el servidor comenzara a responder al nuevo nombre. El procedimiento viene muy bien descrito, aunque en inglés, en la dirección http://help.blogger.com/bin/answer.py?answer=55373&hl=en&ctx=rosetta.

Feedburner, como servicio con solera en este mundillo, ofrece también una instalación de lo más sencilla. Una vez completado el registro como usuario, dispone de un generador de código HTML a través del cual podremos ir añadiendo los enlaces a los distintos tipos de suscripción disponibles. Por tanto, como viene siendo habitual en estos servicios, todo se reduce, a lo sumo, a una secuencia de copiar y pegar.

De todas formas estaré durante un tiempo alerta por si detecto algo que funcione mal; confío que me aviséis si véis algo raro, eh?

He dejado para más adelante otros cambios que tengo en mente, como pegar el salto a WordPress, o modificar totalmente el aspecto de la página. Pero esto será ya otra historia...
domingo, 8 de julio de 2007
Uno, que es inocente por naturaleza, asume que utilizar AJAX, acrónimo cuyas siglas corresponden con Asynchronous Javascript And XML, implica el uso de Javascript, comunicación asíncrona con el servidor y XML como formato de intercambio de información.

Lo primero es absolutamente cierto. Javascript es la base actual de AJAX; sin duda es el lenguaje de moda para la programación de funcionalidades avanzadas en cliente, está relativamente bien soportado por los navegadores modernos (o al menos son bien conocidas las particularidades de cada browser) y ofrece una potencia más que suficiente para lo que habitualmente pretendemos utilizarlo.

Lo segundo, la comunicación asíncrona con el servidor, es sólo relativamente cierto. Además de ser posible y útil la comuncación síncrona, hoy en día el término AJAX se utiliza con demasiada frecuencia; basta hacer una web tenga algún script para asegurar que estamos usando esa tecnología punta. Y no, señores, que los menús dinámicos ya se hacían con DHTML hace muuchos muuuchos años.

Sin embargo, hay librerías y frameworks AJAX que, entre otras características, incluyen funciones con efectos visuales realmente espectaculares, y esto cala muy rápidamente en los usuarios y desarrolladores al ser realmente sencillos de integrar y utilizar. De hecho, es fácil encontrar aplicaciones que utilizan de forma masiva estos componentes y no utilizan intercambio de datos alguno con el servidor.

Y por último, la gran decepción: no tiene por qué usarse XML. Lo que parecía tan obvio (de hecho, en un nuevo alarde de ignorancia y osadía lo aseguré en el post Llamar a servicios web con ASP.NET AJAX paso a paso), no es así la mayoría de las veces, y me explico.

XML, a pesar de su estandarización, interoperabilidad y claridad de lectura es lento a la hora de ser procesado. Si habéis probado a manejar un documento complejo usando XMLDOM o similares, habréis comprobado lo engorroso y lento que resulta recorrer o crear la estructura y acceder a sus elementos. Y claro, si se utiliza este lenguaje para comunicar cliente con servidor se supone que esta complejidad se produce en ambos extremos del intercambio de datos, lo cual no resulta agradable ni a la hora de desarrollarlo ni una vez puesto en explotación, puesto que se pretende que este intercambio sea rápido.

En su lugar se suelen utilizar formatos más ligeros, fácilmente procesables y manejables tanto desde cliente como desde servidor, y aquí la estrella es JSON (JavaScript Object Notation), un formato ligero para el intercambio de información basado, como XML, en texto plano, muy estructurado, de fácil lectura, con una gran difusión y, sobre todo, muy fácil de procesar tanto desde Javascript como desde software en servidor. Una prueba de su popularidad es que el propio Yahoo! adoptó JSON como formato de intercambio de datos con sus servicios, aunque sigue permitiendo XML.

Sin embargo, como siempre que existen distintas opciones para hacer lo mismo, hay un fuerte debate sobre la conveniencia de usar XML o JSON, con continuas luchas entre uno y otro bando en las que se aportan las ventajas de utilizar una opción y las debilidades de la opuesta. Vamos, lo de siempre (Windows/Linux, Internet Explorer/Firefox, PlayStation/Xbox, Burger King/Mc Donnald's...).

Como curiosidad, decir que se ha llegado a acuñar el término AJAJ para identificar a la tecnología que combina el Javascript Asíncrono con JSON (de ahí la "J" final), pero es obvio que el término no es tan atractivo como AJAX y ha sido descartado. Además, el uso de otros formatos de intercambios podría dar lugar a extrañas variaciones de las siglas que inundarían el ya colmado espacio mental reservado para estas aberraciones. Por ejemplo, si en vez de XML usamos HTML, la tecnología debería llamarse AJAH; si la complementamos con CSS podría ser AJACH; si usamos también comunicación síncrona necesitaríamos SAJACH. Y así hasta el infinito y más allá.

Por ello, y esto sí que es importante, parece que existe finalmente un gran consenso respecto a la utilización del término Ajax (mayúsculas la inicial, minúscula el resto), de forma que deje de ser un acrónimo y se convierta en un nombre propio que identifique a la filosofía, no al conjunto de tecnologías que se usan por debajo. Esto, además, supone un giro radical en su definición: mientras que AJAX es un término centrado en la tecnología, Ajax está centrado en el usuario, en lo que ve, en lo que obtiene, en su forma de relacionarse con el sistema, relegando los aspectos tecnológicos a un segundo plano.

Por cierto, otro día dedicaré un post en exclusiva a JSON, que creo que es lo suficientemente interesante como para dedicarle un ratito.

martes, 3 de julio de 2007

Sí, he de admitir que es una pregunta rara, pero me la hago desde que conocí hace ya muchos años que en lenguaje C podía incrementar una variable de tres formas, autoincrementando (var++), incrementando en uno (var+=1) o sumando la unidad (var=var+1)... ¿hay alguna diferencia entre ellas? Esta absurda inquietud la he mantenido durante lustros, viendo cómo estas construcciones se propagaban hacia lenguajes más actuales con sintaxis basada en C, como C++, C# o Java.

Claro está que desde el punto de vista semántico no existe diferencia alguna, pues todas comparten el mismo objetivo: incrementar en una unidad la variable indicada. Sin embargo, ¿existe diferencia en la forma en que el compilador las trata? ¿se genera código más eficiente utilizando una de ellas, o son absolutamente iguales?

Para responder a esta cuestión, he realizado una pequeña aplicación en varios lenguajes y plataformas, generado posteriormente un ejecutable y desensamblado el binario de salida con la herramienta correspondiente en cada caso. A continuación describo los resultados obtenidos.

En primer lugar, he atacado al lenguaje C, compilado bajo Linux con gcc y desensamblando con ndisasm.

La aplicación con la que he realizado las comprobaciones era la siguiente:

#include "stdio.h"
main()
{
int i;
i = 0x99f;
i++;
i += 1;
i = i + 1;
printf("Vale: %d", i);
}

Nota: el 0x99f con el que inicializo la variable "i" me sirve para buscar rápidamente en el código ensamblador dónde se encuentran las instrucciones a estudiar.

Bueno, a lo que vamos. Una vez compilado y desensamblado, el código que encuentro es:

...
mov word [di-0x8], 0x99f
add [bx+si], al
add word [di-0x8], byte +0x1
add word [di-0x8], byte +0x1
add word [di-0x8], byte +0x1
...

Según parece, el compilador gcc ha generado exactamente el mismo código en todos los casos. La verdad es que este resultado me ha sorprendido un poco, esperaba que se utilizaran en los primeros casos las instrucciones de incremento directo del procesador, optimizando el binario generado, pero no ha sido así. A la vista de esto, he preguntado a Google y parece ser que es un comportamiento recomendado para los compiladores de C, por lo que podemos dar por concluida esta línea de la investigación.

A continuación he pasado a C#, compilando tanto con .NET Framework de Microsoft como con Mono. La aplicación era similar a la anterior (traducida, obviamente), y el resultado en lenguaje intermedio (MSIL), obtenido tanto con ildasm como con su equivalente monodis es el mismo:

[...]
//000011: int i = 0x99f;
IL_0001: ldc.i4 0x99f
IL_0006: stloc.0
//000012: i++;
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: add
IL_000a: stloc.0
//000013: i += 1;
IL_000b: ldloc.0
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: stloc.0
//000014: i = i + 1;
IL_000f: ldloc.0
IL_0010: ldc.i4.1
IL_0011: add
IL_0012: stloc.0
[...]

Podemos observar que, como en el caso anterior, el compilador no diferencia entre el tipo de incremento que utilicemos, da exactamente igual.

Por último, probamos con Java 5, utilizando el JDK de Sun. La aplicación es exactamente igual a las anteriores, con la correspondiente adaptación a este lenguaje, algo así como:

class Prueba
{
public static void main(String[] args)
{
int i = 0x99f;
i++;
i+=1;
i=i+1;
System.out.println("Vale: " + i);
}
}

El compilador de Java, en este caso, sí hace distinciones entre los dos primeros modelos de incremento y el tercero. El autoincremento e incremento los genera exactamente iguales, creando una instrucción bytecode de incremento en una unidad, mientras que el último lo crea como una suma; supongo que la primera será posible optimizarla y su ejecución será más rápida:

 0: sipush 2463
3: istore_1
// i++:
4: iinc 1, 1
// i+=1:
7: iinc 1, 1
// i=i+1:
10: iload_1
11: iconst_1
12: iadd
13: istore_1
// Resto...
[...]

En resumidas cuentas, podemos usar con toda tranquilidad cualquiera de los operadores de suma para incrementar una variable, puesto que el código será igual de eficiente (o poco eficiente, según se mire) y prácticamente no tendrá incidencia en la velocidad de ejecución, al menos con las opciones de compilación por defecto. Sólo Java parece estar adelantado en este sentido, pues es capaz de distinguir estos casos.

Y sí, era una inquietud de lo más absurda, lo dije desde el principio, pero me he quedado muy tranquilo, y con una duda menos en mi saco de ignorancia.

domingo, 24 de junio de 2007
Hace unos días, visitando Caso Patológico, encontré un código javascript mediante el cual podía obtenerse de forma muy sencilla el contenido del portapapeles del visitante de una página, siempre que éste utilizara un navegador inseguro.

De hecho, si visitáis la página con IE6, podréis observar a la derecha un aviso en el que se advierte de la inseguridad a la que estáis expuestos al utilizarlo, mostrando además parte del contenido de vuestro portapapeles, es decir, lo último que habéis copiado (control+c), por ejemplo desde un editor de textos.

Si combinamos esta idea con la capacidad de ASP.NET AJAX, framework del que ya llevo publicados varios post, para invocar desde cliente funcionalidades en servidor, resulta un proyecto tan simple como interesante: crear una base de datos en servidor con el contenido del portapapeles de los visitantes de una página. Desde el punto de vista tecnológico, vamos a ver cómo podemos utilizar Ajax para comunicar un script cliente con un método de servidor escrito en C#; desde el punto de vista ético, lo que vamos a hacer pertenece un poco al lado oscuro de la fuerza: vamos a enviar al servidor (y éste lo va a almacenar) información importante, que puede llegar a ser muy sensible, sin que el usuario se percate de lo que está ocurriendo.

Para ello crearemos una página ASP.NET en la que introduciremos un código script que, una vez haya sido cargada, obtenga el contenido textual del portapapeles y lo envíe, utilizando un PageMethod, al servidor, quien finalmente introducirá este contenido y la dirección IP del visitante en una base de datos local. Como almacén vamos a usar SQL Express, pero podríamos portarlo fácilmemente a cualquier otro sistema.

Empezaremos desde el principio, como siempre. En primer lugar, recordar que es necesario haberse instalado las extensiones ASP.NET AJAX, descargables gratuitamente en esta dirección. Una vez realiza esta operación, podremos crear en Visual Studio 2005 un sitio web Ajax-Enabled, utilizando una de las plantillas que se habrán instalado en el entorno.

Después de esta operación, el entorno habrá creado por nosotros un sitio web con todas las referencias y retoques necesarios para poder utilizar AJAX. En particular, tendremos un Default.aspx cuyo único contenido es un control de servidor ScriptManager, del que ya hemos hablado en otras ocasiones.

Pues bien, acudiendo al código de la página (.aspx), introducimos ahora el siguiente script:


<script type="text/javascript">
$addHandler(window, "onload", salvaClipboard);
function salvaClipboard()
{
if (window.clipboardData)
{
var msg=window.clipboardData.getData('Text');
if (typeof(msg) != "undefined" &&
(msg != "") && (msg != null))
{
PageMethods.SaveClipboard(msg);
}
}
}
</script>

 

Nótese, en primer lugar, la forma en la que añadimos un handler al evento OnLoad de la ventana. El alias $addHandler, proporcionado por el framework Ajax en cliente, nos facilita la vinculación de funciones a eventos producidos sobre los elementos a los que tenemos acceso desde Javascript.

En segundo lugar, fijaos la forma tan sencilla de obtener el contenido del portapapeles de windows: window.clipboardData.getData('Text');. Los ifs previos y posteriores son simples comprobaciones para que el script no provoque errores en navegadores no compatibles con estas capacidades.

Por último, una vez tenemos en la variable msg el texto, lo enviamos vía un PageMethod al servidor, que lo recibirá en el método estático correspondiente, definido en el code-behind de la misma página (default.aspx.cs). Como hemos comentado en otras ocasiones, es el ScriptManager el que ha obrado el milagro de crear la clase PageMethods e introducir en ella tantos métodos como hayan sido definidos en el servidor y así facilitar su llamada de forma directa desde el cliente.

Vayamos ahora al lado servidor. En el code-behind sólo hemos tenido que incluir el siguiente código en el interior de la clase:


[WebMethod()]
public static void SaveClipboard(string texto)
{
string client =
HttpContext.Current.Request.UserHostAddress;
SqlConnection conn =
new SqlConnection(Settings.Default.ConnStr);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "Insert into Portapapeles "+
"(Ip, Clipboard) Values (@ip, @texto)";
cmd.Parameters.AddWithValue("ip", client);
cmd.Parameters.AddWithValue("texto", texto);
try
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
// Nada que hacer!
}
}

 

Simple, ¿eh? La llamada a PageMethod.SaveClipboard en el cliente invoca al método estático del mismo nombre existente en la página del servidor, siempre que éste haya sido adornado con el atributo System.Web.Services.WebMethod. El parámetro "texto", con el contenido del portapapeles del cliente, se recibe como string de forma directa y transparente, sin necesidad de hacer ninguna conversión ni operación extraña.

Una vez obtenida también la IP del visitante usando el HttpContext (hay que recordar que el método es estático y por tanto no tiene acceso a las propiedades de la propia página donde está definido), se establece la conexión con la base de datos y se almacena la información.

Y eso es todo, amigos. Como habéis podido comprobar, es realmente sencillo utilizar Ajax para enviar desde el cliente información al servidor utilizando scripting y el framework AJAX proporcionado por Microsoft. Si esto lo unimos a la capacidad de extraer información local del equipo del visitante en determinados navegadores, los resultados pueden ser espectaculares y realmente peligrosos. Afortunadamente, las nuevas generaciones de browsers (IE7 incluido) se toman la seguridad algo más en serio y hacen más difícil la explotación de este tipo de funciones.

Finalmente, como siempre, indicar que he dejado en Snapdrive el proyecto completo, base de datos incluida, para que podáis probarlo (AjaxClipboardSpy.zip). Ojo, para que todo funcione debéis cambiar la ruta del archivo .MDF de SQL Express sobre el archivo Settings.settings de la aplicación.
domingo, 17 de junio de 2007

Hace unas semanas publicaba un par de posts con ejemplos de utilización del framework ASP.NET AJAX, donde se podía ver cómo invocar desde Javascript funcionalidades escritas en servidor y actualizar el contenido de una página web de forma dinámica, sin postback alguno.


En el primero de ellos veíamos cómo acceder a un servicio web desde javascript, paso a paso, mientras que en el segundo invocábamos funcionalidades de servidor llamando a métodos estáticos contenidos en el interior de una página (PageMethods). Sin embargo, en ambos casos se trataba de llamar a funciones que devolvían un string después de realizar alguna operación, y pudimos ver que resultaba realmente sencillo gracias al control ScriptManager incluido en la página.


Pero el framework AJAX va más allá, y permite incluso la comunicación cliente-servidor y viceversa utilizando entidades de datos propias. En otras palabras, podríamos retornar tipos complejos desde un método en servidor y utilizarlo desde cliente con toda la naturalidad del mundo, o instanciar en cliente tipos de datos declarados en servidor y enviárselos posteriormente para su tratamiento. Con esto conseguimos saltar lo que hasta ahora era una barrera infranqueable en una aplicación Web: el paso de entidades o datos estructurados de forma bidireccional entre cliente y servidor.


A lo largo de este post vamos a realizar un ejemplo completo que permite ilustrar cómo podemos hacer que un objeto se desplace cual pelota de ping-pong entre cliente y servidor sin provocar recargas de página completa. La lógica a implementar será bastante simple; como respuesta a la pulsación de un botón, el cliente generará un mensaje y se lo enviará al servidor. El mensaje será un objeto de tipo Mensaje, definida en C# (servidor) de la siguiente forma:


public class Mensaje
{
public string Remitente;
public string Destinatario;
public DateTime Fecha;
public int Numero;
}
 

Ya veremos como desde javascript podemos, de forma casi milagrosa, crear instancias de esta clase, acceder a sus atributos, enviar objetos al servidor, y obtenerlos desde éste de forma muy muy sencilla y transparente.


El primer mensaje enviado por el cliente establecerá la Fecha actual, el campo Numero a 1, el Remitente será un nombre introducido por pantalla y el Destinatario contendrá el valor "servidor". Cuando el servidor recibe este mensaje, incrementa el valor del atributo Numero, intercambia el remitente y el destinatario del mensaje y lo enviará de vuelta al cliente, quien lo dejará almacenado hasta que se vuelva a pulsar el botón de envío, que provocará de nuevo un intercambio del destinatario y el emisor del mensaje, así como un incremento del número de serie. El siguiente diagrama muestra una secuencia completa de este "peloteo":



Una vez explicado el escenario en el que vamos a jugar, pasamos a la acción, no sin antes recordar que necesitamos tener instalado el framework ASP.NET AJAX, descargable en la dirección http://ajax.asp.net/.


Partimos de un sitio web Ajax-Enabled, con todas las referencias y retoques en el web.config que el asistente de Visual Studio crea por nosotros. Este sitio, como ya se comentó en un post anterior, se puede crear utilizando la plantilla que se habrá instalado en nuestro entorno de desarrollo junto con el framework AJAX.


En primer lugar, vamos a montar el interfaz cliente, sobre el archivo default.aspx (reproduzco sólo las etiquetas incluidas entre la apertura y cierre del cuerpo <body> de la página):


 <body>
<form id="form1" runat="server">
<fieldset>
<input type="text" id="nombre" />
<input id="Button1"
type="button"
value="¡Pulsa!" onclick="llamar();" />
</fieldset>
<asp:ScriptManager ID="ScriptManager1"
runat="server"
EnablePageMethods="True" />
</form>
<div>
<strong>Mensajes obtenidos:</strong>
<br />
<label id="lblMensajes" />
</div>
</body>
 

Podemos observar que hemos creado un formulario con un cuadro de edición y un botón. El primero servirá para que el usuario introduzca su nombre y el segundo para enviar el mensaje al servidor. Es importante destacar que en ninguno de los dos casos se trata de controles de servidor, no hay runat="server" por ninguna parte. No es necesario debido a que todo se realizará en cliente, y las funcionalidades de servidor se invocarán mediante AJAX.


Después de estos se ha incluido el ScriptManager, que ya en otras ocasiones hemos identificado como el responsable de hacer posible la magia, el acceso transparente a las funcionalidades de servidor. En este caso, le hemos activado la propiedad EnablePageMethods para que podamos llamar con javascript a un método estático de servidor definido en el código de la página actual, en el code-behind (default.aspx.cs).


Por último, disponemos de una etiqueta donde iremos mostrando de forma sucesiva los mensajes intercambiados entre ambos extremos, modificando su contenido de forma dinámica.


Pasemos ahora a la parte de lógica en cliente, las funciones javascript. En primer lugar tenemos la función llamar(), establecida como controlador del evento click del botón del formulario:


 function llamar()
{
var msg;
if (ultimoMensaje == null)
{
msg = new Mensaje();
msg.Remitente = $get("nombre").value;
msg.Numero = 1;
}
else
{
msg = ultimoMensaje;
msg.Remitente = ultimoMensaje.Destinatario;
msg.Numero = ultimoMensaje.Numero + 1;
}
msg.Destinatario = "servidor";
msg.Fecha = new Date();
mostrarMensaje(msg);
PageMethods.EcoMensaje(msg, OnOK);
}
 

Creo que se puede entender simplemente leyendo el código, pero lo explico un poco. La primera vez que se ejecuta la función atendiendo a la pulsación del botón, se crea en cliente una instancia de la clase Mensaje, asignando a sus atributos los valores iniciales: el remitente (tomado del cuadro de edición), el número de serie (inicialmente 1), el destinatario y la fecha del envío. La variable ultimoMensaje almacenará el último mensaje obtenido del servidor (ya lo veremos más adelante) y sólo será nula la primera vez; en las sucesivas entradas a la función llamar(), ésta se limitará a incrementar el número de serie del mensaje, y a intercambiar el remitente por el destinatario.


Eh, pero un momento... decíamos que la clase Mensaje se había creado en el servidor, en C#, ¿cómo es posible que podamos instanciar en cliente una clase definida en servidor? Pues como siempre, gracias a la intermediación del ScriptManager, que ha detectado que existe un PageMethod que utiliza la clase y ha creado una clase "espejo" en cliente. Desde luego es impresionante lo bien que hace su trabajo este chico.


Volviendo al código anterior, podemos observar que además de componer el objeto a enviar al servidor, se llama a la función mostrarMensaje(), cuyo único objetivo es mostrar el mensaje en pantalla, añadiéndolo al contenido de la etiqueta "lblMensajes" definida en el interfaz. Por último, llama al método EcoMensaje de la clase PageMethods que el ScriptManager ha creado para nosotros, provocando la llamada asíncrona al método en servidor, al que además envía el Mensaje creado. El segundo parámetro de la llamada indica la función de notificación asíncrona, donde se enviará el control una vez el servidor devuelva la respuesta, cuyo código es así de simple:



 function OnOK(mensaje)
{
ultimoMensaje = mensaje;
mostrarMensaje(mensaje);
}
 

Está claro, ¿no? A nuestra función de notificación llega como parámetro que es el valor retornado por el método del servidor al que hemos invocado. Como veremos un poco más adelante, este método devuelve un objeto de tipo Mensaje, que podemos almacenar en la variable ultimoMensaje y mostrar por pantalla como hacíamos justo antes de llamar al servidor.


Y veamos ahora la parte del servidor, escrita en C# en el archivo code-behind "Default.aspx.cs". Por una parte tenemos definida la clase Mensaje, con el código que hemos visto un poco más arriba, y el método de página (Page Method) al que estamos invocando desde el script:


 [WebMethod()]
public static Mensaje EcoMensaje(Mensaje m)
{
m.Numero = m.Numero + 1;
string tmp = m.Destinatario;
m.Destinatario = m.Remitente;
m.Remitente = tmp;
m.Fecha = DateTime.Now;
return m;
}
 

Atención aquí. El método, marcado con el atributo WebMethod() para que el ScriptManager sepa que existe, recibe como parámetro el Mensaje que hemos enviado desde el cliente. De nuevo el framework está haciendo magia poniendo a nuestra disposición el mensaje en el idioma que habla el servidor, como una clase cualquiera escrita en .NET. Es la infraestructura AJAX la que está encargándose de convertir los datos enviados desde el cliente en formato JSON en una instancia de la clase, con sus correspondientes campos rellenos.


Obsérvese además que desde el código simplemente tomamos el objeto que nos ha enviado el cliente, le asignamos valores a sus atributos y lo enviamos de vuelta al mismo. Para que la función OnOk, descrita anteriormente, reciba este objeto como parámetro en formato nativo javascript, la infraestructura Ajax deberá serializar la clase .NET y enviarla de vuelta, también utilizando JSON (por cierto, a ver si otro día me acuerdo y hablamos un rato sobre JSON, un tema interesante!).


A continuación se muestra una captura de pantalla del sistema en funcionamiento:



Como de costumbre, he puesto en Snapdrive una copia del proyecto VS2005 completo, para los que quieran jugar un poco con esto sin molestarse demasiado. Puedes descargarlo aquí: AjaxPingPong.zip.

jueves, 14 de junio de 2007
Hay veces que encuentras por internet herramientas que no tienen una utilidad demasiado grande pero resultan curiosas. Este es uno de esos casos.

Se trata de SelectOracle (algo así como Selectoráculo), una herramienta on-line que traduce cadenas de selectores, indicados según el estándar CSS 3.0, al español, inglés y, de forma aún incompleta, al alemán y búlgaro.

¿Y qué signica esto? Para que os hagáis una idea, reproduzco una serie de selectores que le he enviado y la respuesta que me ha devuelto la herramienta:

Selector: *
Traducción: Selecciona cualquier elemento.

Selector: p a
Traducción: Selecciona cualquier elemento a que es descendiente de un elemento p.

Selector: div#main > p + a[title]
Traducción: Selecciona cualquier elemento a con un atributo title que sigue inmediatamente a un elemento p que es hijo de un elemento div con un atributo id que equivale a main.

Como se puede ver, es en casos con cierta complejidad como este último donde la herramienta puede sernos de ayuda.

Una prueba más de que en internet hay de todo, sólo hace falta buscar un poco.