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.
¿No estaría bien poder ignorar esos problemas y centrar nuestro código en aportar valor a nuestros clientes?
Publicado por José M. Aguilar a las 12:01 a. m.
Etiquetas: c#, inocentadas, novedades, patrones
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.
Publicado por José M. Aguilar a las 8:30 a. m.
Etiquetas: aspnetcore, aspnetcoremvc, patrones, trucos
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.
Publicado por José M. Aguilar a las 8:55 a. m.
Etiquetas: aspnetcoremvc, aspnetmvc, buenas prácticas, patrones
En este post vamos a ver cómo está construida, y cómo podemos usarla en nuestras aplicaciones.
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.
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.
Publicado por José M. Aguilar a las 9:10 a. m.
Etiquetas: aspnetmvc, autofac, desarrollo, patrones, trucos
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.
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.
public class MyHub: Hub { public Task sendMessage(string text) { using (var services = new LogServices()) { services.Log(Context.ConnectionId, text); return Clients.All.receiveMessage(text); } } }
Publicado por José M. Aguilar a las 9:45 a. m.
Etiquetas: desarrollo, javascript, knockout, patrones
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.
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 para 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 ;-)
- Iconos 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.
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 unalert()
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.
Publicado por José M. Aguilar a las 5:17 p. m.
Etiquetas: antipatrones, buenas prácticas, humor, interfaces, patrones
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.
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:
- Recibimos la petición Post con los datos que ha introducido el usuario en un formulario.
- Ejecutamos la lógica asociada a la recepción de dicho formulario, por ejemplo, grabar en la base de datos.
- 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.
- 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:
¿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
Publicado por José M. Aguilar a las 11:50 p. m.
Etiquetas: asp.net, aspnetmvc, buenas prácticas, desarrollo, patrones
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]
Código fuente para su inserción en una página:
<img src="http://yuml.me/diagram/class/[Company]<>-1>[Location], [Location]+->[Point]" />
Una 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)
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
Publicado por José M. Aguilar a las 11:05 p. m.
Etiquetas: desarrollo, diseño, dsl, patrones, servicios on-line
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 (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 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.
- 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
Ademá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.
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
Publicado por José M. Aguilar a las 11:40 p. m.
Etiquetas: .net, antipatrones, buenas prácticas, calidad, desarrollo, herramientas, patrones
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: |
|
Causas: |
|
Solución positiva: |
|
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/.
Publicado por José M. Aguilar a las 8:00 p. m.
Etiquetas: antipatrones, buenas prácticas, desarrollo, patrones, proyectos
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).
Publicado por José M. Aguilar a las 8:48 p. m.
Etiquetas: desarrollo, dsl, fluent interfaces, interfaces fluidos, patrones, programación
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.
Publicado por José M. Aguilar a las 9:10 p. m.
Etiquetas: .net, asp.net, aspnetmvc, desarrollo, frameworks, orcas, patrones, web