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 ;)

17 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!
Mostrando entradas con la etiqueta buenas prácticas. Mostrar todas las entradas
Mostrando entradas con la etiqueta buenas prácticas. Mostrar todas las entradas
lunes, 9 de noviembre de 2009

imageSimone Chiaretta, desarrollador, MVP, bloguero y autor de un libro sobre ASP.NET MVC Framework, entre otros méritos, recoge en su recomendable bitácora Code Climber unas cuantas buenas prácticas a considerar cuando trabajamos en proyectos ASP.NET MVC, que cito y comento a continuación:

  1. Borra el AccountController. Siendo fieles al principio YAGNI, prácticamente lo primero que deberíamos hacer al crear un proyecto ASP.NET MVC es eliminar todo lo relativo al sistema de cuentas de usuario incluido por defecto en el mismo, que muy difícilmente nos será útil tal cual en proyectos reales.

  2. Aísla los controladores del mundo exterior, no dejes que dependan de elementos externos como HttpContext,  datos del reloj (hora/fecha actual), ni accedas directamente a bases de datos o elementos de configuración. Harán tu aplicación muy poco flexible y difícil de testear.

  3. Utiliza un contenedor IoC, te ayudará a gestionar las dependencias de los controladores, facilitando la sustitución de estos elementos de forma muy sencilla, sobre todo, vistas a la realización de pruebas.

  4. No utilices cadenas mágicas, dificultan la detección de errores. No es buena idea usar expresiones del tipo ViewData["variable"], las vistas tipadas son el mecanismo ideal para pasar información desde el controlador. También es peligroso el uso de los helpers que utilizan cadenas para referirse a nombres de controladores y acciones, y para ello existen alternativas basadas en expresiones lambda o plantillas T4 bastante potentes.

  5. Crea tus propias convenciones tomando como base las propuestas por el framework MVC. Por ejemplo, crea controladores y vistas base de las que heredar, e implementa en ellos aspectos comunes.

  6. Presta atención a los Verbos, a los verbos HTTP, claro ;-). Envía información desde formularios con el método POST y genera las vistas que muestran datos desde peticiones GET. Utiliza el patrón Post-Redirect-Get.

  7. DomainModel != ViewModel, el primero representa los datos y lógica del dominio, mientras que el segundo se diseña exclusivamente para satisfacer las necesidades de información de las vistas y normalmente serán estructuras planas, y principalmente strings, que es el tipo de datos que normalmente necesitan los controles de entrada y salida de datos.

  8. Usa ActionFilters para manejar los datos compartidos entre distintas acciones y controladores, dejando que éstos se centren en la tarea que deben realizar. Puedes utilizar filtros para cargar información común (por ejemplo, para componentes de una página maestra) y utilizar vistas parciales para mostrarla.

  9. No utilices el code-behind. Nunca. En mi opinión, el code-behind no es necesario (al menos no le he encontrado aún ninguna utilidad en MVC), y puede crear confusión si compartes tu código con otros desarrolladores que no esperarán encontrar nada ahí.

  10. Escribe HTML siempre que puedas. No utilices helpers que lo único que van a hacer es generar el código HTML por ti. Es decir, mejor usar <input type="submit" value="grabar" /> que <%=Html.Submit("grabar") %>.

  11. Si hay un if, escribe un helper. Las vistas deben ser fáciles de leer, y muchos bloques de códigos mezclados con marcado no facilita la tarea. Dado que en las vistas la lógica ha de ser necesariamente muy simple, probablemente puedas crear helpers que simplifiquen la composición del marcado en casos en los que hay condiciones if o bucles for .

  12. Elige el motor de vistas cuidadosamente, WebFormViewEngine no es el único ni, para Simone, el mejor de los existentes. De hecho, recomienda el uso de Spark, un motor de vistas libre en el que es el propio HTML el que controla el flujo de composición del interfaz de forma muy sencilla y potente:

  13. <viewdata products="IEnumerable[[Product]]"/>
    <ul if="products.Any()">
      <li each="var p in products">${p.Name}</li>
    </ul>
    <else>
      <p>No products available</p>
    </else>
     
    En mi caso, todavía no he encontrado motivos suficientes como para dar el salto a un motor de vistas distinto de WebForms. Sinceramente, no me parece tan aberrante ver código y marcado dentro del mismo archivo, siempre teniendo en cuenta que la lógica que debe aparecer en estos puntos debe ser siempre relativa a la presentación y, por tanto, simplísima.

Opiniones aparte, la verdad es que es un interesante grupo de consejos a tener en cuenta.

Fuente: 12 ASP.NET MVC Best Practices

Publicado en: Variable not found.

lunes, 2 de noviembre de 2009

Hoy vamos a dedicar un rato a comentar una técnica que es considerada una buena práctica en el desarrollo de aplicaciones web: el patrón PRG o Post-Redirect-Get. Seguramente alguna vez lo haya citado por aquí, pero nunca lo había explicado en profundidad.

Por último, antes de entrar en materia, es conveniente indicar que lo que vamos a ver es válido para ASP.NET Webforms, ASP.NET MVC y, en general, para cualquier tecnología de construcción de sitios web que incluya componentes en servidor, puesto que se trata de una forma de hacer las cosas, no de la implementación de una solución. Ya en el último epígrafe veremos implementaciones concretas para Webforms y el framework MVC.

El problema

Es bastante habitual que al desarrollar aplicaciones para la web creemos un formulario de introducción de datos, y lo normal es que estos envíen los datos al servidor utilizando el verbo HTTP Post. Hasta aquí, bien.

Cuando desde el servidor se recibe una petición de este tipo normalmente se ejecuta un código, por ejemplo para almacenar la información en la base de datos y, de forma bastante frecuente, aprovechamos para enviar al cliente feedback de que su operación ha sido realizada con éxito. Y aquí es donde aparece el problema.

image Si el usuario, por esas ocurrencias que suele tener ;-), decide pulsar F5 o actualizar la página en el navegador, se van a producir dos efectos desagradables:

  • primero, se le mostrará al usuario un cuadro de diálogo informándolo de algo que difícilmente va a entender y que, en cualquier caso, le asustará bastante. El navegador le informa de que está realizando un reenvío completo de los datos del formulario.
  • segundo, una vez superado el escollo anterior, se volvería a ejecutar en servidor toda la lógica asociada a la recepción de datos del formulario con consecuencias, a veces terribles, como el almacenamiento de registros duplicados en la base de datos.

¿Cómo podemos evitar esto?

La solución: Post-Redirect-Get

El patrón PRG viene a indicarnos una forma de diseñar nuestras aplicaciones pensando en evitar los problemas descritos anteriormente, y, como veremos, es bastante simple. El procedimiento general a seguir sería:

  1. Recibimos la petición Post con los datos que ha introducido el usuario en un formulario.
  2. Ejecutamos la lógica asociada a la recepción de dicho formulario, por ejemplo, grabar en la base de datos.
  3. Enviamos al cliente una respuesta con código HTTP 30x (Redirect), indicando al agente de usuario que debe solicitar otra página, en la mostraremos un mensaje informando de que el proceso se ha realizado con éxito.
  4. El navegador obtiene dicha página mediante una petición de tipo Get.

En este punto, si el usuario decide (o el diablo que lleva dentro le ordena ;-)) refrescar la página, lo único que conseguirá será que su navegador vuelva a solicitar la página en la que le estamos informando de que el proceso ha sido satisfactorio. No se le muestra ningún cuadro de diálogo amenazante, ni se ejecuta la lógica de nuevo, ni hay ningún tipo de daños colaterales.

El siguiente diagrama, basado en el de la imprescindible Wikipedia, muestra gráficamente este proceso:

Secuencia en el patrón PRG

¿Un poco de código? Sí, por favor

ASP.NET WebForms

La abstracción sobre los protocolos montada por la tecnología Webforms hace más difícil reconocer los conceptos que estamos tratando, pero aún así es bastante sencillo aplicar el patrón.

En los formularios web, los postbacks se realizan a través de métodos Http POST, por lo que la implementación de la lógica y la redirección podremos realizarlas en la implementación del evento de servidor correspondiente, por ejemplo, el de pulsación de un botón:

protected void btnAceptar_Click(object sender, EventArgs e)
{
    if (Page.IsValid)
    {
        // Lógica 
        Cliente cliente = new Cliente(txtNombre.Text, txtApellidos.Text);
        GestorDeClientes.Salvar(cliente);
    
        // Redirección
        Response.Redirect("clientes.aspx", true);
    }
}

La página “clientes.aspx” podría ser ser el listado de clientes registrados en el sistema, por ejemplo.

ASP.NET MVC

En el framework MVC, por su cercanía a los protocolos, sí es fácil identificar los conceptos de petición y redirecciones. El siguiente código sería equivalente al anteriormente mostrado, pero enviando al usuario a la acción “Index”:

[HandleError]
public class ClientesController : Controller
{
    ... // Otras acciones
 
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Editar(Cliente cliente)
    {
        if (ModelState.IsValid)
        {
            GestorDeClientes.Grabar(cliente);
            return RedirectToAction("Index");
        }
        return View(cliente);
    }
}

Publicado en: Variable not found

lunes, 6 de julio de 2009

image Hace unos meses, un usuario de StackOverflow planteaba una interesante cuestión: ¿qué debería saber un desarrollador para construir un sitio web público? Es decir, ¿cuáles son aquellos aspectos importantes que deben tenerse en cuenta a la hora de crear un site de calidad, desde el punto de vista técnico?

Tras un tiempo de respuestas, ideas y debates, otro usuario ha realizado una recopilación de los aspectos y sugerencias más votadas y los ha publicado en forma de lista categorizada, donde podemos encontrar muy buenas ideas a tener en cuenta en nuestros propios desarrollos, y que me he permitido traducir.

Muchos de los puntos son obvios y seguro que ya los estáis teniendo en cuenta, quizás otros son demasiado exagerados, y seguro que alguno de ellos ni siquiera os los habíais planteado. En cualquier caso el resultado es una relación interesante y muy a tener en cuenta para mejorar nuestros sitios web.

Interfaz y experiencia de usuario

  • Ser consciente de que los navegadores implementan los estándares de forma diferente y asegurarse de que el sitio web funciona razonablemente bien en la mayoría de los principales navegadores. Como mínimo, sería necesario probarlo con un navegador que utilice un motor reciente Gecko (Firefox), Webkit (Safari, Chrome y algunos navegadores móviles), las versiones soportadas de Internet Explorer, y Opera.
  • Tener en cuenta que el sitio web puede ser visitado utilizando medios distintos a los navegadores habituales, como por ejemplo teléfonos móviles, lectores de pantalla, o motores de búsqueda. Usar estándares de accesibilidad como WAI o Section508.
  • Considerar los mecanismos de actualización del sitio web para que estos procesos no afecten a los usuarios una vez que el sistema está en marcha y puedan producirse de forma suave y transparente. Por ejemplo, puede ayudar el mantener entornos de prueba paralelos, el uso de herramientas de control del código fuente, o mecanismos de builds automatizados.
  • No mostrar errores directamente al usuario.
  • No incluir en las páginas direcciones de correo de usuarios en texto plano, para evitar que sean bombardeados por los spammers.
  • Incluir límites razonables de utilización del sitio para evitar malos usos por parte de usuarios o procesos automáticos (como puede ser los virus). Por ejemplo, es razonable que un sistema de correo electrónico gratuito limite el número de mensajes diarios que puede enviar un usuario, aunque el número máximo sea muy alto; otro ejemplo podemos verlo en Google, que muestra un mensaje de error cuando detecta demasiado tráfico hacia sus servidores desde una única dirección IP.

Seguridad

  • Conocer la amplia guía de desarrollo OWASP, que  cubre la seguridad de sitios web de forma muy completa.
  • Conocer el fundamento de los ataques de inyección SQL y cómo prevenirlos.
  • Jamás confiar en los datos introducidos por los usuarios.
  • Evitar el almacenamiento de contraseñas en texto plano utilizando técnicas criptográficas como hashes y salts.
  • No intentes utilizar tu magnífico y elaborado sistema de autenticación; es bastante probable que existan fallos impredecibles de los que sólo te darás cuenta después de haber sido hackeado.
  • Usar SSL/HTTPS en las páginas de identificación de usuarios y, en general, en todas aquellas páginas donde sea introducida información sensible, como datos personales o bancarios.
  • Evitar el secuestro de sesiones (session hijacking).
  • Evitar los ataques XSS (Cross Site Scripting).
  • Evitar los ataques XSRF (Cross Site Request Forgeries).
  • Mantener tus sistemas actualizados con los últimos parches disponibles.
  • Asegurarse de que la información de conexión a la base de datos está almacenada en un lugar lo suficientemente seguro.
  • Mantener informado sobre las últimas técnicas de ataque y vulnerabilidades que afecten a la plataforma sobre la que trabajas.
  • Conocer el manual The Google Browser Security Handbook.

Rendimiento

  • Implementar el cacheado de páginas cuando sea necesario. Comprender y usar apropiadamente los mecanismos de cacheo HTTP.
  • Optimizar las imágenes. Por ejemplo, no utilizar una imagen de 20 Kb. como mosaico de fondo.
  • Conocer cómo comprimir el contenido de las páginas con gzip.
  • Echar un vistazo al sitio Yahoo Exceptional Performance, donde se muestran directrices y buenas prácticas para mejorar el rendimiento de sitios web. Utilizar herramientas como YSlow.
  • Utilizar la técnica de CSS Sprites para las pequeñas imágenes (como las que encontramos en las barras de herramientas), con objeto de minimizar el número de peticiones HTTP.
  • Los sitios web de alto tráfico deberían considerar el despliegue de componentes en distintos dominios para optimizar la descarga en paralelo de los mismos.
  • En general, minimizar el número total de peticiones HTTP necesarias para que el navegador muestre las páginas.

SEO

  • Utilizar direcciones URL amigables para los buscadores. Por ejemplo, utilizar direcciones del tipo "ejemplo.com/paginas/titulo-del-articulo" en lugar de "ejemplo.com/index.php?page=45".
  • No utilizar enlaces que digan "pulse aquí". Estarías creando sitio web poco optimizado para buscadores, a la vez que complicando las cosas para los usuarios que utilizan lectores de pantalla.
  • Crear un mapa del sitio en XML (sitemap).
  • Utilizar <link rel="canonical" ... /> Cuando tengas múltiples URLs que apunten a un mismo contenido.
  • Utilizar las herramientas disponibles en www.google.com/webmasters.
  • Instalar Google Analytics desde el principio.
  • Conocer cómo funcionan los rastreadores de los buscadores y el archivo robots.txt.
  • No maquetar con tablas; Google generalmente valorará positivamente el marcado HTML semántico y la maquetación con CSS.
  • Si tienes contenido no textual en la página, utiliza en el sitemap las extensiones de Google para audio, video, etc. Hay alguna información sobre ello en la respuesta de Tim Farley.

Tecnología

  • Entender el protocolo HTTP; conocer cosas como GET, POST, sesiones, cookies, y saber lo que significa e implica su naturaleza "sin estado" (stateless).
  • Escribir el código (X)HTML y CSS conformes a las especificaciones de la W3C, y asegurarse de que validan. El objetivo es evitar las particularidades de los navegadores, a la vez que se facilita enormemente la navegación utilizando browsers no estándar como lectores de pantalla o dispositivos móviles.
  • Comprender cómo se procesa el código javascript en los navegadores. Mover los scripts al final de las páginas.
  • Comprender cómo funciona el sandbox de javascript, especialmente si pretendes utilizar iframes.
  • Asegurarse de que javascript puede ser deshabilitado sin que la página deje de funcionar. AJAX debe ser una extensión, y no la base sobre la que se construya un sitio. Aunque la mayoría de usuarios lo tengan activado, recordar que existen muchos y muy populares dispositivos en los que no funcionará correctamente.
  • Entender la diferencia entre las reflexiones 301 y 302 (esto también es un aspecto SEO).
  • Aprender tanto como sea posible sobre la plataforma en la que será desplegado el sitio web en producción.
  • Considerar el uso de un reseteador de CSS.
  • Considerar herramientas como jQuery, que oculta muchas de las particularidades de los distintos navegadores utilizando javascript para la manipulación del DOM.

Corrección de errores

  • Entender que pasarás el 20% del tiempo codificando y el 80% restante manteniéndolo, por tanto codifica apropiadamente.
  • Configurar un buen sistema de notificación y gestión de errores.
  • Habilitar sistemas para que los usuarios puedan contactar contigo y trasladarte críticas y sugerencias.
  • Documentar cómo funciona la aplicación para facilitar el futuro soporte y mantenimiento del sistema.
  • Poner a funcionar el sistema primero en Firefox y después en Internet Explorer.
  • Hacer copias de seguridad frecuentes.

Publicado en: Variable not found.

lunes, 11 de mayo de 2009

Joe Cartano, perteneciente al Visual Web Development Team de Microsoft, ha publicado en el blog oficial (Visual Web Developer Team Blog) un post anunciando que ha actualizado la plantilla que permite crear directamente proyectos ASP.NET MVC con tests unitarios NUnit.

Así, una vez instalado, al crear un proyecto de tipo ASP.NET MVC nos aparecerá un cuadro de diálogo como el siguiente, en el que se nos brindará la oportunidad de crear en la solución un proyecto de pruebas unitarias utilizando NUnit:

Crear proyecto de pruebas unitarias

Para los poseedores de algunas de las versiones profesionales de Visual Studio 2008, esta ventana no es nueva, puesto que por defecto ya se incluyen los proyectos de tests propios de Microsoft, pero sí lo es para la versión express del IDE, que no incluye el framework de pruebas y en el que había que crear el proyecto a mano.

El proyecto, que se crea automáticamente, realiza 27 tests sobre la plantilla original de proyectos ASP.NET MVC, y pueden servir como base para seguir creando nuestro propio conjunto de pruebas:

¡La plantilla ASP.NET MVC valida!

La plantilla se instala descargando el archivo .zip cuyo enlace encontraréis en el post original y ejecutando, si es necesario con un usuario con privilegios de administrador, el script installNUnit.cmd disponible en el raíz del directorio donde lo hayáis descomprimido.

Para que todo vaya bien, debéis contar con NUnit previamente instalado en vuestro equipo. Pero ojo, las plantillas están preparadas para la versión 2.4.8.0 y la versión actual es la 2.5.0.9122, por lo que puede que no os funcionen bien si estáis a la última.

En este caso, es necesario tocar a mano los archivos de plantillas. Podéis seguir estos pasos:

  1. Descargad el archivo de plantillas desde el blog del Visual Web Developer Team.
  2. Descomprimidlo sobre cualquier carpeta.
  3. En los subdirectorios CSharp y Visual Basic encontraréis un archivo llamado MvcApplication.NUnit.Tests.zip. Son las plantillas para cada uno de esos lenguajes.
  4. El interior de dicho zip está el archivo de proyecto (MvcApplication.NUnit.Test.vbproj en el caso de Visual Basic, MvcApplication.NUnit.Test.csproj en C#). Descomprimid sólo estos archivos y buscar en ambos la cadena “2.4.8.0” y sustituirla por la versión de NUnit que tengáis instalada (en mi caso, “2.5.0.9122”). Al acabar, actualizad de nuevo el .zip con el archivo que acabáis de editar.
  5. Ejecutad el script de instalación installNUnit.cmd.

Publicado en: Variable not found.

domingo, 3 de mayo de 2009

Existen numerosas aplicaciones que permiten analizar nuestros desarrollos con el objetivo final de incrementar la calidad de los mismos. FxCop, por ejemplo, es capaz de analizar los ensamblados y avisarnos cuando se encuentra con incumplimientos de las pautas de diseño para desarrolladores de librerías para .Net Framework (Design Guidelines for Class Library Developers). También hace tiempo comenté por aquí la disponibilidad de  Microsoft Source Analysis for C#, una herramienta que se centra en el código fuente y el cumplimiento de reglas de codificación.

Ahora, gracias al ofrecimiento de Patrick Smacchia, lead developer del producto, he podido probar NDepend, una herramienta de análisis de código de la que había oído hablar y que va mucho más allá que las citadas anteriormente.

La principal misión de NDepend es ayudarnos a incrementar la calidad de nuestros sistemas desarrollados con .NET mediante el análisis de sus ensamblados y código fuente desde distintas perspectivas, como la complejidad de sus módulos, el tamaño de los mismos, las interdependencias entre ellos, etc. Es decir, a diferencia de otros analizadores, su objetivo no es avisarnos de aspectos como la utilización de convenciones de codificación (aunque también puede hacerlo), o el uso de buenas prácticas de diseño, sino ayudarnos a determinar, por ejemplo, cuándo ponemos en peligro la mantenibilidad y evolución de un sistema debido a la complejidad  o al fuerte acoplamiento de algunos de sus componentes, por citar sólo algunos criterios.

El entorno gráfico

VisualNDepend es el entorno gráfico de la herramienta, y nos ofrece un entorno de trabajo muy potente e intuitivo, aunque durante los primeros minutos pueda resultar algo complejo debido a la cantidad de información mostrada.

Iniciar el análisis de un sistema es muy sencillo; una vez seleccionado el ensamblado, conjunto de ensamblados o proyecto a estudiar, el sistema realiza el análisis, del cual se obtiene un informe bastante completo, basado en web, sobre el mismo (podéis ver un ejemplo de informe en la página del producto). En él se recogen:

  • métricas de la aplicación, entre las que encontramos el número de líneas de código, comentarios, número de clases, métodos, etc., así como datos estadísticos relativos a la complejidad, extensión y estructura del código.
  • métricas por ensamblado, donde se refleja, por cada uno de los ensamblados que componen la solución, datos sobre su tamaño, grados de cohesión, acoplamiento, y otros aspectos relativos a su complejidad e interdependencia.
  • Vista de estructura vista de estructura (captura de la derecha) que muestra la distribución de componentes, la granularidad y su complejidad relativa según el tamaño de los bloques visualizados.
  • diagrama de abstracción e inestabilidad, que posiciona cada ensamblado en función del número de clases abstractas e interfaces que presenta y su dependencia del resto de elementos.
  • relación entre ensamblados, que detalla las interdependencias entre ensamblados del proyecto, los posibles ciclos, así como un posible orden de generación.
  • consultas y restricciones CQL, que realiza una serie de consultas predefinidas sobre los ensamblados y el código que nos ayuda a detectar una infinidad de problemas en nuestros desarrollos, desde aspectos relativamente simples como el exceso de métodos en clases o el incumplimiento de ciertas convenciones de nombrado, hasta problemas en la cobertura de los tests generados con NCover o Visual Studio Team System.

Pero lo mejor del entorno gráfico no es poder generar un análisis en formato web para poder consultarlo más adelante, de hecho esto puede conseguir también con la aplicación de consola que incluye NDepend. Lo mejor son las fantásticas herramientas interactivas que nos permiten navegar a través de nuestras aplicaciones, cambiar de vista, ampliar información sobre cualquier elemento, y realizar consultas en tiempo real, siempre ofreciendo unos resultados muy claros y visuales, como:

Diagrama de dependencias

  • diagrama de dependencias entre todo tipo de elementos, como clases, espacios de nombres, o ensamblados. Resulta muy útil, además, configurar el tamaño de los bloques, el grosor del borde y el de las flechas de unión para que sean proporcionales a la complejidad, tamaño y una larga lista de criterios.
  • Tabla de dependencias matriz de dependencias, que muestra de forma visual las relaciones de utilización entre espacios de nombres, tipos, métodos o propiedades, con posibilidad de ir ampliando información.
  • comparación entre ensamblados, mostrándonos los cambios producidos entre, por ejemplo, dos versiones de una misma librería o aplicación.
  • navegación avanzada por el código a través del uso del menú contextual que facilita la rápida localización de referencias, directas e indirectas, hacia y desde un método, propiedad o tipo existente.
  • enlace con Reflector, una herramienta indispensable, con la que se integra perfectamente gracias a su plugin.

 

CQL (Code Query Language)

Sin duda, una de las características más interesante que tiene NDepend es el soporte del lenguaje de consulta CQL (Code Query Language), que nos ofrece la posibilidad de tratar nuestro código y ensamblados como si fuesen una gigantesca base de datos sobre la que podemos realizar consultas de forma muy natural.  Las posibilidades que esto ofrece son tan amplias que prácticamente todas las funcionalidades de la aplicación están basadas en órdenes CQL prediseñadas que acompañan al producto, aunque podemos crear todas las consultas personalizadas que necesitemos, como por ejemplo:

/* Obtiene los métodos que escriben una propiedad */
SELECT METHODS WHERE IsDirectlyWritingField "Model.Cliente.Nombre"

/* Obtiene métodos que acceden incorrectamente a los
datos desde la capa de interfaz
*/
SELECT METHODS FROM NAMESPACES "Interfaz" WHERE IsDirectlyUsing "MySql.Data"

/* Obtiene los 10 métodos con más líneas de código */
SELECT TOP 10 METHODS ORDER BY NbLinesOfCode DESC

/* Obtiene los métodos considerados "peligrosos" según su complejidad ciclomática */
SELECT METHODS WHERE CyclomaticComplexity > 20


Editor de CQL con intellisenseAdemás de consultas CQL cuyo resultado podremos observar de forma directa tanto visualmente como en forma de listado, es posible incluir restricciones (WARN) que hará que el sistema nos alerte durante el análisis de un proyecto que cumpla las condiciones especificadas. Por ejemplo, la siguiente restricción nos avisará cuando exista un cierto tufillo a complejidad excesiva en un método (que haya sido definido con más de 10 parámetros):

WARN IF Count > 0 IN  SELECT METHODS WHERE NbParameters > 10

Estas consultas pueden ser añadidas (en la versión Pro) e integradas en los análisis, así como modificar las existentes, de forma que el producto puede ser personalizado a nuestras convenciones o necesidades específicas.

Otra posibilidad es incluir dentro del código de un ensamblado las restricciones que deseamos que se cumplan, expresándolas en lenguaje CQL embebido en un atributo de tipo CQLConstraint aplicado a sus elementos:

Afortunadamente existe mucha información disponible en la web sobre el lenguaje CQL, y consultas que nos muestran cómo sacarle el máximo partido.

Instalación e integraciones

NDepend se distribuye en formato .zip, y que puede ejecutarse directamente una vez descomprimido el contenido sobre una carpeta. La licencia, una vez obtenida, es un archivo XML firmado digitalmente que debemos colocar en el directorio de la aplicación, y listo.

Integración con VS y Reflector

Ya en ejecución, desde el menú “options” es posible configurarlo para que se integre con Visual Studio 2005, 2008 y como he comentado anteriormente, con el magnífico Reflector, con el que hace una excelente pareja.

Asimismo, es posible utilizarlo en sistemas como MSBuild y NAnt, facilitando así su uso en entornos de integración continua y montaje automatizado, para los que ofrece librerías

Finalmente, he de aclarar que NDepend es una aplicación comercial, aunque dispone de una versión limitada gratuita utilizable por universidades, desarrolladores open source e incluso, durante un tiempo determinado, de prueba en proyectos comerciales.

En cualquier caso, no dudéis en probarlo: os dará un control sobre vuestro código difícil de conseguir con otras herramientas.


Publicado en: www.variablenotfound.com

domingo, 1 de marzo de 2009
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.
martes, 21 de octubre de 2008
Prototipo en papel de Vimeo.comSaboreando los bocabits ofrecidos por Javier Babuglia encontré, hace ya algo de tiempo, una herramienta de prototipado de interfaces de usuario de lo más útil y simpática, Balsamiq Mockups, que combina la potencia y flexibilidad de un diseñador visual con los resultados del prototipado en papel.

El objetivo de este tipo de herramientas no es obtener el diseño gráfico final de los interfaces de un sistema, sea de escritorio o web, sino un esqueleto o esquema que muestre la disposición conceptual de los principales elementos en pantalla, sin entrar en detalles concretos más cercanos al mundo del diseño artístico.

Su utilización es sencillísima. Contamos con hasta 60 elementos prediseñados que cubren prácticamente todas las necesidades (cuadros, iconos, controles de formularios, textos, etc.) que podemos arrastrar y colocar sobre la superficie de diseño como con cualquier otra herramienta visual, modificando las propiedades (contenido textual, alineación, colores...) de forma directa. El resultado que podéis llegar a obtener es como el mostrado en la siguiente imagen, tomada de los Mockups de ejemplo de la web de sus autores.


Balsamiq Mockups es una aplicación multiplataforma creada con Adobe Flex, de la que existen tanto la versión on-line para usar desde la web, como off-line, para su uso estando desconectado, que se puede descargar de forma gratuita, aunque para acceder a alguna de sus funcionalidades será necesario obtener una clave de licencia, que puede ser gratis si programas por amor al arte (para ONGs, proyectos open source...), o si eres un blogger o escribes en sitios web. En cualquier caso, todo hay que decirlo, la licencia resulta muy económica, menos de 80$.

Y para terminar, ahí va un prototipo de Variable not found realizado en unos minutos:

Variable Not Found, casi en papel

Publicado en: www.variablenotfound.com.
lunes, 23 de junio de 2008
NUnitLa inclusión en el SP1 (Beta) de Visual Web Developer Express 2008 de soporte para librerías de clases y aplicaciones Web, abriendo el uso del framework MVC Preview 3 para los que estamos aprendiendo con esta herramienta, era sin duda una novedad sorprendente, pero no la única.

Joe Cartano comentaba hace unas semanas, en el blog oficial del equipo de Visual Web Developer , las nuevas mejoras de este IDE, y en especial las relativas al soporte para plantillas de terceros, y publicó de paso unas estupendas plantillas para la creación de tests unitarios basados en NUnit en aplicaciones ASP.NET MVC.

Para instalarlas, basta con descargar el archivo (con el enlace anterior), descomprimirlo sobre un directorio cualquiera y ejecutar el archivo .BAT correspondiente a la versión de Visual Studio que estemos utilizado, siempre con permisos de administrador. Si todo va bien y suponiendo además que tenemos NUnit instalado, al crear una nueva aplicación ASP.NET MVC en VWD Express aparecerá un cuadro de diálogo como el siguiente:

Diálogo de creación de un proyecto de tests
Esto va en la línea de lo comentado por ScottGu meses atrás, en sus primeros posts sobre el nuevo framework MVC, donde aseguraba que se podría utilizar cualquier framework de testing, citando algunos como NUnit y MBUnit. Y lo de permitir una cierta integración de estos frameworks ajenos a la casa en la versión Express es todo un detalle.

Si se acepta el diálogo, se creará dentro de la misma solución un proyecto de tipo librería que contendrá las referencias a ensamblados necesarios para su ejecución (NUnit, routing, Mvc, etc.) y con un par de métodos de prueba predefinidos. De esta forma, para comprobar el correcto funcionamiento de nuestras aplicaciones sólo tendremos que ejecutar los tests, aunque de momento, y a diferencia de las versiones superiores de Visual Studio 2008, tendrá que ser desde fuera del entorno, utilizando la consola de NUnit:

WDExpress 2008 y NUnit en ejecución

Publicado en: www.variablenotfound.com.
domingo, 25 de mayo de 2008
¿A qué huele tu código?Algunos dirán que a nada, como las nubes ;-) Sin embargo, el olor que desprende tu código, el llamado "code smell", término acuñado por Kent Beck (uno de los padres del Extreme Programming), puede darte pistas sobre problemas existentes en el mismo y alertarte ante situaciones no deseadas.

El concepto es parecido a los antipatrones de programación, aunque funcionan a un nivel todavía más sutil, pues no describe situaciones completas sino indicios. De hecho, el uso de esta metáfora sensorial respecto a un código, es decir, que éste desprenda cierto tufillo, indica que sería conveniente realizar una revisión en profundidad para ver si hay que refactorizar, pero no implica que necesariamente haya algo incorrecto. Además, dado que trata de algo tan personal y específico como el código fuente, a veces las señales son bastante subjetivas y dependientes de lenguajes y tecnologías concretas.

Existen multitud de listas y clasificaciones, aunque es muy interesante la realizada por Mika Mäntylä, investigador de la universidad de Helsinki, ha creado una taxonomía que agrupa code smells relacionados en cinco categorías en función del efecto que pueden provocar:

  • The bloaters (los infladores), que agrupa 'aromas' que indican el crecimiento excesivo de algún aspecto que hacen incontrolable el código.

    • Long method (método extenso) que precisa de su reducción para ser más legible y mantenible.

    • Large class (clase larga), con síntomas y consecuencias muy similares al caso anterior.

    • Primitive obsession (obsesión por tipos primitivos), cuyo síntoma es la utilización de tipos primitivos para almacenar datos de entidades pequeñas (por ejemplo, usar un long para guardar un número de teléfono).

    • Long parameter list (lista de parámetros larga), que incrementan la complejidad de un método de forma considerable.

    • Dataclumps (grupos de datos), o uso de un cunjunto de variables o propiedades de tipos primitivos en lugar de crear una clase apropiada para almacenar los datos, lo que a su vez provoca el incremento de parámetros en métodos y clases.

  • The Object-Orientation Abusers (los maltratadores de la orientación a objetos), que aglutina code smells que indican que no se está aprovechando la potencia de este paradigma:

    • Switch statements (sentencias Switch), que podrían indicar una falta de utilización de mecanismos de herencia.

    • Temporary field (campo temporal), que se salta el principio de encapsulamiento y ocultación de variables haciendo que éstas pertenezcan a la clase cuando su ámbito debería ser exclusivamente el método que las usa.

    • Refused bequest (rechazo del legado), cuando una subclase 'rechaza' métodos o propiedades heredadas, atentando directamente contra uno de los principales pilares de la OOP.

    • Alternative Classes with Different Interfaces (clases alternativas con distintos interfaces) indica la ausencia de interfaces comunes entre clases similares.

  • The change preventers (los impedidores de cambios)

    • Divergent Change (cambio divergente), que hace que sean implementadas dentro de la misma clase funcionalidades sin ninguna relación entre ellas, lo que sugiere extraerlas a una nueva clase.

    • Shotgun surgery (cirujía de escopeta), ocurre cuando un cambio en una clase implica modificar varias clases relacionadas.

    • Parallel Inheritance Hierarchies (jerarquías de herencia paralelas), paralelismo que aparece cuando cada vez que se crea una instancia de una clase es necesario crear una instancia de otra clase, evitable uniendo ambas en una úncia clase final.


  • The Dispensables (los prescindibles), pistas aportadas por porciones de código innecesarias que podrían y deberían ser eliminadas:

    • Lazy class (clase holgazana), una clase sin apenas responsabilidades que hay que dotar de sentido, o bien eliminar.

    • Data class (clase de datos), cuando una clase sólo se utiliza para almacenar datos, pero no dispone de métodos asociados a éstos.

    • Duplicate code (código duplicado), presencia de código duplicado que dificulta enormemente el mantenimiento.

    • Dead code (código muerto), aparición de código que no se utiliza, probablemente procedente de versiones anteriores, prototipos o pruebas.

    • Speculative generality (generalización especulativa), ocurre cuando un código intenta solucionar problemas más allá de sus necesidades actuales.


  • The couplers (Los emparejadores), son code smells que alertan sobre problemas de acoplamiento componentes, a veces excesivo y otras demasiado escaso.

    • Features envy (envidia de características), que aparece cuando existe un método de una clase que utiliza extensivamente métodos de otra clase y podría sugerir la necesidad de moverlo a ésta.

    • Inappropriate intimacy (intimidad inapropiada), ocurre cuando dos clases de conocen demasiado y usan con demasiada confianza, y a veces de forma inapropiada, sus miembros (en la acepción POO del término ;-))

    • Message Chains (cadenas de mensajes), aroma desprendido por código que realiza una cadena de llamadas a métodos de clases distintas utilizando como parámetros el retorno de las llamadas anteriores, como A.getB().getC().getD().getTheNeededData(), que dejan entrever un acoplamiento excesivo de la primera clase con la última.

    • Middle man (intermediario), que cuestiona la necesidad de tener clases cuyo único objetivo es actuar de intermediaria entre otras dos clases.


Aunque agrupadas bajo otros criterios, existe una interesante relación de code smells y la refactorización a aplicar en cada caso, que ayuda a determinar las acciones correctivas oportunas una vez se haya comprobado que hay algo que no va bien.

Y ahora, ¿piensas que tu código no huele a nada? ;-P

Publicado en: http://www.variablenotfound.com/.
sábado, 24 de mayo de 2008
Análisis de CódigoJason Allor anunciaba ayer mismo el lanzamiento de una nueva herramienta, Microsoft Source Analysis for C#, cuyo objetivo es ayudar a los desarrolladores a producir código elegante, legible, mantenible y consistente entre los miembros de un equipo de trabajo. De hecho, era conocida como StyleCop en Microsoft, donde llevan utilizándola ya varios años.

Y aunque pueda parecer similar a FxCop, Microsoft Source Analysis for C# se centra en el análisis de código fuente y no en ensamblados, lo que hace que pueda afinar mucho más en las reglas de codificación.

Incluye sobre 200 buenas prácticas, cubriendo aspectos como:
  • Layout (disposición) de elementos, instrucciones, expresiones y consultas
  • Ubicación de llaves, paréntesis, corchetes, etc.
  • Espaciado alrededor de palabras clave y operadores
  • Espaciado entre líneas
  • Ubicación de parámetros en llamadas y declaraciones de métodos
  • Ordenación de elementos de una clase
  • Formateo de documentación de elementos y archivos
  • Nombrado de campos y variables
  • Uso de tipos integrados
  • Uso de modificadores de acceso
  • Contenidos permitidos en archivos
  • Texto de depuración
Microsoft Source Analysis integrado en VS2005
Tras su descarga e instalación, que puede realizarse desde esta dirección, la herramienta se integra en Visual Studio 2005 y 2008, aunque también puede utilizarse desde la línea de comandos o MSBuild.


Publicado en: www.variablenotfound.com.
domingo, 6 de abril de 2008
Semanas atrás publicaba el post "101 citas célebres del mundo de la informática", la traducción del post original de Timm Martin en Devtopics, "101 Great computer quotes". El tema me pareció tan divertivo e interesante que he realizado una nueva recopilación de otras tantas frases relacionadas con el mundo de la informática, y con especial énfasis en el desarrollo de software.

Este es el segundo post de la serie compuesta por:
miércoles, 27 de febrero de 2008
Bonito plato de spaghettiSabemos que los patrones son plantillas reutilizables que podemos usar para solucionar problemas habituales en el proceso de desarrollo de software. Así, permiten utilizar soluciones fiables y bien conocidas a problemas concretos, aprovechando experiencias previas como base para la consecución de mejores resultados en los nuevos desarrollos.

Pues bien, justo en el lado opuesto se encuentran los antipatrones, que definen situaciones y comportamientos que, según experiencias anteriores, nos conducen al fracaso en proyectos de desarrollo de software, es decir, son soluciones o planteamientos que se han demostrado incorrectos.

Y es ahí donde radica su interés: la observación y conocimiento de los mismos puede evitarnos resultados desastrosos, o actuar como alertas tempranas ante decisiones o dinámicas incorrectas, permitiéndonos prevenir, evitar o recuperarnos de estos problemas.

Al igual que en los patrones, su descripción está relativamente formalizada y suele recoger los siguientes aspectos:
  • nombre del antipatrón, así como su "alias"
  • su tipología: organizacional, de análisis, desarrollo... (veremos esto más tarde)
  • contexto y entorno en el que se aplica
  • descripción del problema concreto
  • síntomas, y consecuencias de la aplicación del antipatrón
  • causas típicas y raíces del problema
  • refactorización a aplicar, es decir, una descripción de cómo podríamos replantear el problema y conseguir una solución positiva.
  • ejemplos y escenarios para su comprensión.
  • soluciones relacionadas con la propuesta.

Por ejemplo, un resumen del clásico antipatrón que reconoceréis muy rápidamente, el llamado spaghetti code:

Nombre:Spaghetti Code
Tipología:Desarrollo
Problema:Existencia de una pieza de código compleja y sin apenas estructura que dificulta enormemente su mantenimiento posterior
Síntomas y consecuencias:
  • Tiempo de mantenimiento excesivo debido a la necesidad de estudio del código
  • Código no reutilizable
  • Aparición del temido "es mejor reescribirlo"
  • Métodos y funciones muy extensas
  • Abuso de variables globales
Causas:
  • Inexperiencia de desarrolladores
  • Reutilización de código de prototipos rápidos
  • Ausencia de diseño previo a la implementación
  • Desarrolladores trabajando en solitario
  • Falta de revisiones de código
Solución positiva:
  • Aplicar refactorización mientras se programa
  • Usar disciplinas de desarrollo específicas, métricas y buenas prácticas
  • Realizar y desarrollar el diseño del sistema antes de implementar

Según según la Wikipedia, los antipatrones se clasifican en los siguientes grupos, atendiendo a las áreas a las que afectan:
  • Antipatrones Organizacionales, que incluyen prácticas nocivas a este nivel, como pueden ser, entre otros:
    • Gestión de champiñones (Mushroom management), o mantener al equipo en la oscuridad, desinformado, y cubierto de porquería.
    • Parálisis en análisis (Analysis paralysis), o quedar inmovilizado debido a un análisis o precaución excesiva, en contraposición a la siguiente:
    • Extinción por intuición (Extint by instinct), llegar a la muerte por adelantarse demasiado y usar la intuición para la toma de decisiones.
  • Antipatrones de Gestión de proyectos, describiendo problemas en la gestión de proyectos, como los célebres:
    • Marcha de la muerte (Death march), que describe el avance de determinados proyectos hacia el fracaso aunque todo el personal, excepto los gerentes, saben que al final se darán el castañazo.
    • Humo y espejos (Smoke and mirrors), o la demostración de funcionalidades o características no implementadas como si fueran reales, lo que siempre he llamado "enseñar cartón piedra".
  • Antipatrones de Gestión de equipos, que recoge problemas relacionados con la relación con y de equipos de trabajo, como:
    • Doble diabólico (traducción libre del término Doppelganger), personas que dependiendo del día pueden ser magníficos colaboradores o auténticos demonios.
    • Gestor ausente (Absentee manager), describiendo situaciones en las que el director está invisible periodos prolongados
  • Antipatrones de Análisis, categoría que engloba antipatrones relacionados con la fase analítica de los proyectos software, entre otros:
    • Retroespecificación (Retro-specification), o lo que viene a ser la realización del análisis una vez implementada la solución.
    • Especificación de servilleta (Napkin specification), también muy socorrida, que consiste en pasar al equipo de desarrollo las especificaciones del producto a crear descritas con muy poco detalle o informalmente.
  • Antipatrones de Diseño, que incluye malas prácticas de diseño de software que dan lugar a aplicaciones y componentes estructuralmente incorrectos:
    • Gran bola de lodo (Big ball of mud), realización de aplicaciones sin estructura reconocible.
    • Factoría de gas (Gas factory), diseños innecesariamente complejos.
    • Botón mágico (Magic Pushbutton), o implementación de funcionalidades directamente en los manejadores de evento (p.e., click) del interfaz.
  • Antipatrones en Orientación a objetos, como una especialización del anterior, describe problemas frecuentes en los diseños creados bajo este paradigma, como:
    • Llamar al super (Call super), obligar a las subclases a llamar a la clase de la que heredan.
    • Singletonitis, abuso del patrón singleton.
    • Orgía de objetos (Object orgy), o encapsulación incorrecta en clases que permite el acceso incontrolado a sus métodos y propiedades internas.
    • Otra jodida capa más (YAFL, Yet another fucking layer), o la inclusión excesiva de capas en un sistema.
  • Antipatrones de Programación, con un gran número de errores frecuentes a evitar, como:
    • Spaghetti code, comentando anteriormente.
    • Ravioli code, que consiste en la existencia de un gran número de objetos desconectados o débilmente acoplados entre sí.
    • Ocultación de errores (Error hiding), o capturar errores antes de que lleguen usuario, mostrando mensajes incomprensibles o simplemente no mostrar nada.
    • Números mágicos (Magic numbers), incluir números inexplicables en el código.
  • Antipatrones Metodológicos, o formas de desarrollar que se han demostrado incorrectas a lo largo del tiempo, como pueden ser:
    • Programación copy & paste, también llamada herencia de editor, consiste en copiar, pegar y modificar, en contraposición a la estritura de software reutilizable.
    • Factor de improbabilidad (Improbability factor), asumir que un error conocido es improbable que ocurra.
    • Optimización prematura (Premature optimization), según algunos la raíz de todos los males, consiste en sacrificar el buen diseño y mantebilidad de un software en benecificio de la eficiencia.
    • Programación por permutación (Programming by permutation), o intentar dar con una solución modificando sucesivamente el código para ver si funciona.
  • Antipatrones de Gestión de configuración, hace referencia a antipatrones relacionados con la gestión de los entornos de desarrollo y explotación del software, como las variantes del infierno de las dependencias (Dependency hell), o problemas de versionado de librerías y componentes:
    • DLL's Hell, el conocido y traumático mundo de las librerías dinámicas en Windows.
    • JAR's Hell, idem, pero relativo a las librerías Java.

Por no hacer el post eterno sólo he recogido unos cuantos, aunque existen cientos de ellos, y con una gran variedad temática: antipatrones para el desarrollo guiado por pruebas (TDD), antipatrones de manejo de excepciones, para el uso de arquitecturas orientadas al servicio (SOA), de rendimiento, de seguridad, centrados en tecnologías (p.e., J2EE antipatterns) o según el tipo de software (sistemas de gestión, tiempo real, videojuegos, etc.).

Y como conclusión personal, decir que me he visto reconocido en multitud de ellos, lo cual significa que muy descaminados no andan. Es más, si hiciera una lista con patrones y otra con los antipatrones que utilizo o he utilizado, la segunda tendría más elementos que la primera... ¿quizás es momento de reflexionar un poco?

Publicado en: http://www.variablenotfound.com/.
domingo, 10 de febrero de 2008
Existen muchos consejos para crear código mantenible, como los que ya cité cuando hablaba sobre comentar el código fuente, pero ninguno iguala a este:



"Always code as if the person who will maintain your code is a maniac serial killer that knows where you live"

(Codifica siempre como si la persona que fuera a mantener tu código fuera un asesino en serie maníaco que sabe donde vives)

Al parecer se trata de un leyenda urbana sobre Visual C++ 6.0, pero no deja de tener su razón...

Imagen: My Confined Space

Publicado en: http://www.variablenotfound.com/.
domingo, 20 de enero de 2008
FxCop es una herramienta que nos ayuda a mejorar la calidad de nuestras aplicaciones y librerías desarrolladas en cualquier versión de .Net, analizando de forma automática nuestros ensamblados desde distintas perspectivas y sugiriéndonos mejoras cuando detecta algún problema o incumplimiento de las pautas de diseño para desarrolladores de librerías para .Net Framework (Design Guidelines for Class Library Developers).

La versión actual (1.35) se puede descargar desde esta dirección, aunque ya existe una beta de la v1.36 en la web de Microsoft. Todos los comentarios que siguen se refieren a esta última versión, la 1.36 (beta), osado que es uno ;-), pero la mayor parte son válidos para la última revisión estable, la 1.35.

Una vez instalado tendremos a nuestra disposición dos aplicaciones: FxCop, que facilita el análisis y consulta de resultados a través de su propia GUI, y FxCopCmd, ideada para su utilización desde línea de comandos e integrarlo en otros sistemas, como Visual Studio, como parte del proceso de construcción (build) automatizado.

En cualquiera de los dos casos, el análisis de los ensamblados se realiza sometiéndolos a la comprobación de una serie de reglas basadas en buenas prácticas y consejos para asegurar la robustez y mantenibilidad de código. Del resultado del mismo obtendremos un informe con advertencias agrupadas en las siguientes categorías:
  • Advertencias de diseño, recoge avisos de incumplimientos de buenas prácticas de diseño para .Net Framework, como pueden uso de constructores públicos en tipos abstractos, interfaces o namespaces vacíos, uso de parámetros out, capturas de excepciones genéricas y un largo etcétera.

  • Advertencias de globalización, que avisan de problemas relacionados con la globalización de aplicaciones y librerías, como pueden ser el uso de aceleradores de teclado duplicados, inclusión de rutas a carpetas de sistema dependientes del idioma ("archivos de programa"), etc.

  • Advertencias de interoperabilidad, que analizan problemas relativos al soporte de interacción con clientes COM, como el uso de tipos auto layout visibles a COM, utilización de System.Int64 en argumentos (que no pueden ser usados por clientes VB6), o la sobrecarga de métodos.

  • Advertencias de movilidad, cuestionando el soporte eficiente de características de ahorro de energía, como uso de procesos con prioridad ProcessPriorityClass.Idle., o inclusión de Timers que se repitan más de una vez por segundo.

  • Advertencias de nombrado, que detectan las faltas de cumplimiento de las guías y prácticas recomendadas en cuanto al nombrado de elementos (clases, métodos, variables, etc.), como uso de nombres de parámetros que coinciden con nombres de tipo, y más con los propios de un lenguaje concreto, mayúsculas y minúsculas no utilizadas correctamente, eventos que comiencen por "Before" o "After", puesto que deben nombrarse conjugando verbos en función del momento que se producen (p.e., Closing y Closed en lugar de BeforeClose y AfterClose), y un largo conjunto de comprobaciones.

  • Advertencias de rendimiento, que ayudan a detectar problemas en el rendimiento de la aplicación o librería, comprobando puntos como el número de variables locales usadas, la existencia de miembros privados o internos (a nivel de ensamblado) no usados, creación de cadenas (strings) innecesarias, por llamadas múltiples a ToLower() o ToUpper() sobre la misma instancia, realización de conversiones (castings) innecesarios, concatenaciones de cadenas en bucles, etc.

  • Advertencias de portabilidad, que recoge observaciones interesantes para la portabilidad a distintas plataformas, como el uso de declaraciones PInvoke.

  • Advertencias de seguridad, que se centran en analizar aspectos que podrían dar lugar a aplicaciones o librerías inseguras, avisando de problemas potenciales como la ausencia de directivas de seguridad, punteros visibles, o uso de arrays de sólo lectura, entre otros.

  • Advertencias de uso, que analizan el uso apropiado del framework .Net realizando multitud de chequeos sobre el código, detectando aspectos como ausencia la liberación (dispose) explícita de tipos IDisposable, resultados de métodos no usados, uso incorrecto de NaN, etc.


(Puedes ver la lista completa de comprobaciones, en inglés, aquí)

Realizar un análisis de un ensamblado con FxCop resulta de lo más sencillo. Basta con crear un proyecto (al iniciar la aplicación aparecerá uno creado por defecto), añadir los ensamblados a analizar y pulsar el botón que iniciará el proceso.

El tiempo dependerá del número y complejidad de los ensamblados a analizar, así como del conjunto de reglas (pestaña "rules") a aplicar, que por defecto serán todas. En cualquier caso, el proceso es rápido y finalizará con la presentación de una lista con el resumen de las anomalías detectadas, sobre la que podremos navegar y ampliar información.


Por cada anomalía, además, podremos acceder a una descripción completa de sus causas, origen en el código fuente, posibles soluciones, una URL para ampliar información, grado de certeza de existencia del problema, su gravedad y la categoría a la que pertenece. Con estos datos, sólo nos quedará acudir a nuestro código y corregir o mejorar los aspectos indicados.

En conclusión, se trata de una interesante herramienta que puede ayudarnos a mejorar la calidad del código que creamos. Aunque existen los "falsos positivos" y a veces no es todo lo precisa que debiera, la gran cantidad de comprobaciones que realiza, la posibilidad de añadir reglas personalizadas, así como el detalle de los informes de resultados hacen de ella una utilidad casi imprescindible para los desarrolladores .Net.

Publicado originalmente en: http://www.variablenotfound.com/.