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 patrones. Mostrar todas las entradas
Mostrando entradas con la etiqueta patrones. Mostrar todas las entradas
sábado, 28 de diciembre de 2019
Un reciente estudio de la consultora Garner indica que durante el desarrollo de una aplicación dedicamos más del 80% de nuestro tiempo a implementar controles de posibles fallos.

Además, este otro informe de StackOverflow obtenido tras analizar el código fuente de miles de proyectos open source, el control y tratamiento de excepciones y problemas supone más del 60% de nuestra base de código y, por tanto, aporta gran parte de la complejidad interna de las aplicaciones.

Pero, adicionalmente, estos estudios ponen al descubierto otros tres aspectos bastante interesantes:
  • Primero, que la mayoría de errores que intentamos controlar no se van a producir nunca. Son posibles a nivel de flujo de código, pero en la operativa de la aplicación no ocurrirán, por lo que podríamos decir que son problemas creados artificialmente durante el proceso de desarrollo.
     
  • Segundo, las líneas de control de errores no están exentas de problemas, por lo que muy a menudo encontraremos en ellas nuevo código de control (¿quién no ha visto try/catch anidados a varios niveles?), por lo que la bola de nieve no para nunca de crecer: código de tratamiento de errores que a su vez contiene código de tratamiento de errores, y así hasta el infinito.
     
  • Y por último, también nos encontramos con que en muchas ocasiones el código de control no hace nada. Por ejemplo, se cuentan por millones las líneas de código detectadas en Github cuyo tratamiento de excepciones consiste simplemente en la aplicación a rajatabla del Swallow Design Pattern, por ejemplo, implementando bloques catch() vacíos.
Y conociendo estos datos, ¿por qué dedicamos tanto tiempo a la gestión de errores en nuestro código? Pues básicamente porque hemos sido educados para eso. Exceptuando cuando se nos cala el coche, no hay nada que suponga un golpe al ego tan importante como cuando una de nuestras aplicaciones falla, y por eso no escatimamos recursos a la hora de evitarlo.

¿No estaría bien poder ignorar esos problemas y centrar nuestro código en aportar valor a nuestros clientes?
martes, 12 de febrero de 2019
ASP.NET Core Como sabemos, ASP.NET Core incluye un sistema de inyección de dependencias que, aunque es algo simple comparado con otras alternativas más veteranas, cubre la mayoría de necesidades habituales. Por ejemplo, un aspecto que no es muy conocido y que puede ser útil en muchas ocasiones es su capacidad para registrar y recuperar múltiples implementaciones de una misma interfaz.

En este post vamos a ver cómo conseguirlo, y un caso práctico de uso de esta técnica en un escenario muy frecuente.
martes, 27 de noviembre de 2018
Desarrolladores Como sabemos, la inyección de dependencias está grabada a fuego en los genes de ASP.NET Core. La mayoría de sus componentes la usan internamente para obtener acceso a otros componentes que necesitan para cumplir sus funciones y, además, es una práctica recomendada en la parte que nos toca a nosotros como desarrolladores de aplicaciones.

Por ello, en ASP.NET Core MVC, lo habitual es que implementemos nuestros controladores atendiendo a este principio, y para ello utilicemos la técnica de inyección de dependencias en el constructor:
public class InvoiceController: Controller
{
    private readonly IInvoiceServices _invoiceServices;
    private readonly IMapper _mapper;
    private readonly ILogger<InvoiceController> _logger;

    public InvoiceController(
        IInvoiceServices invoiceServices, 
        ILogger<InvoiceController> logger,
        IMapper mapper)
    {
        _invoiceServices = invoiceServices;
        _logger = logger;
        _mapper = mapper;
    }
    ...
}
Nota: aunque en este post estemos hablando de controladores ASP.NET Core MVC, las ideas que vamos a comentar aquí son también aplicables a ASP.NET MVC "clásico" e incluso a otro tipo de frameworks que comparten los mismos conceptos.
martes, 23 de julio de 2013
ASP.NET MVCLas novedades de Unity 3 no acaban en la inclusión del soporte directo para ASP.NET MVC, o en la introducción de convenciones para facilitarnos el registro de componentes, no. La extensión específica para MVC incluye otra característica muy demandada por los desarrolladores, que es la capacidad de realizar inyección de dependencias en filtros (action filters).

En este post vamos a ver cómo está construida, y cómo podemos usarla en nuestras aplicaciones.
martes, 16 de julio de 2013
Microsoft patterns & practicesSin duda, las convenciones están de moda. Cualquier framework actual que se precie trae su propio conjunto de convenciones, que no son sino una serie de reglas predefinidas, normalmente de carácter opcional, cuyo cumplimiento evitará que tengamos que tomar decisiones, evitará que cometamos errores, y, normalmente, aumentarán nuestra productividad.

Pues bien, comentaba hace poco que una de las sorpresas que acompañaba a la nueva versión de Unity, el Contenedor de Inversión de Control creado por el equipo de Patterns & Practices de Microsoft, es precisamente la posibilidad de usar convenciones a la hora de registrar asociaciones entre interfaces y clases de nuestro sistema, lo cual nos vendrá de fábula en muchas ocasiones.
martes, 18 de junio de 2013
ASP.NET MVC
En este tercer y último post de la serie (ir al primero o segundo) , vamos a ver una última técnica para realizar inyección de parámetros a acciones ASP.NET MVC que, aunque aporta menos a la hora de comprender las misteriosas interioridades del framework, es ciertamente mucho más cómoda y práctica en caso de que deseemos aplicar esta técnica.
martes, 11 de junio de 2013
ASP.NET MVCEn el primer post de la serie, vimos rápidamente en qué consiste la inyección de parámetros como fórmula para suministrar dependencias a una acción ASP.NET MVC, y realizamos una implementación sustituyendo unas pequeñas piezas del framework llamados action invokers que, como su nombre indica, son los responsables de invocar las acciones solicitadas por el usuario.
miércoles, 5 de junio de 2013
ASP.NET MVCNo hace demasiado tiempo describíamos por aquí cómo desacoplar controladores ASP.NET MVC mediante el uso de Inyección de Dependencias. En este caso, como en otros que hemos tratado, se hacía uso de uno de los “sabores” de esta técnica, que consiste en suministrar como parámetros al constructor de una clase todos aquellos componentes de los que depende para su funcionamiento. Sin embargo, esta no es la única forma de usar inyección de dependencias; hay otros métodos, quizás menos usados, como la inyección de propiedades o la inyección de parámetros en métodos que pueden ser interesantes en algunos casos y que, como mínimo, vale la pena conocer.
martes, 14 de mayo de 2013
ASP.NET MVCHasta ahora, los desarrolladores que queríamos usar Unity con ASP.NET MVC teníamos que recurrir a triquiñuelas o componentes no oficiales, como Unity.MVC3. No es que fuera especialmente incómodo ni que tuviera contraindicaciones, pero la verdad es que no dejaba de resultar curioso que no existieran adaptadores específicos “oficiales” para tecnologías tan difundidas como ASP.NET MVC, o WebAPI.

Pues bien, desde hace unas semanas tenemos disponible la versión 3.0 de Unity, que ha venido acompañando también a la reluciente versión 6 de la Enterprise Library. Como sabemos, esta creación del equipo de Patterns & Practices de Microsoft contiene un conjunto de componentes reutilizables llamados “application blocks” que resuelven problemáticas comunes en el desarrollo de sistemas, como logging, tracing, acceso a datos, gestión de excepciones y otras, incluyendo por supuesto inyección de dependencias e inversión de control.

En este post vamos a ver cómo podemos usar fácilmente esta nueva versión de Unity en nuestras aplicaciones ASP.NET MVC y algunas de las novedades que ofrece para este tipo de sistemas.
martes, 5 de febrero de 2013
ASPNETMVCHace poco, en el post donde trataba la inyección de dependencias y desacoplamiento de Hubs de SignalR, el amigo Maxxx comentaba que podría estar bien ver cómo podríamos emplear las mismas técnicas con ASP.NET MVC.

Y ciertamente, me ha parecido muy interesante porque es un escenario que encuentro habitualmente en empresas de desarrollo: comprenden los beneficios de reducir el acoplamiento entre componentes, pero les parece algo demasiado complejo como para aplicar en su día a día porque desconocen cuáles son y cómo usar las herramientas de que disponemos para conseguirlo.

Por tanto, en este post vamos a ver, paso a paso y de forma totalmente práctica, cómo evolucionar desde un controlador MVC fuertemente acoplado a clases del modelo hasta otro totalmente desacoplado usando inyección de dependencias y contenedores de inversión de control.

Y aunque las técnicas y ejemplos que mostraremos están muy enfocados a controladores MVC, los conceptos tratados son aplicables en cualquier tipo de tecnología y arquitectura.
miércoles, 16 de enero de 2013
imageCuando estamos implementando Hubs de SignalR, podemos encontrarnos fácilmente con que éstos necesitan utilizar componentes externos para llevar a cabo su tarea. Por ejemplo, es bastante probable que un servicio en tiempo real proporcionado por un Hub tenga que utilizar una clase de servicios o cualquier otro componente externo de una aplicación, como en el siguiente código:
public class MyHub: Hub
{
    public Task sendMessage(string text)
    {
        using (var services = new LogServices())
        {
            services.Log(Context.ConnectionId, text);
            return Clients.All.receiveMessage(text);
        }
    }
}
martes, 17 de abril de 2012
La programación web tradicional, basada en el modelo de petición-respuesta de página completa, no requería demasiado código en cliente más allá que el necesario para realizar validaciones y lógica de presentación simple: ¿para qué complicarnos en cliente si podíamos hacerlo todo en servidor?
miércoles, 25 de enero de 2012
La inyección de dependencias es uno de esos conceptos rodeados de misterio que parecen reservados a gurús, arquitectos, y otros profesionales de gama alta, y aplicables exclusivamente en proyectos mastodóndicos.

Y nada más lejos de la realidad: DI se basa en principios relativamente simples, e incluso diría intuitivos, para lograr evitar el acoplamiento entre componentes, es aplicable en todo tipo y tamaño de aplicaciones, y por tanto todas ellas pueden beneficiarse de las ventajas que aporta, como la simplicidad, mantenibilidad, extensibilidad, o facilidad para la realización de pruebas unitarias.
lunes, 16 de noviembre de 2009

¡Programadiseñadores al poder! Ya sabemos lo que suele ocurrir cuando los programadores diseñamos interfaces de usuario ;-). Para seguir profundizando en este curioso e inevitable fenómeno, Ian Voyce ha publicado hace unas semanas el divertido post The 7 signs your UI was created by a programmer, en el que recoge pistas que nos ayudarán a determinar si el interfaz de la aplicación que usamos a diario está creado por un diseñador experto en usabilidad, o ha sido el propio desarrollador el encargado de dichas tareas.

Bueno, en realidad se trata más bien de una lista con malos hábitos en el diseño de interfaces, y no necesariamente creados por programadores, pero ciertamente me he reconocido en alguno de los puntos y me han hecho gracia. Los cito y comento a continuación:

  • Iconos de exclamación en cuadros de diálogo
    Efectivamente, cuando incluimos una exclamación en un cuadro de diálogo no pensamos en que es posible que el usuario vea el mensaje 50 veces al día, con lo que dejaría de ser ese mensaje asombroso y puntual que pensamos en un principio. Hoy en día, muchas aplicaciones utilizan un tono mucho más neutral y cercano para enviar mensajes al usuario.

  • Mensajes con dobles negaciones en cuadros de diálogo, del tipo “¿Seguro de que no quieres perder tus cambios?” -- Hmm… sí… digooo, no…  También son muy propias construcciones más complejas de la cuenta, paradójicas o inesperadas, como “Su mensaje no se ha enviado, ¿desea descartarlo?”, que ponen a prueba los reflejos de cualquier usuario.

  • Orden de tabulación inexistente, o incorrecto, que fuerzan a que la navegación se realice exclusivamente a golpe de ratón. Y especialmente en aplicaciones de entrada masiva de información, el cambio de teclado a ratón y viceversa es terrible. Y paraGroupboxes para todo.. porque mola hacernos conscientes de ello, nada como dar vacaciones un rato al animalito y ver lo bien que manejamos determinadas aplicaciones.

  • Groupboxes rodeándolo todo… porque hay sitios donde queda bonito, aunque no esté agrupando nada ;-). Me confieso: durante años, he rodeado de groupboxes todo lo que se me ponía por delante, porque me parecía más agradable a la vista. Ahora lo estoy dejando ;-)

  • IconoIconos creados en el IDE, je, este es otro de mis puntos fuertes: soy un fiera diseñando iconos desde el editor de Visual Studio. El problema es que, a pesar de lo orgulloso que estoy siempre de mis creaciones artísticas, no quedan bien e incluso introducen un cierto tufillo a cutre en las aplicaciones.

  • Utilización de grids, debido a lo que llama Voyce “la enfermedad de considerar que Excel es lo máximo en diseño de interfaces de usuario”, que fomenta la creación de rejillas con controles de lo más potentes y variopintos en las filas de datos (calendarios, gráficos, etc.).

  • Message Boxes no implementados, el equivalente en los interfaces de usuario a los TODO en el código fuente :-DD. Buena analogía. Algo parecidos serían los mensajes del tipo “Este mensaje no debería aparecer nunca” que alguna vez he encontrado por ahí, auténticos actos de rebeldía contra sus respectivos creadores.

  • Uso excesivo de cuadros de diálogo, incluso en situaciones en las que perfectamente podríamos obviarlos por no ofrecer información útil para el usuario, que no va a poder entender, o donde no se requieren decisiones por su parte.

    Los componentes necesarios han sido detectados. Accediendo...Esto es algo muy frecuente de ver. Por ejemplo, el otro día accediendo a una aplicación web para la que es necesario contar con certificado digital, me saltó la alerta que muestro a la derecha:

    Sí, probablemente los componentes Java necesarios para la autenticación y firma electrónica hayan sido detectados con éxito, pero… ¿realmente era necesario interrumpir mi navegación para informarme de ello? ¿Un usuario, sabrá interpretar el mensaje? Y en cualquier caso, ¿le aporta algo? No sé, no sé… me da que es un alert() creado por un desarrollador durante las pruebas y que al final se quedó ahí para la posteridad.

Hasta aquí las citadas en el post original, aunque siguiendo en la misma línea, puedo añadir algunas más de propia cosecha:

  • Cuadros de diálogo con mensajes y botones inconsistentes. Mensajes del tipo “¿desea cancelar la operación?” en cuyo pie aparece un botón “Aceptar” y otro “Cancelar” siempre me dejan pensando un rato. Si pulso aceptar, ¿estoy aceptando la cancelación, o justo lo contrario?… Muchas veces, parece que sólo podemos confiar en el azar.

  • Cuadros de mensaje con demasiados (o demasiados pocos) botones. No siempre atendemos a la Ley de Hick, que nos dice que “el tiempo que se tarda en tomar una decisión aumenta a medida que se incrementa el número de alternativas”, y eso nos lleva a crear cuadros de diálogo con muchos, demasiados, botones que el usuario debe estudiar.

    Y justo en el lado contrario, pero igualmente desconcertantes, son los cuadros de diálogo de introducción de datos sin ningún botón de aceptación, en los que su cierre (con la X de la esquina superior) implica el salvado de datos.

  • Interfaz descuidado. Y no hablo de bonito o feo, términos bastante subjetivos, sino de descuidado: controles sin alinear, con tamaños no proporcionales al contenido pretendido, sensación de desorden, faltas de ortografía… Esto no es un problema de interfaces creados por desarrolladores, sino creados por gente que no pone el más mínimo cariño en lo que hace, independientemente de su puesto de trabajo.

  • Interfaces monocromos, mi especialidad. Como inútil reconocido en temas de diseño, me considero absolutamente incapaz de crear algo medio aparente con más de un color (eso sí, empleando distintas tonalidades ;-)). Nunca he entendido la compleja lógica que hay detrás del “eso no pega con aquello”, que algunos/as parecen dominar de serie.

  • Controles con trastorno de personalidad. Un clásico es encontrar un grupo de checkboxes actuando como un grupo de radios. A ver, si sólo vamos a poder elegir una de las opciones, ¿por qué no usamos directamente el control específicamente ideado para ello? ¿Y un desplegable con las opciones "Activar" y "Desactivar"? ¿No sería más claro poner un checkbox?

Artículo original: The 7 signs your UI was created by a programmer

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

martes, 12 de mayo de 2009

yUML Tobin Harris ha puesto en marcha un curioso e interesante servicio, al que ha denominado yUML, cuyo propósito es facilitar la generación al vuelo de diagramas UML a partir de una concisa descripción expresada en un sencillo lenguaje específico.

Pero además de la generación automática del diagrama UML, que ya tiene mérito de por sí, llama la atención que esto puede realizarse desde una etiqueta (X)HTML <img> a la que se le envía la especificación como parámetro, generándose en tiempo real una imagen con el diagrama correspondiente. Por ello, está especialmente indicado para autores de blogs, wikis o contenidos web que deseen introducir muy fácilmente estos diagramas en sus creaciones.

En los siguientes ejemplos se muestran la especificación y la imagen generada de un diagrama de clases y uno de casos de uso, respectivamente. Como podréis comprobar, la especificación es bastante legible directamente.

Diagrama de clases

Especificación: [Company]<>-1>[Location], [Location]+->[Point]

image

Código fuente para su inserción en una página:

<img src="http://yuml.me/diagram/class/[Company]<>-1>[Location], [Location]+->[Point]" />

Estilo informalUna curiosidad es que si en la dirección insertamos la palabra “scruffy”, el sistema generará un diagrama como si hubiese sido dibujado a mano, en un estilo mucho más informal:
<img src="http://yuml.me/diagram/scruffy/class/[Company]<>-1>[Location], [Location]+->[Point]" />

Diagrama de casos de uso

Especificación: [User]-(Login), [User]-(Logout), (Login)<(Reminder), (Login)>(Captcha)

image

Código fuente para su inserción en una página:

<img src="http://yuml.me/diagram/usecase/[User]-(Login), [User]-(Logout), (Login)<(Reminder), (Login)>(Captcha)" />

Si prefieres simplemente descargar el diagrama para subirlo a tu web, opción bastante prudente hasta que se pueda confiar en la fiabilidad y disponibilidad del servicio, desde el mismo sitio web del producto podemos generar la imagen introduciendo la especificación textual; a partir de ahí podremos copiarla y pegarla sobre nuestra herramienta de edición, o salvarla en nuestro equipo para enviarla a su ubicación definitiva.

Si bien todavía yUML está en pruebas y es algo limitado (sólo soporta diagramas de clases y de casos de uso), me ha parecido muy interesante tanto la idea como la implementación del servicio.


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

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/.
miércoles, 14 de noviembre de 2007
Pues no, esta entrada no trata de los diseños líquidos habituales en el mundo de la maquetación web, aunque podría parecer lo contrario. El término interfaz se utiliza en su acepción relativa a la orientación a objetos, y la fluidez se refiere a la continuidad en el movimiento de instancias entre distintas llamadas a métodos.

En pocas palabras, el uso de interfaces fluidos es un estilo cada vez más frecuente de programación, también llamado a veces "encadenamiento de métodos" (method chaining), que promueve la eliminación de código innecesario y engorroso para la realización de tareas frecuentes, sustituyéndolo por una secuencia natural, intuitiva y fluida de instrucciones que se encadenan de forma casi mágica.

Pero veámoslo con un ejemplo. Y ojo, que aunque lo codificaremos en C#, el concepto es perfectamente válido para otros lenguajes orientados a objetos, salvo por los aspectos sintácticos.

Imaginemos la clase Calculator, con un diseño como el mostrado a la izquierda, que es capaz de mantener un único valor (entero) y que soporta cinco operaciones: Get (para obtener el valor actual de la calculadora), Set (para establecerlo), y Add, Substract y Multiply (para sumarle, restarle y multiplicarle un valor respectivamente).

La forma habitual de operar con esta calculadora para obtener el resultado de un cálculo sería algo parecido a:
  Calculator calc = new Calculator();
calc.Set(0);
calc.Add(10);
calc.Multiply(2);
calc.Subtract(4);
Console.WriteLine("Resultado : " + calc.Get());
 
Como podemos observar, para realizar unas operaciones muy simples hemos necesitado demasiadas líneas de código, y además bastante repetitivas.

Veamos ahora cómo utilizando la técnica de interfaces fluidos podemos dejar este código en:
  Console.WriteLine("Resultado: " +
new Calculator().Set(0).Add(10).Multiply(2)
.Substract(4).Get()
);
 
El truco consiste en hacer que métodos que normalmente no devolverían ningún valor (métodos void, como los de la clase Calculator anterior) retornen referencias hacia el propio objeto, es decir, acaben con un return this;. De esta forma, la llamada a la función podrá ir seguida de otra llamada sobre el mismo objeto, que a su vez lo devolverá para el siguiente y así sucesivamente. Y de ahí el término "fluido": fijaos en el ejemplo anterior como la instancia de Calculator que es retornada por el constructor se utiliza directamente en la llamada Set(0), que a su vez la devuelve y es utilizada por Add(10)... ¿no es eso fluir, aunque el término suene algo poético?

Otro ejemplo, donde se utiliza la misma técnica, pero esta vez combinando instancias de distintas clases (fijaos que nada impide en la mayoría de lenguajes dividir las líneas de código como se muestra, facilitando así la lectura):

new Surface()
.Clear()
.Fill("white")
.CreateText()
.SetMessage("Hi, all!")
.SetColor("blue")
.Draw()
.CreateCircle(100, 100, 10)
.Fill("green")
.Draw()
.Border("red")
.Draw()
 
Este código muestra tres aspectos importantes. Primero, que es posible crear un pseudo-lenguaje de programación utilizando esta técnica, de hecho los fluent interfaces son muy utilizados en los DSL (Lenguajes Específicos de Dominio). En el ejemplo se puede intuir un lenguaje para el dibujo de figuras sobre una superficie.

Segundo, que la devolución de los métodos no tiene por qué limitarse a una única clase. En el código anterior, los métodos CreateText() y CreateCircle() retornan referencias a nuevas instancias de clases que representan estas figuras, que también hacen uso de interfaces fluidos. Los métodos Draw() de ambas retornan de nuevo una referencia a la instancia de la superficie (Surface) sobre la que están dibujando.

Tercero, se deja entrever la dificultad de desarrollar clases que permitan utilizar esta técnica, pues cada método debe devolver una referencia al objeto oportuno para facilitar el encadenamiento con el método posterior. Una elección incorrecta de la clase de devolución hará que la fluidez se rompa.

Finalmente, decir que los interfaces fluidos no son algo nuevo. Hay quien habla de su uso en SmallTalk antes de la década de los noventa (!), aunque el concepto se extendió a partir de la inclusión de una entrada en la Bliki de Martin Fowler comentándolo hace un par de años.

Hay también quien opina que los interfaces fluidos son algo más que el encadenamiento de métodos, que también existe en un código como name.Trim().ToUpper(), pues aporta una interfaz comprensible e intuitiva.

En cualquier caso, hace algún tiempo que esta técnica me llamó la atención y cada vez lo veo utilizado en más ocasiones, especialmente en contextos de frameworks y para implementar DSLs (como Quaere).
domingo, 7 de octubre de 2007
Vía CodeBetter llego a un interesante post de Jeffrey Palermo donde cuenta que Scott Guthrie, de la división de desarrolladores de Microsoft, anunció y demostró el pasado 5 de ocubre en el contexto de las conferencias Alt.Net un framework MVC para ASP.NET en el que los de Seattle llevan tiempo trabajando.

Algunas de las características que describe, aunque muy someramente, de la nueva plataforma son:
  • Soporte nativo para TDD (¿qué diantres es esto?) en los Controladores.
  • Vistas basadas en ASPX, sin viewstate ni postbacks.
  • Soporte para enlaces otros motores como MonoRail.
  • Soporte para contenedores IoC (¿ein?) y DI (¿y esto qué es?).
  • Control absoluto sobre las URLs y la navegación. Éstas seguirán un modelo común, algo similar a: "/Ruta/Acción/Param1/Param2... ", que se mapearán hacia la acción oportuna del Controlador asignado.
  • Separación de la capa de negocio de la de presentación, como buen MVC.
  • Integración total en ASP.NET, sin traumas. De hecho, la llegada de esta tecnología no implica, ni por asomo, la desaparición de los conocidos y utilizados Webforms actuales, ambos modelos podrán convivir incluso en la misma aplicación.
  • Soporte para lenguajes estáticos como C++, C#, o VB.Net y dinámicos como Javascript, Ruby o Python.


Se espera una CTP pública hacia finales de año, y se espera la versión definitiva como add-on para el próximo Visual Studio 2008. Mínimo primavera-verano, por tanto.