Thursday, August 23, 2007

Digame Patrón

Hola de nuevo

Esta ves quiero regresar a bloguear con un tema que definitivamente es de mucha importancia para todos los que tratamos de desarrollar software. Todos ya nos conocemos el tema aquel de análizar, diseñar, construir, probar... Y en cada una de estas etapas, algunos consagrados y juiciosos personajes han encontrado soluciones generales a problemas bastante específicos. Soluciones que no están restringidas a ningún lenguaje, tecnología o herramienta. Si señores, son los patrones, que nos contextualizan, nos emprobleman, pero al final nos dan una solución.
Y espero de aqui en adelante, basado en el documento "Enterprise Solution Patterns Using Microsoft .NET v2.0" de lo señores de Patterns & Practices, regalarles algunos tips de lo que encuentro ahi como lo más relevante. Acerca de esto no se ha dicho la última palabra, pero los patrones aqui expuestos son la base filosofica y metafisica de miles de aplicaciones ejecutandose en el mundo, por qué? porque nos facilitan la vida, cuando esta se vuelve un ocho en aplicaciones de clase empresarial. No siendo más espero sea de su utilidad.

Patrones para soluciones empresariales utilizando Microsoft .NET

Lo primero es pensar en que todo sistema empresarial debe concebirse simple y crecerá con el tiempo. Esto radica en que cualquier cosa simple trabaja mientras necesite ser reemplazada. La idea es encontrar patrones que sirvan a lo simple y a lo complejo en tiempos distintos. No significa que un patrón lo haga mal y el otro lo haga correctamente, significa que cada patrón se acomoda a un momento dado del proyecto. Muchos objetos en .NET ya implementan varios patrones, así que la idea es utilizarlos y no implementar el patrón desde el principio.

La idea es presentar 32 patrones que expandan varios puntos de vista, y mostrar como pueden ser integrados en una aplicación empresarial. Visualizar los patrones como un lenguaje para expresar experiencias de diseño. Los patrones proporcionan un lenguaje común a arquitectos y desarrolladores para acortar la brecha entre las dos disciplinas.

Las soluciones de negocio de clase empresarial, son a menudo extremadamente complejas y deben ejecutarse bien frente a las altas expectativas. No solo deben ser altamente disponibles y escalables de cara a lo impredecible, sino también medibles y predecibles en respuesta a requerimientos de negocio que cambian rápidamente.

Los patrones son útiles para arquitectos y desarrolladores porque:
· Documentan mecanismos simples que trabajan
· Proveen un vocabulario y una taxonomía común para desarrolladores y arquitectos
· Habilitan a las soluciones para ser descritas como combinaciones de patrones.
· Habilitan el rehúso de arquitectura, diseño, e implementación de decisiones.

Mecanismo para documentar patrones

Un patrón describe un problema recurrente que ocurre en un contexto dado y, basado en un conjunto de lineamientos, recomienda una solución. La solución es usualmente un mecanismo simple, una colaboración entre dos o más clases, objetos, servicios, procesos, hilos, componentes, o nodos que trabajan juntos para resolver el problema identificado en el patrón.

Nota. Se debe aclarar que la implementación de los patrones puede volverse compleja, y lo mostrado aquí es solo para propósitos de introducción, así que mientras más se estudian los patrones en profundidad, se pueden observar aspectos más detallados y de mayor complejidad.

Patrón Singleton

Contexto. Controlar el acceso a una clase administrando su proceso de instanciación.

Problema. Una aplicación contiene un cierto tipo de data que necesita ser globalmente accedida y mantenida. Al mismo tiempo, este tipo de data es a menudo única en el sistema. Cómo proveer una interfaz accesible a una clase, pero controlar el número de instancias dentro del sistema.

Solución. La clase en si misma es responsable de crear una instancia simple y proveer acceso global a esa instancia. Crear una clase que contiene una instancia estática del Singleton que es retornada con un método estático.

public class MiSingleton
{
private static MiSingleton miInstancia = null
private MiSingleton() {}
public static MiSingleton ObtenerInstancia ()
{
if (miInstancia ==null)
{
miInstancia = new MiSingleton ()
}
return miInstancia
}
//... Funciones provistas por MiSingleton
}

El ejemplo anterior define un constructor privado, que hace que ninguna otra clase pueda instanciar a MiSingleton. La clase contiene una instancia estática miInstancia que es retornada con el método ObtenerInstancia().

Como se puede observar, el anterior es un ejemplo muy simple, pero que muestra la implementación esencial del patrón singleton, su objetivo y toda la utilidad que puede proveer dentro de nuestras aplicaciones. Es importante aclarar que los patrones no tienen una única solución o implementación, y están pensados para ser abiertos a cada tecnología.

Patrones en niveles diferentes

Los patrones existen en niveles diferentes de abstracción. Consideremos otro ejemplo, esta ves a un nivel más alto de abstracción que el nivel de codificación:

Estamos diseñando una aplicación basada en Web, que contiene una gran cantidad de lógica de negocio y de presentación. Cómo organizar este sistema a alto nivel para que sea flexible, débilmente acoplado, y aun así, altamente cohesivo?

Una solución a este problema involucra organizar el sistema dentro de una serie de capas, con cada capa conteniendo elementos aproximadamente en el mismo nivel de abstracción. Se identifican las dependencias en cada capa y decidir por una estrategia de capas estricta o relajada. Luego, se decide si se va a crear un esquema de capas personalizado o adoptar un esquema de capas previamente documentado por otros. Supongamos que vamos a usar una estrategia de capas bien conocida, una capa para presentación, para la lógica del negocio y para el acceso a datos.

Si siempre diseñamos sistemas de este modo, estamos empleando un patrón ya existente, independiente de cualquier patrón generalizado. Aún así, hay muchas razones por la que queramos entender los patrones que apoyan esta aproximación de diseño. Podemos ser curiosos y preguntarnos por qué los sistemas frecuentemente se diseñan de esta manera, podemos buscar aproximaciones más óptimas a los problemas que este patrón no resuelve.

Patrón Capas

Contexto. Estamos trabajando, con un sistema grande y complejo, y queremos administrar la complejidad por descomposición.

Problema. Cómo estructurar una aplicación para soportar tales requerimientos operacionales, como mantenibilidad, reusabilidad, extensibilidad, escalabilidad, robustez y seguridad?

Solución. Componer la solución dentro de un conjunto de capas. Cada capa debería ser cohesiva, y aproximadamente al mismo nivel de abstracción. Cada capa debería ser débilmente acoplada a las capas de abajo.

Esta simple estrategia, ayuda a organizar las aplicaciones para resolver dos desafíos en desarrollo de software: la administración de dependencias y la necesidad de componentes intercambiables. Construir aplicaciones sin una estrategia bien considerada para administración de dependencias, conlleva a componentes frágiles, los cuales son difíciles y costosos de mantener, extender y substituir.

Patrón de Aplicación de Tres capas

Contexto. Estamos construyendo una solución de negocio, usando capas para organizar nuestra aplicación.

Problema. Cómo organizar la aplicación para reutilizar lógica de negocio, proveer flexibilidad en el deployment, y conservar conexión a recursos valiosos.

Solución. Crear tres capas: presentación, lógica del negocio (dominio), y acceso a datos. Colocar todos los componentes responsables de la vista en la capa de presentación. Encapsular toda la lógica del negocio en componentes de la capa de dominio que implementan interfaces de componentes bien conocidas. Localice todo el código relacionado a la base de datos, incluyendo clientes de acceso a base de datos, y componentes de utilidad, en la capa de acceso a datos. La capa de datos es responsable por el pool de conexiones cuando acceda los recursos. Asegurarse de eliminar las dependencias entre componentes de acceso a datos, y componentes de la capa de negocio. Eliminar dependencias entre la capa de negocio y la capa de presentación o administrar las dependencias utilizando el patrón observador.

Refinamiento simple

Cabe notar que Aplicación de tres capas es realmente un refinamiento simple de Capas; el contexto, la importancia, y la solución identificada en Capas se mantiene aplicada en Aplicación de tres capas, pero no al contrario. Esto es, el patrón Capas restringe a Aplicación de tres capas, y el patrón Aplicación de tres capas refina el patrón Capas. Esta relación de patrones es útil para administrar la complejidad. Después de que entendamos un patrón, debemos solo entender las diferencias incrementales entre el patrón inicial y los patrones que lo refinan. Otro ejemplo, esta ves en el área de servicios web, debería ayudar a ilustrar el concepto de refinamiento.

Hemos escrito una aplicación para una empresa exitosa que se expande rápidamente. Ahora queremos extender la aplicación exponiendo su motor de lógica a socios de negocio e integrar los servicios adicionales de los socios (tales como compras) dentro de la aplicación. Cómo estructuramos nuestra aplicación de negocio para proveer y consumir servicios?

Una solución a este problema es extender el patrón Aplicación de tres capas adicionando responsabilidades relacionadas a servicios adicionales a cada capa. La capa de negocio adiciona la responsabilidad de proveer un conjunto simplificado de operaciones para aplicaciones clientes a través de Interfaces de Servicio. Las responsabilidades de la capa de acceso a datos van más allá de la base de datos e integran hosts para incluir comunicación con otros proveedores de servicios. Esta funcionalidad adicional en la capa de acceso a datos es encapsulada en componentes de Pasarelas de Servicios, los cuales son responsables por conectarse a servicios (tanto sincrónica como asincrónicamente), administrando el estado conversacional básico con el servicio, y notificando a los componentes de procesos de negocio de significativos eventos relacionados a servicios.

Patrón Servicios de tres capas

Contexto. Estamos construyendo una solución de negocio que usa capas de presentación, negocio y acceso a datos para organizar la aplicación. Queremos exponer algo de la funcionalidad central de la organización como servicios que otras aplicaciones puedan consumir y habilitar la aplicación para consumir otros servicios.

Problema. Cómo organizar nuestra aplicación para proveer y consumir datos granulares y elementos lógicos de fuentes altamente variables?

Solución. Descomponer la lógica de la aplicación dentro de un conjunto de servicios colaborativos que proveen partes de la funcionalidad completa del sistema. Luego, en la capa de dominio, identificar una Interfaz de Servicios por cada servicio que es independiente de la implementación subyacente. Finalmente, extender la capa de acceso a datos para utilizar Pasarelas de Servicio, para comunicarse con otros proveedores de servicio. Si la lógica de navegación de la aplicación es suficientemente compleja, consideremos usar componentes de proceso de interfaz de usuario como parte de la capa de presentación para encapsular y reutilizar esta lógica.

Es notoria la relación entre estos patrones. Capas introduce una estrategia fundamental para organizar una aplicación de software. Aplicación de tres capas refina esta idea y la restringe a los sistemas de negocio que requieren reutilizar lógica de negocio, flexibilizar el deployment, y uso eficiente de conexiones. Aplicación de servicios de tres capas refina a Aplicación de tres capas y extiende el diseño para proveer y consumir elementos granulares de datos y lógica de fuentes altamente variables.

Bien para terminar, ya iremos desarrollando algo práctico de todo esto, pero es muy importante iniciarse en la teoría y familiarizarse con la forma de documentar patrones, que realmente no es tan complicado, y tal ves tú, si tú, puedas encontrar nuevos patrones o refinar los existentes.

Feliz arquitectura