JavaScript Intellisense con Visual Studio 2010
Parece que la próxima versión de Visual Studio va a traer importantes mejoras en el Intellisense para JavaScript.
En la imagen anterior se aprecia como es capaz de reconocer la introducción de 5 variables de forma dinámica a pesar de los alerts y las excepciones lanzadas.
20 desastres famosos relacionados con el software
José M. Aguilar ha publicado una serie de artículos donde se describen 20 desastres relacionados con el software:
NDepend
La gestión de la complejidad es uno de los principales retos a los que nos enfrentamos a la hora de desarrollar software. Recientemente Patrick Smacchia me invitó a probar NDepend, una potente herramienta que nos proporciona, de forma muy visual e interactiva, una gran cantidad de información sobre ensamblados .NET.
Su utilización simplifica la gestión de una base de código compleja al poder realizar medidas objetivas sobre el código y poder comparar su evolución en el tiempo. También facilita la comunicación al poder ver de forma muy visual la estructura y dependencias del código. Además, combinada con reflector (herramienta con la que se puede integrar), nos puede facilitar enormemente la tarea de entender o evaluar ensamblados no escritos por nosotros.
Los diferentes gráficos y resultados mostrados a continuación son el resultado del análisis mediante NDepend a una sencilla aplicación que escribí hace tiempo. Se puede observar el informe HTML que fue generado automáticamente por la herramienta aquí.
NDepend facilita ver la estructura y las interrelaciones entre los diferentes componentes de un proyecto de software así como responder a preguntas sobre la calidad u otros aspectos del software en base a los numerosos indicadores o métricas incluidos. Además, podemos realizar nuestras propias preguntas sobre el código utilizando CQL (Code Query Language), un lenguaje de consultas similar a SQL.
Al cargar un conjunto de ensamblados en NDepend se realiza un completo análisis de los mismos. A partir de ese momento tendremos a nuestra disposición una gran cantidad de información que podemos visualizar bajo una agradable interface. Al termino del análisis también se generará un informe en HTML con la información más relevante.
Métricas
Tenemos diferentes métricas a nuestra disposición, las cuales pueden operar a diferentes niveles: espacios de nombres, ensamblados, tipos, métodos y campos. Las métricas nos permiten detectar potenciales problemas en la arquitectura del software y nos pueden indicar la necesidad de reestructurar el código (refactoring).
En la siguiente imagen se observa un gráfico generado por la herramienta que representa el número de líneas de código de cada uno de los métodos de una aplicación. Cada recuadro sombreado representa un método, y su tamaño es proporcional al número de líneas de las que está compuesto. Además, los métodos están agrupados dentro de los tipos que les contienen, por lo que podemos ver su peso especifico dentro de la aplicación.

La cantidad de información que proporciona el gráfico anterior es muy elevada, siendo además interactivo por lo que nos permite navegar a las estructuras representadas dentro del proyecto.
Entre las diferentes métricas a nuestra disposición destacamos las siguientes (tenemos un listado completo en el sitio web de la herramienta):
- Longitud: en instrucciones de lenguaje intermedio (IL), o en líneas de código. Una gran longitud en nuestros tipos o clases podría indicar un exceso de responsabilidad para estas y por lo tanto aconsejar la necesidad de refactorización.
- Aferencia: la aferencia es el número de vías de entrada o referencias hacia la entidad bajo observación. En otras palabras, si estamos trabajando a nivel de métodos, la aferencia de un método nos indicará el número de métodos que dependen de este método bajo observación. Este indicador nos muestra la ‘importancia’ que tiene una determinada entidad. Si una entidad es muy ‘importante’ será más difícil modificarla, porque el número de entidades que depende de ella será elevado y al hacerlo, alguno de ellos podría dejar de funcionar.
- Eferencia: indica el número entidades de las que depende esta entidad. Por ejemplo, a nivel de tipo o clase, nos indicaría el número de clases de las que depende la clase bajo observación. En general, nos interesa mantener este número bajo. Idealmente, un tipo solo debería depender de los tipos inmediatamente inferiores a el en la jerarquía.
CQL
Las consultas predeterminadas que NDepend realiza sobre nuestro proyecto durante su análisis principal se agrupan en las categorías que muestra la siguiente figura.
Esta consultas nos proporcionan una evaluación de nuestro código en base a diferentes parámetros de calidad y son totalmente personalizables.

Dentro de cada uno de los grupos podemos ver cada una de las consultas y las partes del software que no han superado la prueba. Al seleccionar una de las consultas, además, dichas partes se resaltaran tanto en el gráfico como en el visor de resultados.
Dependencias
Un alto nivel de dependencias generalmente significará mayores problemas a la hora de realizar cambios o ampliar la funcionalidad de una aplicación. A través de la matriz de dependencias, podemos observar de forma gráfica e interactiva las dependencias entre los componentes del proyecto, lo cual nos facilita mantener dichas dependencias dentro de un nivel razonable. Por ejemplo, el que la segunda línea de la figura siguiente esté completa indica que todos los tipos de la aplicación dependen de tipos definidos en el ensamblado ‘mscorlib’, lo cual es de esperar ya que es el ensamblado principal del FrameWork.
La herramienta nos proporciona también diagramas en los que el grosor de las líneas entre nodos indica el grado de dependencia con respecto a un ensamblado concreto.

Comparaciones y otras características
Otra característica de NDepend es la comparación entre las diferentes versiones de un conjunto de ensamblados con lo que podemos ver su evolución y observar, por ejemplo, la efectividad de una etapa de refactorización del código.
Podemos ver un ejemplo de este escenario, así como de otros escenarios interesantes en el sitio web de NDepend bajo ‘Online Demos’.
SmallBasic enseña a los niños a programar
SmallBasic, un lenguaje puramente imperativo con no más de 15 palabras clave o ‘keywords’ pretende hacer de la iniciación a la programación una experiencia divertida, a la vez que gratificante.
El entorno, elegante y sencillo, proporciona capacidades avanzadas como IntelliSense y ayuda dependiente del contexto.
El programa anterior, de tan solo cuatro líneas de código, obtiene una imagen de Flickr con las etiquetas de ‘Cantabria’ y ‘Santander’, la representa en pantalla y la establece como fondo de escritorio. A continuación se muestran los resultados de su ejecución.
Un completo manual muy fácil de leer con multitud de ilustraciones y ejemplos permite iniciarse rápidamente al lenguaje y el entorno, eso sí, de momento solo se encuentra disponible en inglés.
Se proporciona un poderoso, a la vez que accesible conjunto de librerías para tareas comunes (y no tan comunes) como dibujado en pantalla, escritura de texto, funciones matemáticas, acceso a internet, control de ratón, sonido e incluso para acceder a un diccionario online o para controlar una ‘tortuga’ al estilo de logo.
Desde luego el entorno no está limitado a principiantes sino que es una herramienta valiosa para el desarrollo de pequeños programas proporcionando la sensación de las antiguas máquinas de 8 bits en las que se arrancaba directamente en un entorno tipo Basic donde directamente podíamos ejecutar código.
SmallBasic se puede descargar de aquí gratuitamente. Tanto el entorno como el lenguaje está basado en .NET siendo fácilmente extensible.
Sysinternals Live
El equipo de Sysinternals ha hecho accesible su fantástica colección de utilidades a través de una unidad de red, a la cual podemos acceder escribiendo la siguiente direccion en nuestro explorador de archivos: \\live.sysinternals.com\tools\
Tambien podemos ver el directorio completo de utilidades desde nuestro navegador web en http://live.sysinternals.com.
Otras 101 citas del mundo de la informática
Hace unas semanas escribí sobre la traducción realizada por José M. Aguilar del artículo '101 citas célebres del mundo de la informática' de Timm Martin. Pues bien, como replica a dicho artículo J.M Aguilar ha realizado otra recopilación de curiosas frases sobre el mundo del desarrollo de software y de la informática en general. Se puede encontrar el artículo en su blog.
Introducción al contenedor Unity
Unity es un contenedor de inyección de dependencias que facilita el desarrollo de aplicaciones proporcionando un sistema para gestionar tanto la construcción de objetos como las dependencias entre los diferentes componentes de una aplicación.
Supongamos que hemos definido un interface a través del cual gestionaremos todo el sistema de registro de eventos de nuestra aplicación.
public interface ILoggingService
{
void Log(string message);
}
Y a su vez una clase que implementa dicho interface y que en este caso simplemente enviara el mensaje a la consola del sistema.
public class ConsoleLoggingService: ILoggingService
{
public void Log(string message)
{
Console.WriteLine("Console: " + message);
}
}
El funcionamiento básico del contenedor es sencillo, en primer lugar registraremos en el contenedor los tipos de objetos que deseamos que gestione. Al hacerlo, además, indicaremos al contenedor cual debe ser el ciclo de vida del objetos de ese tipo. En el caso que nos ocupa registraremos el interface ILoggingService en el contenedor mapeando dicho interface al tipo ConsoleLoggingService de tal forma que cuando solicitemos al contenedor un objeto implementando el interface ILoggingService nos devuelva un objeto del tipo ConsoleLoggingService. Como además deseamos que en la aplicación solo exista una única instancia del sistema de eventos (Singleton), indicaremos al contenedor que se encargue de controlar la vida del objeto, de esta forma la primera vez que solicitemos el interface se creará el objeto pero las veces sucesivas se nos devolvera una referencia al mismo objeto. El siguiente fragmento de código muestra el proceso de registro utilizando uno de los métodos que nos brinda el contenedor.
IUnityContainer container = new UnityContainer();
container.RegisterType<ILoggingService,
ConsoleLoggingService>(new ContainerControlledLifetimeManager());
Veamos como funciona la inyección de dependencias. El contenedor nos proporciona varias formas de realizar la inyección de dependencias: a través del constructor, a través de una propiedad ó a través de un método. En el caso general, las inyección requiere que marquemos el constructor, la propiedad o el método con un atributo que indicará al contenedor que debe realizar la inyección de un objeto. El siguiente fragmento de código muestra la utilización del atributo InjectionConstructor para indicar al contenedor que debe inyectar un objeto con el interface ILoggingService a la hora de construir un objeto del tipo MainApplicationModule.
public class MainApplicationModule
{
ILoggingService mLoggingService;
[InjectionConstructor]
public MainApplicationModule(ILoggingService loggingService)
{
mLoggingService = loggingService;
mLoggingService.Log("Inicializado el módulo principal de la aplicación");
}
}
Nótese que en este caso, al existir solo un constructor, el contenedor inyectará las dependencias en el constructor de forma autómatica aunque no hayamos marcado el constructor, sin embargo, dicho atributo es útil para indicar que constructor utilizar en el caso de que existan varios. Si tenemos una clase con varios constructores y ninguno de ellos está marcado con el atributo de inyección, el contenedor utilizará aquel que tenga más parámetros, lanzando una excepción en el caso de que exista más de un constructor que cumpla la propiedad de tener el máximo número de parámetros.
1 static void Main(string[] args)
2 {
3 using (IUnityContainer container = new UnityContainer())
4 {
5 container.RegisterType<ILoggingService,
6 ConsoleLoggingService>(new ContainerControlledLifetimeManager());
7 MainApplicationModule mainModule = container.Resolve<MainApplicationModule>();
8 Console.ReadLine();
9 }
10 }
En la linea 7 del anterior fragmento de código, solicitamos al contenedor que nos devuelva un objeto del tipo MainApplicationModule. Obsérvese que en este caso no ha sido necesario registrar el objeto con el contenedor previamente. La utilidad de crear un objeto a través del contenedor de un tipo que no ha sido previamente registrado es que el contenedor evaluará e inyectará las dependencias de dicho objeto al generarle.
Después de la ejecución de la linea 7 aparecerá en la consola del sistema la siguiente línea indicando que se ha realizado el proceso de inyección de la dependencia ILoggingService correctamente:
Console: Inicializado el módulo principal de la aplicación
Las ventajas de la utilizacion del patron de diseño de inyección de dependencias se hacen evidentes a médida que el número de componentes de la aplicación aumenta, permitiendonos mantener un acoplamiento débil entre dichos componentes y facilitando el mantenimiento posterior de la aplicación al unificar el sistema de construcción y cableado de objetos.
Puede que surja la pregunta de que tipo de objetos debemos instanciar a través del contenedor. En mi experiencia, los componentes que forman parte de la arquitectura o flujo principal de la aplicación, esto es, servicios, vistas, presentadores, módelos, etc, son buenos candidatos para ser incluidos en el contenedor.
Finalizaremos este artículo enumerando dos ventajas instantaneas de utilizar un contenedor para estructurar nuestra aplicación:
- Si en lugar de mostrar los eventos del sistema por la consola decidimos registrarles en una base de datos, podríamos definir un nuevo tipo DatabaseLoggingService implementando el interface ILoggingService y registrar dicho tipo en lugar de ConsoleLoggingService. Con esa sencilla modificación la aplicación pasaría a registrar los eventos en una base de datos.
- El contenedor introduce el concepto de 'cadena de montaje' y nos permite extender las acciones a realizar a la hora de crear un objeto. Un uso típico es el 'EventBroker' o sistema de gestión de eventos que permite marcar eventos de los tipos con el atributo de publicación y métodos con el atributo de suscripción, encargandose el contenedor a la hora de construir los objetos de cablear los publicadores con los suscriptores facilitando la implementación del patron de diseño observador.
