Angel Hernández

Inyección de políticas, punteros a función y por qué prefiero .NET en vez de Java

Ayer en la tarde venía en el tren hacia mi casa, cuando de repente se me ocurrió la idea de escribir algo acerca de inyección de políticas, punteros a función y mi preferencia de .NET antes que Java. Primero, permítanme comenzar con inyección de políticas, es un término que se escucha comúnmente en conversaciones de desarrolladores, pero ¿qué significa ó de que trata? En pocas palabras lo podríamos definir como “Una técnica que se está popularizando con la adopción de la programación orientada a aspectos (AOP), la cual brinda distintos mecanismos para cambiar el comportamiento de objetos de negocios y otras clases a través de la aplicación de políticas, facilitando así la implementación común de conceptos como validación, registro de eventos, manejo de excepciones y caché y muchas más”.

En AOP, se utiliza el término concepto para referirse a una tarea ó característica de una aplicación. Los conceptos claves son características únicas de una clase u objeto, por ejemplo, una clase para conectarse a una BD ó serializar un objeto a disco. Las tareas comunes para una clase u objeto se denomina “funcionalidad transversal” (en inglés, cross-cutting), que en muchas oportunidades un mal manejo de estas trae como consecuencia código duplicado y difícil de mantener sin mencionar aplicaciones poco confiables.

La inyección de políticas fue introducida en .NET por Microsoft con la versión de 3 de su librería de aplicaciones empresarial, la cual trae consigo un componente de inyección de políticas que se integra con los otros componentes de dicha librería. La última versión se puede descargar acá

Sin embargo, me gustaría compartir con ustedes la idea ó el principio de detrás de la “inyección de políticas”, si ustedes son como yo que prefieren diseñar y desarrollar todos los componentes de una aplicación entonces este post puede ser de utilidad.

En mi humilde opinión tenemos dos posibles maneras de “inyectar” bien sea usando Generics y un poco de Reflection ó a través del uso de Callbacks (delegados), a continuación describiremos las dos:

1-. Haciendo uso de Generics: Generics fue introducido en .NET 2.0 y nos ofrece la posibilidad de escribir código más “genérico” esforzando la tipificación de los datos, es decir, no más casting a Object para conseguir reutilización múltiple. Supongamos que tenemos la siguiente clase

 

clip_image002

La cuál implementa la interfaz ISample que posee un sólo método PerformAction que arroja una excepción si el segundo actual es par (esto para simular que algo falla con la ejecución de dicho método), nótese que no tenemos manejo de excepciones en ese método. Ahora supongamos que tengo un montón de clases que implementan la misma interfaz pero con la misma carencia de manejo de excepciones, ¿en ese caso qué puedo hacer? Sí tomamos en consideración las definiciones de concepto y funcionalidad transversal, podemos entonces decir: Tengo distintos conceptos (porque aunque la interfaz implementada es común su implementación es distinta) pero a su vez tengo funcionalidad transversal, es decir, todas mis clases que implementan la interfaz ISample necesitan un manejo de excepciones.

Una vez dicho eso, obsérvese el siguiente fragmento de código

clip_image004

Es una clase genérica a la cual restringimos su uso para objetos que implementen la interfaz ISample además que su utilización requiere una instancia de objeto, en el constructor a través de Reflection obtenemos información de la clase usada con la clase genérica, es decir, el objeto al cuál le aplicaremos la “política”. La clase genérica tiene sólo un método llamado Execute que invoca ó llama a su vez al método PerformAction de la clase que implementa ISample y agrega manejo de excepciones la cual no existía en la implementación original.

 

La manera de utilizarlo desde el cliente ó nuestra aplicación sería así

clip_image006

Nótese que no tuve que modificar el código original sino que hago uso de otro mecanismo, en este caso “inyección de políticas” que a través de una clase genérica que actúa como proxy el cuál me permite conseguir lo que quiero, así aislando mis conceptos pero tomando en consideración la funcionalidad transversal.

2-. Haciendo uso de Callbacks: Los Callbacks, punteros a función ó delegados se refieren al mismo mecanismo de pasar código ejecutable como argumento a otro código. En la vieja escuela C/C++ podríamos conseguirlo así

 

clip_image008

Sin embargo en .NET lo hacemos así

clip_image010

Entonces la manera que podríamos lograr ó conseguir la “inyección de políticas” difiere un poco de la descrita previamente que es más limpia, adecuada, fácil de mantener y la recomendada desde mi punto de vista, porque hacemos uso de un Proxy que se comunica con la clase a la cual se le aplica la política; caso que difiere de hacerlo con un Callback como se muestra a continuación

clip_image012

La mayor diferencia como se puede notar, es que el código que pertenece a la política está del lado del cliente y no en el proxy como tal, permitiendo así repetir código y poner en riesgo el mantenimiento futuro. Podemos conseguir lo que queremos pero no es la mejor manera de hacerlo, sin embargo este segundo enfoque es realmente útil para casos en los cuales, por ejemplo quiera impersonar a un usuario para correr un fragmento de código

 

clip_image014

 

Cambiando de tema y ya casi para finalizar, una de las razones por la cual prefiero .NET en vez de Java es por el soporte y uso de Callbacks los cuales están con nosotros desde siempre y son muy útiles como el caso de la función qsort (Implementación de quicksort en el CRT) que acepta como último argumento una función que se encarga de comparar los elementos que se desean ordenar sin mencionar el poder de pasar funciones a funciones. En Java, esto simplemente no “existe” si no hay que “simular conseguirlo” a través de la implementación de interfaces (Patrón de Callback) por lo que me pregunto, ¿qué rayos es eso? Lo puedo hacer en C/C++ en código nativo y en cualquier lenguaje .NET sin implementar ningún tipo de “patrón” para así enfocarme en el requerimiento, por esta y muchas otras razones que .NET me hace más productivo lo prefiero antes que Java.

 

Saludos,

 

Angel

Comments

Efren Fuentes said:

Mi pana deberías entonces preferir C++, ya que los genéricos de .Net están basados en los templates de C++. O sea que existen desde la vieja escuela de C++.

Tampoco creo que tengan el peso suficiente para preferir un lenguaje o una plataforma determinada, si quieres realizar inyección de código de la manera más sencilla podrías hacerlo mejor con Python o Ruby.

Seguro que prefieres .Net pero no creo que sea solo por la inyección de código, debe haber miles de sutilezas por las que estas enamorado de tu plataforma. Puedes darnos algo más que nos haga pensar que debemos enamorarnos de ella? Yo sigo programando en C#, aunque ahora mis lenguajes principales son Java para aplicaciones de escritorio y Ruby para aplicaciones Web. Por que? número 1 portabilidad y segundo claridad en el código hasta hace un año decía que el mejor lenguaje que había probado era C#. ahora pienso que es Ruby.

# July 26, 2009 11:54 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)