Windows Live Writer

 

Windows Live Writer Aunque lamentablemente no me haya dado  demasiada prisa en hacerlo, tenía ganas de probar este producto. Si habéis utilizado alguna vez el interfaz de edición de Blogger, sabréis que no es precisamente una maravilla, y que a veces complica bastante la publicación de entradas en el blog, y máxime cuando se trata de contenidos con formatos especiales, como puede ser código fuente en cualquier lenguaje.

Live Writer es una fantástica aplicación de escritorio desarrollada por Microsoft en el contexto de su iniciativa Live, cuyo objetivo es facilitar la edición y publicación de entradas en blogs y, lo más curioso, compatible con los motores más difundidos del mercado: Blogger, WordPress, LiveSpaces, LiveJournal, TypePad, y un largo etcétera. Y cuando digo compatible, al menos con Blogger, me refiero a realmente compatible, una integración casi perfecta, que hace que la edición de entradas sea una gozada.

Previsualización de la entradaDurante la instalación, Writer nos solicita la introducción de los datos de acceso al blog: la dirección, el usuario y clave. Con esta información, y por supuesto previa confirmación por parte del usuario, crea automáticamente una entrada temporal en el blog que utiliza para tomarla como plantilla, eliminándola unos segundos después. De esta forma, cuando estamos escribiendo, podemos acceder a una previsualización del contenido insertada en sobre dicha plantilla, que nos dará una idea muy aproximada, prácticamente real, del resultado final que obtendremos una vez publiquemos la entrada.

El editor sobre el que escribimos es muy ligero, tiene las opciones justas para poder escribir y dar formato a los textos, siempre de forma visual (el famoso WYSIWYG). Aunque a primera vista puede parecer que se quedará corto, nada más lejos de la realidad; no he echado en falta prácticamente ninguna característica que realmente pudiera hacerme falta durante la escritura: formatos estándar (negritas-cursivas-tachados, subrayados), colores, tablas, alineados, listas, citas,… y siempre generando un código XHTML realmente limpio y muy bien estructurado, a diferencia de otros editores basados en web (como el de Blogger, por ejemplo).

Sólo en casos especiales (por ejemplo, la inclusión de una etiqueta <acronym> para mostrar ayuda sobre el significado de WYSIWYG, o la inclusión de código fuente marcado con <code> son los únicos casos en los que he tenido que salirme del editor visual y acceder a la vista de código fuente XHTML para introducir las etiquetas.

Otro aspecto muy importante es su extensibilidad. Existen un gran número de complementos que pueden instalarse sobre este software para dotarlo de nuevas capacidades no contempladas en el producto base. Por aunque la galería de complementos de Microsoft todavía está a cero no está muy transitada, es fácil encontrar muchos sitios web donde se ofrecen plugins de todo tipo. Por ejemplo, he encontrado uno que a priori puede resultar muy útil, Steve’s Dunn Code Formatter, que permite incluir fácilmente porciones de código formateadas como la siguiente:

try
{
calculate();
// Hard work!
}
catch (Exception ex)
{
Logger.Log(ex.Message);
throw;
}

Pero lo que sin duda más ha llamado mi atención es la gran facilidad para insertar contenidos multimedia, como álbumes de fotos, vídeos, mapas interactivos, y especialmente imágenes, que es lo que más suelo utilizar en mis posts. En este último caso, es sorprendentemente útil la capacidad de Live Writer para abrir imágenes del equipo local o pegarlas directamente desde el portapapeles (por ejemplo capturas de pantalla), ajustarlas al tamaño indicado e incluso agregarle sobre la marcha efectos como sombreados o reflejos (podéis ver ejemplos más arriba). Por fin se acabó el retoque con aplicaciones externas, tener que subir la imagen al servidor, ver cómo queda, retocarla de nuevo, volver a subirla…

Por último, el hecho de tratarse de una herramienta off-line aporta mucha agilidad, y nos brinda la posibilidad de trabajar en modo desconectado, aunque a costa de perder algunas funcionalidades para las que obviamente es necesario disponer de conexión a internet, como la edición de posts ya publicados, almacenados en el blog, o el envío directo de las entradas. En estos casos, el sistema almacena toda la información en local, para que más adelante podamos enviar los cambios realizados.

Ni que decir tiene que este post está completamente escrito sobre Live Writer, e incluso las imágenes las he generado desde la propia herramienta.

En resumen: una maravilla, imprescindible.

Descarga: Microsoft Live Writer

Publicado en: www.variablenotfound.com.

Formas de relanzar excepciones en C#

PuzzleEs bastante habitual encontrar código que captura una excepción y la vuelve a relanzar tras realizar algún tipo de operación. Sin embargo, habréis observado que existen varias fórmulas para hacerlo, y no necesariamente equivalentes:

  • crear y lanzar una nueva excepción partiendo de la original
  • relanzar la excepción original
  • dejar que la excepción original siga su camino

El primer caso ocurre cuando capturamos una excepción de un tipo determinado, y desde dentro del mismo bloque catch instanciamos y lanzamos otra excepción distinta a la original. Esto permite elevar excepciones a niveles superiores del sistema con la abstracción que necesita, ocultando detalles innecesarios y con una semántica más apropiada para su dominio.

El siguiente ejemplo muestra una porción de código donde se están controlando distintos errores que pueden darse a la hora de realizar una transmisión de datos. Por cada uno de ellos se llevan a cabo tareas específicas, pero se elevan al nivel superior de forma más genérica, como TransmissionException, pues éste sólo necesita conocer que hubo un error en la transmisión, independientemente del problema concreto:

  ...
try
{
transmitir(datos);
}
catch (HostNotFoundException ex)
{
sendToAdmin(ex.Message); // Avisa al administrador
throw new TransmissionException("Host no encontrado", ex);
}
catch (TimeOutException ex)
{
increaseTimeOutValue(); // Ajusta el timeout para próximos envíos
throw new TransmissionException("Fuera de tiempo", ex);
}
...

 
Es importante, en este caso, incluir la excepción original en la excepción lanzada, para lo que debemos llenar la propiedad InnerException (en el ejemplo anterior es el segundo parámetro del constructor). De esta forma, si niveles superiores quieren indagar sobre el origen concreto del problema, podrán hacerlo a través de ella.

Otra posibilidad que tenemos es relanzar la misma excepción que nos ha llegado. Se trata de un mecanismo de uso muy frecuente, utilizado cuando deseamos realizar ciertas tareas locales, y elevar a niveles superiores la misma excepción. Siguiendo con el ejemplo anterior sería algo como:

  ...
try
{
transmitir(datos);
}
catch (HostNotFoundException ex)
{
sendToAdmin(ex.Message); // Avisa al administrador
throw ex;
}
...

 
Este modelo es conceptualmente correcto si la excepción que hemos capturado tiene sentido más allá del nivel actual, aunque estamos perdiendo una información que puede ser muy valiosa a la hora de depurar: la traza de ejecución, o lo que es lo mismo, información sobre el punto concreto donde se ha generado la excepción.

Si en otro nivel superior de la aplicación se capturara esta excepción, o se examina desde el depurador, la propiedad StackTrace de la misma indicaría el punto donde ésta ha sido lanzada (el código anterior), pero no donde se ha producido el problema original, en el interior del método transmitir(). Además, a diferencia del primer caso tratado, como la propiedad InnerException no está establecida no será posible conocer el punto exacto donde se lanzó la excepción inicial, lo que seguramente hará la depuración algo más ardua.

La forma de solucionar este inconveniente es utilizar el tercer método de los enumerados al principio del post: dejar que la excepción original siga su camino, conservando los valores originales de la traza:

  ...
try
{
transmitir(datos);
}
catch (HostNotFoundException ex)
{
sendToAdmin(ex.Message); // Avisa al administrador
throw;// Eleva la excepción al siguiente nivel
}
...

 
En esta ocasión, si se produce la excepción HostNotFoundException, los niveles superiores podrán examinar su propiedad StackTrace para conocer el origen concreto del problema.

Publicado en: www.variablenotfound.com.

Usando using, valga la redundancia (C#)

C#La palabra reservada using tiene diversos usos en el lenguaje C#, y seguro que muchos la utilizamos exclusivamente para importar espacios de nombres (namespaces), ignorando el resto de posibilidades que nos ofrece:

  • Importación de espacios de nombres
  • Definición de alias, tanto de espacios de nombres como de tipos.
  • Adquisición y liberación de recursos

Vamos a dar un repasillo a cada una de estas utilidades, profundizando un poco en aquellas menos habituales.

1. Importación de espacios de nombres

En este caso, la palabra reservada using actúa como una directiva del compilador, haciendo que se puedan utilizar tipos definidos en el espacio de nombres importado sin necesidad de especificarlos de forma explícita en el código.

  using System;
using System.Collections;...

 
Este es el using más común y conocido, así que poco más hay que decir al respecto…

2. Definición de alias

Otra forma de utilizar using como directiva es crear alias, o nombres cortos alternativos, a namespaces o tipos de datos, que ayuden a evitar conflictos en nombres. Veamos cada uno de ellos.

2.1. Alias de espacios de nombres

Puede ser útil cuando tenemos namespaces cuyos nombres coinciden con el de clases, o en situaciones similares que hacen que el compilador no tenga claro qué estamos intentando decirle. Por ejemplo, observad el siguiente código, que no compila, a pesar de ser aparentemente correcto:

  using System;
namespace Prueba
{
class Saludo
{
public static void Run()
{
Console.WriteLine("hola");
}
}
}

namespace OtroNS
{
class Prueba
{
public static void Main(string[] args)
{
Prueba.Saludo.Run(); // No compila
Console.ReadLine();
}
}
}

 
El problema es que para acceder a clase que queremos utilizar (Saludo) desde un namespace distinto a donde se encuentra definida debemos indicar su ruta completa, es decir, especificar en qué espacio de nombres la encontraremos. Sin embargo, en el ámbito de la clase Prueba, el compilador piensa que el código Prueba.Saludo.Run() está intentando acceder a una propiedad de dicha clase, y como no lo encuentra, revienta en compilación.

La solución a esto es bien sencilla utilizando los alias, puesto que permiten hacer referencia a un espacio de nombres o un tipo utilizando una denominación diferente, lo que eliminará la ambigüedad. Podemos, por ejemplo, utilizar el alias predefinido global, que representa al nivel raíz del árbol de namespaces:

      ...
public static void Main(string[] args)
{
global::Prueba.Saludo.Run();
Console.ReadLine();
}
...

 
Otra posibilidad, usando using, sería definir un alias personalizado que nos permitiera acceder al espacio de nombres conflictivo utilizando otro identificador:

  ...
using MiAlias = Prueba;
...
....
public static void Main(string[] args)
{
MiAlias::Prueba.Saludo.Run();
Console.ReadLine();
}
...

 
Observad el uso de los dos puntos (::) para indicar que el identificador que se encuentra a su izquierda es un alias. Esto puede ayudar a evitar conflictos cuando el nombre del alias coincida con el de una clase en el ámbito de visibilidad actual.

2.2. Alias a tipos

De la misma forma, podemos crear fácilmente alias a un tipo definido, bien para evitar conflictos en nombres como los descritos anteriormente, o bien para hacer más rápido el acceso a los mismos. En el siguiente ejemplo puede observarse su uso:

  using Strings = System.Collections.Specialized.StringCollection;
using Con = System.Console;
...
Strings s = new Strings(); // 's' es un StringCollection
Con.WriteLine("hola");

 
Habréis observado que en este caso no se utilizan los dos puntos (::) para separar el alias del resto, puesto que éste no representa a un namespace, sino a un tipo.

3. Adquisición y liberación de recursos

En este caso, using sirve para especificar bloques de código en los que se van a utilizar recursos que deben ser liberados obligatoriamente al finalizar, como podrían ser conexiones a base de datos, manejadores de ficheros, o recursos del propio sistema operativo. De hecho, salvo en contadas ocasiones, utilizar using es la forma más recomendable de tratar estos asuntos.

En un bloque using se definen una serie de recursos, siempre implementando la interfaz IDisposable, y se delimita un bloque de código en el que éstos serán válidos y visibles. Al salir la ejecución de dicho bloque, estos recursos serán automáticamente liberados llamando a sus respectivos métodos Dispose(). Y esto se hará siempre, independientemente de si la salida del bloque ha sido de forma natural, mediante una excepción o un salto. En otras palabras, el compilador nos asegura que siempre invocará el método Dispose() de todos los recursos comprometidos en la operación.

Un ejemplo muy habitual lo vemos con las conexiones de bases de datos, recurso valioso donde los haya. La forma correcta de tratarlas sería:

  using (SqlConnection conn = new SqlConnection(connectionString)) 
{
hacerAlgoConLosDatos(conn);
}
// Al llegar aquí, la conexión está liberada. Seguro.
// Además, la variable conn no es visible.

 
Respecto a la liberación automática de recursos, no hay nada mágico en ello. Internamente, el compilador de C# está transformando el código anterior en:

  SqlConnection conn = new SqlConnection(connectionString);
try
{
hacerAlgoConLosDatos(conn);
}
finally
{
if (conn != null)
((IDisposable)conn).Dispose();
}

 
Además de asegurar que los recursos son liberados cuando ya no van a ser necesarios, tiene también un efecto positivo al hacer que centremos su uso en un bloque compacto, fuera del cual no se podrá acceder a los mismos; por ejemplo, en el caso anterior, dado que la variable conn no es visible desde fuera del bloque using, evitaremos accesos a ella cuando haya sido liberada, que provocaría errores en tiempo de ejecución.

Y por cierto, una posibilidad interesante y no demasiado conocida es que se pueden especificar varios recursos en el mismo bloque using, de forma que todos ellos se liberen al salir, sin necesidad de tener que anidarlos, siempre que sean del mismo tipo, por ejemplo:


// Anidando usings
using (SqlConnection conn1 = new SqlConnection(connstr1))
{
using (SqlConnection conn2 = new SqlConnection(connstr2))
{
// hacer algo con las dos bases de datos
}
}

// Forma más compacta
using (SqlConnection conn1 = new SqlConnection(connstr1),
conn2 = new SqlConnection(connstr2))
{
// hacer algo con las dos bases de datos
}

 
Publicado en: www.variablenotfound.com.