Archivo por meses: octubre 2013

C# 5.0: Nuevas características

Esta “nueva” versión (lanzada en Agosto del 2012) de C# incluido en .NET Framework 4.5, incluye algunas novedades que voy a mencionar a continuación, pero que se basa fundamentalmente en la implementación del “asincronismo” de una forma mucho más sencilla que con sus predecesores, ya que a la hora de trabajar con Multithreading no deberemos tirar muchas más líneas de código con respecto a la programación síncrona/secuencial de toda la vida.

Evolución de C#

“Async” o asincronismo más sencillo

Como he comentado anteriormente, esta característica representa el groso de la nueva versión que Microsoft publicó con respecto a su lenguaje de programación estrella, C# 5.0.

La API para programar asíncronamente es sencilla de entender, ya que todos aquellos que hayan estudiado un poco sobre el tema enseguida le sacarán parecido a otras implementaciones de lenguajes de programación como JAVA, C, NodeJS…

En el apartado de programación asíncrona, vamos a manejar un ejemplo sencillo con la clase WebClient, que nos permitirá descargar un documento de manera asíncrona dándole al usuario la posibilidad de poder realizar otro tipo de acciones mientras esta tarea se resuelve, además me parece muy interesante porque no solo se puede aplicar a aplicaciones de escritorio (WinForms), sino que también es aplicable a Web (ya sea WebForms o MVC).

Esto para las aplicaciones de escritorio es un problema muy común, ya que al tardar demasiado tiempo Windows se impacienta y notifica que la aplicación “no responde”, por tanto se bloquea y damos una imagen al usuario bastante pobre de nuestro nivel como programadores.

API Síncrono: WebClient.DownloadString

API Asíncrono: WebClient.DownloadStringAsync

Con el uso de este método solventamos el problema de bloqueo de procesos, de forma transparente para el programador y dotar así al usuario de una mayor flexibilidad a la hora de interaccionar con nuestra aplicación.

Muy bien, ya tenemos una solución a nuestro problema de bloqueo de procesos, pero ahora nos surge otro problema, no sabemos cuando se finaliza ese proceso al que estamos esperando, y por tanto ejecutarlo en el hilo/proceso correspondiente para evitar posibles excepciones que nos pueda indicar nuestra pila con un mensaje esclarecedor de que estamos en una ejecución fuera de contexto.

WebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(WebClient_DownloadStringCallback);
public void WebClient_DownloadStringCallback (object sender, DownloadStringCompletedEventArgs e)
{
   this.txtResult.Text = e.Result;
}

Para solucionar el problema explicado anteriormente, tendremos un manejador de eventos dedicado especialmente para rescatar el resultado de la llamada asíncrona que hemos realizado, así de una forma muy sencilla podremos acceder al hilo que quedó a la espera de la descarga del documento que solicitamos previamente. Más adelante os mostraré los hilos de ejecución que tenemos disponibles y así hacernos una idea por donde transcurre el programa.

Una vez entendemos cómo realizar una llamada asíncrona, vamos a ver como se hacía antes y como lo haríamos ahora en .NET. En el caso del código de servidor existe una clase llamada SynchronizationContext que soluciona este problema en versiones anteriores (nos ayuda a manejar las requests” y las “responses” pertenecientes a un mismo contexto/hilo) funciona con ASP.NET, WPF, Win Forms…

Antes de C# 5.0

A continuación veremos con un ejemplo sencillo, cómo obtener de forma asíncrona los headers presentes actualmente en una web HttpWebRequest, si queremos obtener solamente los headers incluimos en:  HttpWebRequest.Method = “HEAD”  y a continuación implementamos el siguiente código:

HttpWebRequest.BeginGetResponse(
      asyncResult => {
            var resp = (HttpWebResponse) HttpWebRequest.EndGetResponse(asyncResult);
            string headersText = FormatHeaders (resp.Headers);
            this.txtResult.Text = headersText;
      },
      null);

Como vemos, para la llamada BeginGetResponse debemos llamar a un delegado que será el encargado de continuar con la ejecución una vez se ha completado la “request”, en este caso la obtención de los headers y almacenarlos en una caja de texto. También cabe mencionar que como último parámetro es posible incluir cierta información arbitraria, dicha información podría servirnos como añadido a nuestra llamada asíncrona y utilizarla para tal efecto.

En este primer ejemplo, se verá como obtenemos una excepción ya que intentamos asignar los headers de la respuesta a la caja de texto en un hilo distinto al que deberíamos, Main Thread sería el encargado de hacer esta tarea y en cambio es otro hilo secundario el que lo hace…

Threads Asíncronismo
Threads Asíncronismo

Por lo tanto, para solucionar este problema debemos utilizar la clase SynchronizationContext para poder asignar en su delegado dentro del evento BeginGetResponse el resultado a la caja de texto, a continuación veríamos como queda el código:

  var sync = SynchronizationContext.Current;
  HttpWebRequest.BeginGetResponse(
        asyncResult => {
               var resp = (HttpWebResponse) HttpWebRequest.EndGetResponse(asyncResult);
               string headersText = FormatHeaders (resp.Headers);
                   sync.Post(
                        delegate {
                             this.txtResult.Text = headersText;
                        },
                   null);
        },
  null);

Con este código tenemos el comportamiento normal de Multithreading, donde el hilo padre continúa su ejecución de forma normal hasta que finaliza (queda dormido, esperando a sus hijos, en este caso asyncResult), esto lo hacemos gracias al método Post que contiene la clase SynchronizationContext, tal y como entendemos por su nombre se encarga de capturar la finalización de la petición en su hilo correspondiente (padre) para terminar la ejecución del mismo, de esta forma podemos evitar posibles errores de contexto en la ejecución de nuestro programa.

Nota: Para aquellos que tengan un poquito más de conocimiento sobre el tema, deciros que ya no peligra el famoso estado de “inanición” de nuestros procesos gracias a la implementación del asincronismo facilitado por .NET Framework 4.0.

Resumiendo, antes con C# 4.0 era necesario implementar hasta 3 diferentes métodos para el correcto funcionamiento del asincronismo, eso sí de forma muy sencilla y aplicando el patrón de eventos asíncronos, comúnmente conocido como EAP ya disponible en la versión 2.0 de .NET.

Ahora con C# 5.0

Para empezar a trabajar con Async debemos añadir una nueva referencia a nuestro proyecto: AsyncCtpLibrary.dll localizada en ..\Microsoft Visual Studio Async CTP\Samples\. Ahora vamos a pasar a la implementación del asincronismo en unos pocos pasos muy sencillos de codificar:

1.  Declarar nuestros eventos asíncronos:

protected async void btnConfirmar_Click(object sender, RoutedEventArgs e)
{
}

Así cualquier desarrollador que retome este código sabrá que este método se utilizará de forma asíncrona en nuestra aplicación, podemos asemejarlo a la inclusión de los atributos [HttpGet] o [HttpPost] en la cabecera de las acciones MVC, indicando que tipo de peticiones atiende nuestro método. Pues aquí lo mismo, pero asociado al tipo de ejecución que se llevará a cabo (síncrono o asíncrono).

2.  Adaptar el código visto anteriormente para que nuestro compilador pueda atenderlo de forma asíncrona:

protected async void btnConfirmar_Click(object sender, RoutedEventArgs e)
{
     WebClient w = new WebClient();
     string txt = await w.DownloadStringTaskAsync("Mi url");
     this.txtResult.Text = txt;
}

La keyword “await” indica al compilador que esta sentencia será un trabajo a desempeñar de forma asíncrona y por tanto deberá tenerlo en cuenta en el momento de ejecución.

Como comentamos anteriormente, esto es muy útil cuando tenemos ciertas peticiones que no se pueden tener esperando más tiempo de lo normal o simplemente nos pueda devolver un 404/timeout, en ese período de tiempo el usuario podrá hacer más cosas mientras espera el resultado del click del botón.

Por tanto, await está preparado para funcionar con TPL (Task Parallel Library) que ya fue incluido en C# 4.0 donde  WebClient.DownloadStringTaskAsync devuelve un System.Threading.Task<string>. Pero claro en el caso de HttpWebRequest o HttpWebResponse no podemos trabajar con TPL tal cual, sino que debemos utilizar el modelo de programación asíncrona mediante la creación de tareas. Esto lo podemos ver en el siguiente ejemplo:

private async void btnConfirmar_Click(object sender, RoutedEventArgs e)
{
    var req = (HttpWebRequest) WebRequest.Create("mi url");
    req.Method = "HEAD";
    Task<WebResponse> getResponseTask = Task.Factory.FromAsync<WebResponse>(req.BeginGetResponse, req.EndGetResponse, null);
    var resp = (HttpWebResponse) await getResponseTask;
    string headersText = FormatHeaders (resp.Headers);
    this.txtResult.Text = headersText;
}

Como vemos en el código anterior,  HttpWebRequest no contiene una sobrecarga de algún método que podamos ejecutar de forma asíncrona (como WebClient), con lo cual debemos utilizar el TaskFactory para crear una tarea que luego posteriormente será tratada como asíncrona con la palabra reservada “await“, para hacer esto siempre debemos indicar la ejecución del código asíncrono y el método que recogerá la finalización de dicha ejecución:

csharp-5-async-3

El único requisito que debemos tener en cuenta, es el tipo de datos que devolvemos para posteriormente tratarlo en nuestro callback de la llamada asíncrona, es decir, si nuestra instancia Task que debe gestionar TaskFactory es de tipo string también debemos pasarle este mismo tipo de datos para no obtener ninguna excepción de “casting“.

Conclusion: C# 5.0 pretende que el asincronismo a nivel de código sea igual de simple que la implementación del sincronismo.

Caller Information (Herramientas de diagnosis y seguimiento)

Otra de las principales novedades que trae la nueva versión de C#, es la posibilidad de usar de forma nativa multitud de herramientas de diagnosis y seguimiento, sin tener que depender de aplicaciones/esamblados “third-party”para solucionar problemas tan cotidianos como la depuración, traceo y la creación de herramientas de diagnosis.

Esto nos ahorra (en el caso de ser un equipo de varios desarrolladores) duplicidad en el código, ya que puede pasar que cada utilice su propio sistema de traceo, depuración de errores… duplicando al fin y al cabo la misma funcionalidad.

Por tanto, Microsoft nos facilita las siguientes clases con información útil para este propósito:

Un ejemplo de como utilizar estos nuevos atributos lo podemos ver a continuación:

public void TracingMethod()
{
   TraceException("ERROR!!");
}

public void TraceException(string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("Mensaje de error: " + message);
    Trace.WriteLine("Nombre del método: " + memberName);
    Trace.WriteLine("Path del fichero: " + sourceFilePath);
    Trace.WriteLine("Línea de error: " + sourceLineNumber);
}
//Salida:
//  Mensaje de error: ERROR!!
// Nombre del método: TracingMethod
//  Path del fichero: C:\...\Visual Studio 2012\Projects\...\Tracing\CallerInformation.cs
//  Línea de error: 3

Como podéis ver con este método sencillo de implementar, tenemos cubierto cualquier petición de tracing o depuración de errores en nuestra aplicación.

Bueno pues hasta aquí este artículo dedicado especialmente al lenguaje de programación que yo utilizo diariamente, como vemos Microsoft sigue aportando valor a este excelente lenguaje de programación de alto nivel.

Google no actualiza más el PageRank

Muchos de los webmasters que conozco llevan tiempo preguntándose por qué Google todavía no ha actualizado los valores de PageRank desde Febrero del 2013, existen numerosas teorías acerca de cuáles son los proyectos futuros que tiene Google, todos ellos relacionados con la nueva forma de puntuar/valorar cada sitio web.

google-pagerank-update-2013

Vamos primero con una teoría de cosecha propia, donde por supuesto caben todo tipo de comentarios por vuestra parte. Como todos bien sabemos Google está trabajando mediante su algoritmo Panda, todos y cada uno de los indicadores que pueden hacer una página web interesante o relevante para el público en general, esto mismo hoy en día es muy complicado valorarlo porque existen una seríe de puntos a tener en cuenta muy complejos de manejar:

  1. Medición de la reputación social no sólo en su red (Google+) sino en el resto de redes sociales existentes en el mercado, esto actualmente es muy difícil de medir ya que habría que indexar los contenidos de cada una de las redes sociales y asignarlas de alguna forma a la web que se está valorando en ese momento.
  2. Inclusión del video como contenido de calidad, actualmente Google no tiene forma de indexar todos y cada uno de los videos que subimos a nuestra web, aunque los tengamos subidos a nuestro canal. Los contenidos que exponemos en nuestros vídeos no son relevantes para Google (todavía), ya que el “Transcription method” todavía no está bien depurado y si os fijáis no realiza la traducción del speech como debería. Por tanto, algo que desde todos los medios expertos en SEO se está publicando como futura tendencia predominante en el contenido de calidad, el vídeo, algo que Google todavía no controla del todo a la hora de valorar una web e indexar sus contenidos junto con sus videos. De hecho, actualmente tener en una página sólamente un vídeo, aún siendo super explicativo y super valorado por la audiencia en Youtube, puede conllevar efectos negativos en el posicionamiento de la web si la página no contiene nada más.
  3. Contenido de calidad extraido de un vídeo, justo este apartado es el antagónico del expuesto anteriormente, ahora mismo subir un vídeo (contenido elaborado por nosotros) adjuntando una transcripción exacta del mismo es algo que Goolge agradece y puntúa positivamente, pero claro con esta nueva tendencia podría considerar el texto como contenido duplicado, con lo cuál tenemos un problema… Esto es algo que Google debe tener en cuenta en su algoritmo.
  4. Detectar spammers de contenido, a todo lo citado anteriormente debemos añadirle el trabajo diario que tienen para detectar cuáles son los sitios web que forman parte del conjunto de spammers que utilizan el contenido de otros para beneficiarse tanto en SEO como económicamente. Esto es algo complicado de averiguar, ya que existen numerosas técnicas “black hat” que pueden saltarse esa validación que tiene Google en su algoritmo.
  5. Semántica, un cambio de mentalidad, en el momento que Google incluyó en su algoritmo una restricción a la hora de compartir enlaces, la semántica ha tomado un papel importante en dicha acción, ya que actualmente sólo podremos compartir enlaces o realizar “backlinking” (como queráis llamarlo) con sitios web que tengan algo que ver con nuestro negocio. Esto hace que partamos con un algoritmo lo suficientemente complejo como para retrasar la actualización del Pagerank.

 

Por los factores que os acabo de mencionar, Google no está actualizando el PageRank hasta por lo menos el inicio del 2014. “Oficialmente” desde Google nos llegan noticias de que el Google Toolbar no actualiza dicho dato porque ya casi todos los navegadores no admiten la inclusión de este add-on:

  • Firefox: No tiene actualizaciones de este plugin desde 2011, con lo cuál está obsoleto y ya no se usa.
  • Chrome: Directamente no tiene nada parecido que podamos incluirlo como plugin donde nos de información del PageRank.
  • Internet Explorer: Este era el único navegador que acepta toolbars, hasta ahora, porque desde la versión 10 Microsoft publicó que no iba a permitir la utilización de add-on’s de este tipo.

Por mi parte (y por parte de muchos expertos en la materia), creo que Google está pensando en revolucionar el mercado del SEO con un nuevo concepto de PageRank, esto hará que todos volvamos a investigar acerca de qué esconde esa nueva caja negra que Google ha puesto delante de nuestras narices.

Realmente es una lástima todas las personas que están trabajando en mejorar su posicionamiento SEO no pueden ver reflejado en su PR ese esfuerzo, y por lo tanto no poder “vender” su trabajo a otras compañías con ese valor tan preciado para todos. Personalmente creo que un año de espera valdrá la pena, ya que podremos disfrutar de un juez más justo en este juicio llamado posicionamiento web.