Migración facil de proyectos ASP.NET de VS 2003 a Visual Studio 2005

Visual Studio 2005 y ASP.NET 2.0 proponen una manera muy diferente de estructurar  los proyectos ASP.NET. En principio este cambio es en pro de una mayor sencillez y flexibilidad, proporcionando por ejemplo una manera muy simple de compilar código al vuelo por el simple hecho de encontrarse en la carpeta App_Code.


Pero como todo cambio, hay gente a la que le gusta y gente a la que no. O aún más hay gente que tiene enormes proyectos con la estructura de VS 2003 y que ya han sufrido el intento de migrar a VS 2005. Realmente el resultado es un autentico desaguisado que para proyectos grandes exige un trabajo posterior grande y propenso a errores.


Gracias a dios, aunque tarde, alguien en Microsoft se ha dado cuenta del problema y ha trabajado para ofrecer una solución: VS2005 Web Application Project


VS2005 Web Application Project añade un nuevo tipo de proyecto Web que se comporta como los anteriores, facilitandonos la vida a la hora de migrar nuestros antiguos proyectos a VS2005. No dudes en descargarlo. Es gratis.


En este articulo podeís encontrar más información sobre como realizar la migración.

SaaS: Software as a Service

¿Cuantas veces nos han contado que una tecnologia, aplicación, lenguaje etc… iva a cambiar la industria del software radicalmente? Bueno pues otro paradigma (no es una arquitectura, ni una técnologia, sino una aproximación diferente a el desarrollo de soluciones) que promete esto es SaaS (Software as a Service). Y aunque estoy seguro de que SaaS no va a cambiar la industria del software de manera radical, puesto que nunca han ocurrido cambios radicales en esta industria, si creo que va a suponer un cambio. Y siempre es interesante estar preparado para los cambios, sobretodo si te dedicas al desarrollo de software en cualquiera de sus facetas.


Por eso aquí teneís una serie de recursos valiosos sobre SaaS a los que no estaría de más que hechaseís un ojo si creeís que vuestro software debe seguir ese camino:


Architecture Strategies for Catching the Long Tail
Microsoft Solution for Windows-based hosting for Applications Preview Release
Software as a Service Seminar
Perspectivas del SaaS (interesante discusión en Barrapunto)
So Software as a Service is the next big thing – again?

Antipatrones en el trabajo con excepciones (II)

Un error en el que los programadores solemos caer es escribir manejadores de excepciones ‘genéricos’, por ejemplo, capturando todas las excepciones a través de un manejador de la clase base (System.Exception en .Net).


try
{
   f();
}
catch (Exception ex)
{
}


El problema con este enfoque es que se produce un enmascaramiento de todas las excepciones. Manejamos igual aquellas excepciones que sabemos que se pueden producir que aquella inesperadas. El problema reside que las excepciones inesperadas, que no sabemos en que condiciones se producen, son a menudo síntomas de mal funcionamiento de nuestra aplicación y por tanto son errores que debemos solucionar y en ningún caso enmascarar. Otro problema asociado es que perdemos información sobre donde se están produciendo los fallos, puesto que cualquier excepción producida en cualquiera de las funciones que se encuentre en la pila será recogida por ese manejador genérico, aunque la función se encuentre a muchos niveles del manejador. Existe un gran hueco entre donde se produce el fallo y se registra.


 


La solución a este problema es clara. Debemos capturar tipos de excepción concretos que se encuentren entre los que es previsible que se produzcan y evitar enmascarar el resto. Así, en el caso de que la función f(), acceda a disco, y puede que el archivo a acceder no exista lo lógico es captura solo la excepción que se produce cuando el archivo no existe.


 


try


{


f();


}


catch (System.IO.FileNotFoundException ex)


{


      //Operaciones a realizar cuando el archivo no existe


}


 


Aún así existen casos en los que capturar excepciones de manera genérica:


 


Cuando realizamos llamadas a recursos remotos, porque puede ser que la comunicación falle de maneras muy diversas y difícilmente predecible, o podemos recibir datos corruptos, o le recurso remoto no estar accesible, etc… existen tantos puntos de fallo posibles que el enfoque más simple es capturar todas las excepciones y tratar de extraer información concreta de la excepción una vez capturada.


 


Cuando llamamos a plugins de terceros que se pueden cargar  en nuestra aplicación, es una medida natural de protección y seguridad contra plugins maliciosos o mal programados capturar todas las excepciones provenientes de un plugin y si se produce alguna descargar el plugin.


 


try


{


      plugin.Load();


      plugin.DoSomeThing();


}


catch (Exception ex)


{


      plugin.Unload();


}


 


Otro caso en el que capturar todas las excepciones puede ser aceptable es para tratar de revertir el estado de la aplicación, por ejemplo si tenemos un usuarios con altos privilegios impersonado y se produce una excepción, es una buena practica revertir esa impersonación. Recordemos que una vez que se produce una excepción que no esperamos no debemos confiar en el comportamiento de  nuestra aplicación, y esto es especialmente cierto en lo que a seguridad y privilegios se refiere. Muchos errores relacionados con la elevación de privilegios tienen su base en caminos inesperados en el flujo de ejecución de la aplicación.


 


En la próxima entrega: Errores en el logeo de excepciones

¿Como creo un ejecutable sin dependencias?

A menudo me realizan esta pregunta. Actualmente la gran mayoria de los lenguajes de programación corren sobre algún tipo de maquina virtual (C#, VB.Net), o dependen de algún tipo de runtime (VB 6.0, VC++), o directamente son interpretados (Perl, Python). Aún así surge la necesidad a menudo de escribir programa que se ejecuten directamente sin la necesidad de tener más que el ejecutable que deseamos ejecutar, debido a que queremos comodidad, facilidad en el despliegue, o a que necesitamos comprobar precondiciones relacionadas con la existencia o no de interpretes o runtimes que necesitamos para desplegar nuestra aplicación.


En plaforma Windows y utilizando herramientas de desarrollo de Microsoft la única opción con que contamos es utilizar Visual C++ como herramienta de desarrollo, pero ni siquiera esto garantiza el exito. Debemos tener una serie de cuestiones en cuenta.


La primera es que debemos seleccionar el tipo de proyecto adecuado, debe ser un proyecto de tipo MFC, si necesitamos una interfaz gráfica, tipo Win32, si la interfaz gráfica es muy simple o inexsitente o consola si queremos una interfaz de tipo linea de comandos.


Es segundo paso es configurar adecuadamente el proyecto para que el ejecutable que se genere no dependa de librerias externas. Para ello, en Visual Studio 2003 y 2005 debemos dar los siguientes pasos:


En la propiedades del proyecto, en Configuration Properties->General->Use of
MFC selecciona Use MFC in a Static Library, para todas la configuraciones,
tanto Debug como Release. Esto elimina las dependencias de la libreria
MFCxx.dll (MFCDLL Shared Library)


Luego en Configuration Properties->C/C++->Code Generation->Runtime Library
selecciona Multi-threaded Debug (/MTd), para la configuración Debug y
Multi-threaded (/MT), para la configuración Release. Esto elimina la
dependencia de MSVCRxx.dll (Microsoft C Runtime Library) y de MSVCPxx.dll
(Microsoft C++ Runtime Library)


Evidentemente nos vendra a la cabeza el hacer esto en todos nuestros proyectos de Visual C++, pero esto tiene dos desventajas que hay que valorar:


La primera es que el tamaño de nuestro ejecutable crece.
La segunda es que nuestro programa no se beneficia de los parches que Microsoft libere para sus runtime de MFC, C o C++.


Aun existe, siempre utilizando Visual C++, otra opción: La libreria WTL (Windows Template Library), que es un libreria de plantillas de C++ construida directamente sobre el API de Windows. WTL genera unos ejecutables diminutos, extremadamente eficientes y además es una libreria GPL.

Antipatrones en el trabajo con excepciones (I)

Uno de los puntos en los que más fallan los desarrolladores noveles es a la hora de trabajar con excepciones. Existen numerosas formas de trabajar mal con excepciones.


También es curioso como muchos arquitectos a la hora de plantear un marco general de


manejo de excepciones para la aplicación caen, una y otra vez, en los mismo errores.


Cómo, desde un punto de vista general, la aplicación responde a las excepciones, en


que ocasiones estas se propagan hasta el usuario en forma de mensajes de error, cómo se responde a las excepciones totalmente inesperadas, o como se logea el comportamiento de la aplicación en lo que a manejo de excepciones se refiere, es algo, que a menudo no esta bien resuelto, a pesar de ser un punto de suma importancia desde el punto de vista arquitectónico. Debemos prestar atención, como arquitectos y como desarrolladores, a este tema, puesto que tiene una incidencia enorme en la mantenibilidad y manejabilidad de la aplicación una vez desplegada. Sin una buena política de manejo de excepciones, se hará sumamente difícil encontrar los errores que presente nuestra aplicación. Por eso voy a dedicar una serie de entradas en este blog al tema del uso correcto de excepciones.


 


Overthrowing: Número excesivo de excepciones.


 


Es habitual y recomendable lanzar una excepción cuando una función falla. También es


habitual que en la mayoría de las ocasiones la funciones hagan su labor correctamente de manera que, el que respondan con una excepción, es algo que no ocurre muy  a menudo. Pero en ocasiones ocurre que, nuestro código provoca que se lancen numerosas excepciones. Las excepciones son costosas en tiempo de ejecución, debido más que nada a que cada vez que se lanza una excepción se debe recorrer la pila de llamadas en dos ocasiones.


 


Un ejemplo de esta situación, bastante habitual, ocurre cuando necesitamos realizar una conversión desde una cadena, leída desde un archivo, a un valor numérico. Supongamos un archivo que contiene gran cantidad de cadenas, unas representan un numero y otras no. Supongamos que deseamos tratar las cadenas numéricas en variables enteras y descartar aquellas líneas que no sean enteras. Si la cadena, leída del archivo, esta contenida en la variable de tipo string s, parece lógico tener código como el siguiente:


 


try


{


i = int.Parse(s);


}


catch (FormatException)


{


//La conversión fallo, descartamos la cadena leída


//porque no es un entero


}


 


En principio no hay problema con este código, pero supongamos que un gran porcentaje de las cadenas que leemos del archivo no son numéricas. Esto provocará que se produzcan un gran numero de excepciones lo que penalizará en gran medida el rendimiento de nuestra aplicación. Unai ya trato este tema desde el punto de vista del rendimiento.


 


¿Qué solución tenemos a este problema? La verdad en que en el framework 1.1 no hay una buena solución. En la versión 2.0 del framework, se han añadido métodos que permiten comprobar esa situación sin recibir una excepción. Estos métodos siguen el patrón de en lugar de lanzar una excepción devolver un valor booleano que nos informa del resultado de la excepción sin pagar el precio en tiempo de ejecución de la excepción.


 


if (int.TryParse(i, s))


{


//s contiene un valor entero


}


else


{


//s no es un valor entero


}


 


La moraleja es clara, cuando queramos utilizar un método que lanza una excepción y preveemos que esta se produzca en muchas ocasiones, debemos buscar una manera alternativa de hacer las cosas que no implique que se produzcan numerosas excepciones. Y cuando implementemos un método que lanza excepciones y que preveeamos que puede ser llamado en escenarios que produzcan numerosas excepciones, debemos proveer un método alternativo que permita realizar la misma operación sin recibir excepciones. Implementar este segundo mecanismo unicamente no es una buena solución, las situaciones excepcionales deben comunicarse usando excepciones, no valores de retorno, esta es la norma general y solo debe implementarse un mecanismo alternativo si preveemos escenarios de uso de nuestro método en los que se vayan a producir un número excesivo de excepciones.


 


En la siguiente entrega: Overcatching: Recoger más tipos de excepción que los que nos incumben.

Colección de Code Snippets adicionales para VS 2005

Supongo que todos conocereís ya los code snippets de Visual Studio 2005. Pues bien además de los que vienen por defecto podemos descargar y utilizar un mónton de ellos más.


Les hay para VB, C# y Visual Stuido Tools for Office (VSTO), y nos proporcionan código para trabajar con bases de datos, comprobar la conectividad, trabajar con el sistema de archivos, con XML, y un largo ecétera…


 

Patrones + DSL

He visto un interesante proyecto, que implementa, utilizando DSL, algunos de los patrones de la "banda de los cuatro". Puede ser de interés tanto si estas interesado en los patrones como si estas interesado en DSL. Esta disponible el código fuente y una presentación.

Sin duda toda buena software factory deberia estar basada en patrones reconocidos. Y no hay patrones más importantes (a nivel de diseño) que los de la "banda de los cuatro".

Interesante ejemplo de uso del API de Team System

He encontrado un ejemplo muy interesante sobre como utilizar el API de Team System para construir interesantes aplicaciones. En concreto se trata de exponer un RSS con la información sobre que los cambios en las fuentes.


Sample: Version Control RSS Feed
http://blogs.msdn.com/jefflu/archive/2005/07/27/443900.aspx


En el blog además se explica en más detalle como se ha construido esta aplicación.

¿Como obtengo el path de capetas del sistema (por ejemplo System, Archivos de Programa etc…)?

Si estas programando una aplicación nativa (en C++) debes usar la función SHGetFolderPath, si quieres añadir un subdirectorio al valor devuelto (p.e.: C:Archivos de programaTu applicacion) lo puedes hacer directamente con la función SHGetFolderPathAndSubDir. Estas funciones tienen como requisito Windows 95 con Internet Explorer 5.0, Windows 98 con Internet Explorer 5.0, Windows 98 Second Edition (SE), Windows NT 4.0 con Internet Explorer 5.0, Windows NT 4.0 con Service Pack 4 (SP4).


Tambien puedes utilizar las siguientes funciones:


GetSystemDirectory(), para obtener el directorio de sistema.
GetWindowsDirectory(), para obtener el directorio de windows.
GetTempPath(), para obtener el directorio temporal.


Si estas programado una aplicación manejada, usando C#, VB.Net, C++/CLI u otro lenguaje .net hechale un vistazo al método GetFolderPath de la clase Environment y a la enumeración SpecialFolder.


 

¿Es Visual C++ ‘visual’? ¿Es una herramienta RAD?

Aunque Visual C++ si que es ‘visual’ en el sentido que permite realizar gran parte de las tareas mediante asistentes, no es un entorno RAD al estilo de Visual Basic o FoxPro.

 

Si bien la manera de trabajar es diferente, tambien sigue el paradigma de arrastrar y soltar controles, lo que no es visual es el establecer todas las opciones de los controles y estos no tiene tantas propiedades y métodos como en las hermientas RAD. Para darles un comportamiento más rico tienes que usar código.

 

La potencia de Visual C++ esta principalmente en que tu tienes el control y eso tiene ventajas he inconvenientes. Tambien te comento que en mi opinión para apliacaciones basadas en formularios las hermientas RAD son más productivas, pero VC++ es superior si se trata de construir programas que exijan mucho procesamiento, graficos muy avanzados, aplicaciones basadas en documentos o con una interfaz no basada en formularios y en general componentes para ser usados desde otros lenguajes, y por supesto toda la programación a ‘bajo nivel’ (drivers, extensiones de shell,…).

 

Con la llegada de .net y C++/CLI todo esto ha cambiado un poco, puesto que ahora es posible utilizar Visual C++ y Windows Forms para crear aplicaciones con interfaz gráfica simplemente arrastrando y soltando controles. Este tipo de aplicaciones son aplicaciones manejadas, no nativas, que requieres del runtime de .Net para funcionar.