viernes, julio 31, 2009

Plugin Pattern II

En la practica cotidiana existen muchas oportunidades en la que se desea extender la funcionalidad de un sistema, tal sea para implementar de otra forma un funcionalidad existente como agregar una que no exista.

Una alternativa de solución

Usando herencia se puede implementar de otra forma una funcionalidad existente respecto a una clase original.

Por ejemplo en un sistema simple de validación de datos de entrada en donde tenemos que validar los campos tipo string, valores requeridos y uno alfanumérico con un formato predefinido, se podría implementar de la siguiente forma




La clase ValidateEngine permite validar todos los datos de entrada, obviamente esta implementación está muy simplificada pues se debería agrega toda la lógica de validación de datos de entrada de un determinado formulario del front end de la aplicación.

Esto trae como problema que se deba implementar lógica para validar tipo de datos, longitud, expresiones regulares (por ej para un ISBN) y valores requeridos, es decir una implementación con una muy baja cohesión.

Una mejora sería que la clase ValidateEngine sea una clase abstracta del cual se deba heredar para implementar cada tipo de validación.


De esta forma tenemos diferentes validaciones implementadas en clases separadas, lo que permite que cada una de ellas tenga alta cohesión.

Para utilizar este modelo podríamos aplicar el patrón estrategia [3] tal como muestra la figura.


Aplicando este patrón tendríamos un sistema más flexible, por ejemplo en C# se podría implementar de la siguiente manera:


http://codepaste.net/ocb7gy

Como resultado de la ejecución de este ejemplo obtenemos la siguiente respuesta



Si deseamos agregar una nueva forma de implementar una validación deberíamos heredar otra clase y configurarla en la clase de contexto.

Esta solución es mucho mejor que utilizar una sola clase para todo pero tiene el gran inconveniente que para agregar nuevas funcionalidades se debe crear una clase heredada lo que hace el sistema poco flexible.

¿Cómo mejoramos está solución?

Supongamos que deseamos crear un sistema en donde se pueda expandir su funcionalidad pero en forma dinámica, configurable y en tiempo de ejecución, la solución mencionada ya no satisface ese requerimiento.

La implementación del patrón Plugin permite agregar funcionalidad a nuestro sistema en forma dinámica utilizando configuración o un estándar de implementación predefinidos. Los módulos que agregan funcionalidad al sistema se denominan plugins.

Ejemplos de la vida real

Este patrón es muy utilizado en múltiples sistemas como sistemas multimedia que permiten agregar en forma muy simple nuevos módulos para edición de audio, transformación entre formatos, skins, analizadores de espectro etc.

En el mundo del desarrollo este patrón se aplica mucho, el más claro ejemplo es el IDE Eclipse,

la arquitectura de este entorno de desarrollo está exclusivamente basada en plugins, pues por si solo no tiene funcionalidad significativa más que proveer un entorno que permite agregarlos [4].

En sus orígenes fue creado como un entorno de desarrollo para Java, pero actualmente se puede usar para muchos otros lenguajes (C++, Python, PHP, Perl, Intel C++ para Linux, Cobol, ABAP , Google apis etc.), también se puede usar para modelado (UML, Base de datos, Data Warehouse etc.), herramientas de soporte al desarrollo como gran cantidad de editores diferentes, clientes Subversion, para soporte de programación en pares distribuida (Distributed XP) , comerciales como herramientas para el BPM de Tibco, generación de interfases para el broker de Software AG etc , al día de la fecha existen más de 1200 plugins publicados.

Visual Studio .Net tiene una api que permite crear plugins (addons), esta api esta implementada en System.Addin. La versión para desarrolladores del Visual Studio Team System posee plugins para revisión de código (basado en el FXCop) para pruebas unitarias, para análisis de performance, cobertura de código, control de fuentes, implementación etc.

Se pueden utilizar plugins comerciales o bien integrarlos al Visual Studio mediante un desarrollo especial.


Veamos una aplicación práctica

En el siguiente ejemplo vamos a extender el sistema de validación para aplicar el patrón Plugin, en este caso se va a utilizar configuración xml y reflection para poder agregar en forma dinámica nuevos mecanismos de validación.

Las nuevas validación estarán implementadas en assemblies separados y usarán el patrón Separate Interfase [5] para implementar la interfase IValidate que está en el assembly Context.

Cada implementación de una validación diferente se implementa en assemblies separados y mediante configuración se agregan como plugin al sistema original.


En este ejemplo usamos el siguiente archivo de configuración.


<ValidatePluginsConfigFile>

<plugins>

<plugin>

<name>ValidateRegularExpresions name>

<fullName>ValidationExample.ValidateRegularExpresions,Version=1.0.0.0,Culture=neutral,

PublicKeyToken=3d10efd7d0a5d829fullName>

<type>ValidationExample.ValidateRegularExpresions.ValidateRegularExpresionstype>

<active>trueactive>

plugin>

<plugin>

<name>ValidateStringsname>

………………………...

plugin>

………………………...

plugins>

ValidatePluginsConfigFile>


Por lo tanto podemos agregar nuevos nodos plugin por cada componente de validación y el programa automáticamente los invocará.

Un poco más de código

En el siguiente fragmento de código se muestra como se puede ejecutar en forma dinámica un método de un assembly externo usando reflection y un poco de lógica para leer la configuración


http://codepaste.net/k9bih8

Considerando que para que funcione correctamente los plugins deben estar en la GAC el resultado de la ejecución de este programa es idéntico al caso anterior.


Código

El código de ejemplo mostrado es parcial , de este link pueden bajar el proyecto completo para probar en sus maquinas, fue creado con el Visual Studio 2005 SP1.

Conclusión

El patrón plugin es muy útil para extender la funcionalidad de un sistema de forma tal que podemos construir una sistema base que permita agregar plugins y luego esos plugins pueden ser construidos por terceros, esta filosofía la usa el IDE Eclipse ya mencionado y también es muy utilizada en el navegador Firefox (Firefox extensions) y el Chrome de Google.

También se usa en sistemas comerciales cuyos plugins requieren el pago de licencias adicionales al sistema principal.

Como desventaja se debe considerar el aumento del complejidad para permitir el agrego de los plugins en forma simple por un usuario que no tiene porque conocer los detalles del sistema principal.

Como en muchos casos para hacer un sistema que permita utilizar este patrón se debe considerar en el diseño original de la arquitectura del mismo.


Bibliografía


[1] Pattern to Enterprise Applications Architecture - Plugin Pattern ,http://martinfowler.com/eaaCatalog/plugin.html


[2] Log4Net Framework , http://logging.apache.org/log4net/index.html


[3] Erich Gamma et at, “Design Patterns: Elements of Reusable Object-Oriented Software” (Addison-Wesley Professional Computing Series) , pag


[4] Eclipse plugin central web site, http://www.eclipseplugincentral.com/


[5] Erich Gamma et at, “Design Patterns: Elements of Reusable Object-Oriented Software” (Addison-Wesley Professional Computing Series) , pag


[6] Pattern to Enterprise Applications Architecture - Separate Interface pattern, http://martinfowler.com/eaaCatalog/separatedInterface.html



martes, julio 21, 2009

Plugin pattern

Como inicio de una seria de articulos sobre patrones empiezo con uno muy relacionado con mi ultimo post,

Patron Plugin.

“Links classes during configuration rather than compilation.” (Fowler, POEAA, p.4990)[1]

El patrón Plugin permite agregar funcionalidad a nuestro sistema en forma dinámica utilizando configuración, por lo general se usan en frameworks que permitan agregar nuevas formas de implementar funcionalidades ya existente, por ejemplo el log4net [2] permite agregar nuevas implementaciones para los adaptadores a los repositorio donde registrar los mensajes de Log (IAdapter) o formato de los mensajes (IFormater).
Otro sistema que usaba el patrón plugin fue el EDRA de P&P, este framework implementaba el patrón Pipes & filters [3] en donde se podían agregar handlers que ejecuten determinada funcionalidad antes de ejecutar una acción personalizada, después o en ambos casos, ejemplo de un handler de “antes” sería un handler de autenticación, de “después” un handler de validación del formato de respuesta y para ambos casos un handlers que agregue información adicional al mensaje de entrada y al de salida a la acción, por ejemplo para medir tiempo transcurrido entre le ejecución de la llamada a la acción y la recepción del mensaje de respuesta.

Otro ejemplo de implementación del patrón plugin es cuando se usa en la implementación del patrón Chain and Responsability [4], básicamente en este patrón participan un conjunto de objetos de comandos y una serie de objetos de procesamiento, mediante configuración se pueden agregar en forma dinámica nuevos objetos de comandos.
Para implementar este patrón el sistema a extender debe disponer de un mecanismo de configuración donde se puedan agregar los nuevos componentes que implementan interfases definidas para determinadas funcionalidades del sistema.
Siguiendo con el ejemplo de log4net el archivo de configuración de la figura se indica el mecanismo que utiliza este Framework para aplicar el patrón plugin.

En este ejemplo se tienen 3 appenders, uno que envía los registro de Log a la consola, el segundo a un archivo que puede llegar a un máximo de 100kb (y luego se genera otro) y un aprender personalizado que envía los logs a otro repositorio no contemplado en la configuración estándar de log4Net (por ej MSMQ o WCF).



Mas info

[1] Pattern to Enterprise Applications Architecture - Pluging Pattern ,http://martinfowler.com/eaaCatalog/plugin.html

[2] Log4Net Framework , http://logging.apache.org/log4net/index.html

[3] Enterprise Integration Patterns – Pipes & Filters , http://www.enterpriseintegrationpatterns.com/PipesAndFilters.html

[4] Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley Professional Computing Series)

lunes, julio 13, 2009

Logging and trace.

En este post subo información sobre unos de los servicios cross más importantes a considerar en el diseño de un arquitectura empresaria, que es logging y trace de los eventos y errores que surgan en la aplicación. Se analizan las carácteristicas más importantes, los anti patrones, las buenas prácticas y los patrones de diseño aplicados. Al final se indican algunos frameworks de logging para diferentes plataformas y lenguajes de programación.


Objetivo:
Registrar eventos de relevancia para utilizarlos en procesos de auditoria o troubleshuting post mortem.
Es una herramienta muy útil en ambientes productivos donde es imposible depurar con herramientas de desarrollo.
Los eventos pueden ser información de depuración o errores ocurridos en la aplicación.

Características deseables de un sistema de logging:
Configuración de niveles de log

Formateo de eventos
Agregado de información adicional en publicación de eventos
Logging asincrónico
Logging confiable
Logging centralizado
Configuración jerárquica y dinámica
Publicación a múltiples destinos
Aplicación para visualizar y analizar los eventos.


Anti patrones:


Todo en un mismo mensaje: Todo junto en un mismo archivo es muy dificil de analizar.

Registro de datos incompletos:Registrar lo que sirva para, ni más ni menos.

Log sin formato o formato no consistente: Si el log no está estructurado, su analisis se hace muy dificil.

Entradas multi línea: Complica el procesamiento de log para pasarlo a una DB o aplicación que muestre la información en forma amigable.


Registrar mensajes relacionados a un mismo contexto en varias líneas: Muy dificil de analizar lo que pasó en un determinado contextode ejecución.


Buenas prácticas:


Registrar los logs en repositorio con formato, esto facilita en análisis de los logs registrados.

Separar los mensajes en diferentes destinos dependientes de la audiencia que los usa, por un log de auditoria puede tener muchas más información de la necesario para resolver un problema que ocurrió en la aplicación.

Registrar las acciones antes de que ocurran



Evitar que los archivos de logs sean muy grandes, se recomienda archivarlos y crear uno nuevo.

Registrar los eventos en una sola línea, es más fácil de analizar y filtrar. Si la información tiene formato complejo se recomienda usar xml.

Usar formato consistente en un mismo archivo.


Patrones utilizados


Estrategia:

Se puede usar para seleccionar la forma en que el sistema de log registra los eventos y errores.




Pipes and filters:

Se usa para tener un mecanismo extensible y de bajo acoplamiento para agregar información contextual y codificación a los mensajes antes de enviarlo al repositorio de logging.




Consideraciones de implementación:


Por lo general son frameworks muy flexibles, que soporta multiples fuentes y destinos, por lo tanto para implementarlo adecuadamente se requiere un buen análisis de que funcionalidades usar y cual es su mejor forma de implementar.

Otros frameworks de logging e instrumentación.

Java:
log4J
y de este log4Net, log4PHP, log4JavaScript, log4C, log4VB, log4SQL, log4PLSQL etc

AJAX:
log4javascript
, JSLog, Lumberjack, log4Js, jsTracer

Unix like: syslogd (nativo).

Bibliografía


Carácteristicas
http://gojko.net/2006/12/09/logging-anti-patterns/

Frameworks
Pattern & Practices Logging Application Block
Apache Log4Net

Patrones
http://www.dofactory.com/Patterns/PatternStrategy.aspx
http://msdn.microsoft.com/en-us/library/ms978599.aspx


domingo, julio 05, 2009

Golpe en Honduras

Este no e un tema relacionado con Arquiectura de software , pero aprovecho este espacio para repudiar el golpe de estado en el pais hermano de Honduras.
Es importante deterner este golpe, para evitar que otros los quieran imitar.
Me parece muy bien el repudio internacional, y del gobierno argentino.
Nosotros que vivimos casi toda nuestra vida en democracia, y muchos de mis colegas nacieron en democracia deben saber que no debe existir mas golpes de estados en ningún país que pueda desastibilizar la región.