viernes 22 de mayo de 2009

Como soluciona Asp.Net el "stateLess" de la web

En un curso que dicto sobre AspNet, una pregunta recurrente es "como maneja el lenguaje la falta de estado en el entorno web?".

Digamos que en un programa Windows local, el usuario interactúa con una aplicación que está ejecutandose ininterrumpidamente, la cual almacena su información en una porción de la memoria del computador. En una aplicación Web esto no es así, si bien un sitio desarrollado con ASP NET pueda verse como “ejecución ininterrumpida”, esto es solo una ilusión.

En un típico Web Request, el cliente se conecta al Web Server y solicita una página, cuando ésta es enviada la conexión se cierra y el Web Server abandona cualquier información que posea del cliente. Por lo cual cuando el cliente recibe la página solicitada, la aplicación ya ha parado su ejecución. Por este motivo Asp Net nos dota con las siguientes posibilidades para manejar el almacenamiento de los datos (mantener el estado):

Tenemos 4 posibilidades, aquí las 2 primeras, ViewState y QuieryString

Por último, cookies y session state:




martes 19 de mayo de 2009

AOP y DI con Spring Net

Finalmente y despues de tantos meses, he vuelto al ruedo con mi Blog, y he visto que me he comprometido en mi anterior post a proveer de un ejemplo de AOP con Spring Net, en este link tienen un ejemplo sencillo, donde se implementa un "Around Advice", lo cual implica poder ejecutar código antes y despues del llamado al método actual interceptado.

Tambien les dejo un ejemplo de como realizar DI (dependency injection) :



por ejemplo, tenemos una clase "User" que tiene un servicio "UserService", que a su vez tiene en su constructor un parametro que permitirá setear (inyectar...) el DAO con el que trabajará. (si.., tambien podriamos haberlo hecho en una propiedad)



Luego, definimos en un archivo xml de config. (app.config o web.config) , donde se define un objeto "userService" con un parámetro para su constructor ("dao") , que será otro objeto llamado "userDao".

A continuación se muestra la definición del object id "userDao", que como ven es de tipo SpringApp.Data.NHibernate, efectivamente Spring no reinventa la rueda y usa como ORM a NHibernate.

Este objeto llamado "userDao" tiene una property llamada "SessionFactory", que es la definida dentro de la config. de NHibernate dentro del mismo xml.

Por último para crear un objeto "userService" con el seteo hecho en el archivo xml (mi DI):

En la 1er. linea debo cargar el contexto de lo definido con Spring (IApplicationContext) y luego le pido a ese contexto que me dé un objeto cuyo id es "userService".

sábado 14 de junio de 2008

AOP - Que es la prog. orientada a aspectos?

Orientar la programaciòn al uso de "aspectos", que extraño suena no?; tratemos de explicar su uso en la POO.

Definiciòn de AOP

Segùn Wikipedia : "intenta ayudar a los programadores en la separaciòn de incumbencias (soc-separation of concerns), especificamente las incumbencias cruzadas (cross-cutting concerns), como un avance en el uso de la modularizaciòn."

En la POO la modularizaciòn implica el uso del encapsulamiento, ya sea a nivel de clases, paquetes, componentes, capas. Siempre buscamos asignar responsabilidades y aislarlas en su propio mòdulo funcional, logrando diseños de caja negra que nos permitan reusabilidad y fàcil mantenimiento.

Aunque, existen ciertas incumbencias ò àreas de interès (concerns) que son generales a varios mòdulos, por lo que, al incluìr esta funcionalidad en ellos, estarìamos repitiendo còdigo; el cual en caso de tener que modificarlo implicarìa hacerlo en todos los mòdulos que lo contengan. Por ejemplo: la seguridad, el "logging", el "debugging", sincronizaciòn y administraciòn de transacciones, cacheo.

Entonces existen caracterìsticas como las mencionadas que no son modularizables, son incumbencias que no pueden ser aisladas dentro de un solo mòdulo, ya que es su naturaleza estar distribuida su implementaciòn en varios mòdulos.






En este punto debe quedar claro que nuestro sistema està formado por un cojunto de "concerns", donde algunos de ellos no pueden formar parte de un solo mòdulo, a estos los llamaremos "cross-cutting concerns".

EL AOP esta diseñado para manejar estos "cross-cutting concerns", proveyèndonos de un mecanismo conocido como "Aspecto" (aspect).


Aspecto

"Modularizaciòn de un "concern", sin el cual deberìa implementarse a travès de mùltiples objetos con distintas responsabilidades."

"Funcionalidad que se quiere aplicar a otras partes del còdigo (autorizaciones, logging, transacciones,...)"


Como implemento AOP en .NET?

Hay varios frameworks que permiten trabajar con AOP en .NET, entre ellos es de destacar Spring.NET que nos da esta funcionalidad con el uso de su componente Spring.AOP

Para comprender el funcionamiento de los Aspectos, debemos definir algunos conceptos AOP:

Advice : cada una de las cosas que puede hacer un Aspect

Join Point: Punto del programa en el que se ejecutarà un Advice

Point Cut: Conjunto de Join Points, un conj. de mètodos donde se ejecutarà un Aspect.

Target: El objeto sobre el que se aplicarà el/los aspecto/s. Es el obj. que contiene el Join Point.

Introduction: Manipular un Target para añadirle còdigo. Permite introducir nuevas interfaces a cualquier "obj. advised" (Target). Por ej.: un obj. puede implementar "IAuditable" para simplificar el rastreo de cambios en su estado.

Weaver: Caract. de ensamblado para crear los "objs. advised". Puede ser hecho en tiempo de ejecuciòn (como Spring.Net) ò en tiempo de compilaciòn (usando el compilador Gripper-Loom-Net)

Algunos tipos de Advice:
  • Before : Justo antes de un Join Point
  • After: Despuès de terminar un Join Point (haya o no excepciòn)
  • Around: envuelve la ejecuciòn del Join Point, pudiendo ejecutar còd. antes y despues, incluso evitar su ejecuciòn.

En un pròximo post entrare en detalle sobre el uso de AOP de Spring con un ejemplo concreto.

domingo 11 de mayo de 2008

Desarrollando Software con un Modelo de Negocio

Aquí les dejo la presentación que dicté en la UTN Mar del Plata, en el marco de las "Jornadas sobre Desarrollo Software" (Mayo/08).
La temática gira alrededor de los siguientes conceptos: Componentes software, Modelo de negocio (Trans.Script y Domain Model) , Persistencia de objetos de neg. y acceso a datos con NHib. (DataMapper y ActiveRecord), DAO.

Cualquier problema con la visualización de la presentación pulsar en opción "View" de Slideshare.

La aplicación Web que demuestra estas tecnologías ( desarrollada con AspNet 2 y NHib.), se encuentra aquí : ConferenciaWeb.
Dentro del zip tienen una carpeta con las instrucciones para instalar y ejecutar; tener en cuenta que necesitan el VS 2005 y en lo posible SqlServer 2005, si necesitan probar con otra BD deben cambiar los drivers del NHibernate en el web.Config. Espero les sea de utilidad.

Por ultimo les dejo el enlace a la filmaciòn del seminario que realizò la gente de TecnoTV de Canal 10 de MdP : seminario de capas con NET

domingo 27 de abril de 2008

Jornadas sobre Desarrollo de Software (MdP) - MAYO/08

Los dias sabados 10,24 y 31 de Mayo de 10 a 13.30 hs, se dictaràn 3 seminarios orientados a desarrolladores de software : .NET+NHibernate, RubyOnRails y Java con EJB-Struts (reprog. del dia 17/5) respectivamente.

Estas jornadas se haràn en el aula Magna del Centro de Estudios Mar del Plata de la UTN.
Para ampliar sobre las mismas ver la entrevista que me efectuaron en el programa Mercados & Empresas de Canal 10 del cable de MdP.

Cualquier interesado de la zona (estudiante o profesional) con conocimientos en POO puede inscribirse gratuitamente en el sitio de la UTN: http://www.mdp.utn.edu.ar/ (ver folleto)

sábado 5 de abril de 2008

Dominios de aplicaciòn en .NET (App Domains)

Todos sabemos que .NET ejecuta còdigo administrado a travès de Dominios de aplicaciòn, pero conceptualmente no son muchos los desarrolladores .Net que comprenden en profundidad esta arquitectura y sus implicancias.
Por este motivo he decidido compilar un capìtulo interesante del libro "Programming .Net Components 2nd. Ed." que trata sobre este tema.

Còdigo administrado en .NET y dominios de aplicación

Todas las aplicaciones y componentes .NET requieren de un ambiente administrado para ejecutarse. Para esto .NET utiliza un “Dominio de Aplicación” (Application Domain), que permite la ejecución de còdigo administrado de parte de los “Ensamblados” (Assemblies).
El “Dominio de Aplicación” serìa el equivalente en .NET al concepto de Proceso del S.O., con una gran diferencia: dentro de un proceso fìsico del S.O. pueden hostearse mùltiples de estos “Application Domains” . Podrìamos entonces considerarlos como “procesos lògicos” dentro de un proceso real del S.O.
( figura 1)
Esta arquitectura de “Application Domains” posee grandes ventajas con respecto a la tradicional de poseer cada aplicación(exe) y c/u de sus componentes(dlls) dentro de su propio y exclusivo proceso. Los procesos tradicionales son denominados en .NET como “còdigo no administrado”.

Algunas desventajas de esta arq. de multiples procesos son:

  • Crear y Destruir un proceso del S.O. consume mucho tiempo.

  • Mantener un proceso en ejecución es costoso en tèrminos de memoria y de los recursos que el S.O. debe ubicar en ellos.
  • Realizar llamadas entre procesos resulta en penalidades de tiempo, ya que cruzar los lìmites de un proceso es mucho màs costoso que realizar un llamado directo dentro del mismo. Esto es porque se necesitan mecanismos especiales para efectuar los llamados inter-proceso (por ej.: pipes, sockets, LPC/RPC) .

  • El còdigo en los procesos clientes se vuelve complejo para realizar llamados a otros procesos y obviamente difiere de los llamados internos.
Ventajas de los “Application Domains”:

  • Baja sobrecarga en el S.O. por permitir que mùltiples “procesos lògicos” se hosteen en el mismo proceso real que administra el S.O.
  • Los tiempos que requiere Crear o destruir un “App.Domain”, y mantenerlo en ejecución con sus recursos asignados, es una fracciòn del requerido por un proceso fìsico.
  • Los llamados entre “App. Domains” que estàn dentro del proceso fìsico son mucho màs ràpidos que los llamados entre diferentes procesos del S.O.
  • .NET mantiene un lìmite de seguridad estricto entre “App.Domains”, por lo cual los objs. del “App.Domain A” no pueden interferir con los objetos del “App.Domain B”; a menos que estos objs. decidan cooperar usando .Net Remoting.

Es importante destacar que para mantener las 2 grandes ventajas de la arq. tradicional de “mùltiples procesos”: “Aislamiento ante fallas” y “Seguridad”, cada “App.Domain” carga y mantiene su propio juego de Assemblies. En la figura 1 , la librerìa de clases llamada “Assembly 1” se carga 2 veces, una en cada App.Domain (B y C), los cuales poseen su propia copia independiente.

La plataforma .NET y los “App. Domains”
El RunTime de .Net es un juego de Windows DLLs, implementadas en còdigo no administrado con C++; estas proveen : administración del Heap, recolector de basura (GC), compilador JIT (JustInTime), Cargador y adm. de assemblies, y otras herramientas que hacen posible el “còdigo administrado”.
El “App.Domain” habilita a los Assemblies que carga, a acceder a estos servicios del RunTime .Net. Por este motivo se dice que los App.Domains son el puente que une el Mundo de còd. administrado con el Mundo de còd. no administrado.
( figura 2)
Es importante notar en la figura 2 que todos los App.Domain del mismo proceso comparten el mismo “administrador de Heap”.

Threads (Hilos) y App.Domains

Los Threads en .Net no son afines a los App.Domains, esto implica que un thread puede entrar y salir en cualquier Dominio que se ejecute en el mismo proceso subyacente. Por lo tanto nada previene que un Thread creado en un App Domain acceda a los objs. de otro App Domain en el mismo proceso.

App Domains y Remoting

.Net usa la misma arq. de llamados Remotos entre App Domains para:
· 2 App Domains en el mismo proceso
· 2 App Domains en 2 procesos distintos del S.O.
· 2 App Domains en 2 màquinas fìsicas distintas.

(figura 3)

Los clientes que estàn en el mismo App.Domain del obj. llamado pueden tener una referencia directa al obj. En cambio los clientes que estàn en diferentes App.Domains usan un Proxy para conectarse al objeto.
Un Proxy es un obj. que provee exactamente las mismas interfaces, mètodos pùblicos, propiedades y miembros que el obj. real, aunque el Proxy no puede servir al cliente debido a que el còdigo del objeto llamado y su estado residen donde el obj. estè.
Todos los proxys saben como ligarse al obj. y enviarle los llamados hechos por el cliente, esta operación es denominada “marshaling”.
El marshaling cumple con el objetivo de darle al cliente la ilusiòn de que està llamando a un objeto local y darle al servidor la ilusiòn de que està sirviendo a un cliente local. Ni cliente, ni servidor usan mecanismos remotos (pipes, RPC, sockets), debido a que estos detalles estàn encapsulados en el Proxy.
.Net requiere que si un obj. es accedido por un Proxy, la clase del obj. debe derivar de la clase abstracta “MarshallByRefObject”.

jueves 28 de febrero de 2008

Estrategias para persistir objetos : ActiveRecord vs DataMapper

Persistencia : procedimiento que es ejecutado para lograr que los datos sobrevivan a la ejecución de un determinado programa.

Porque es necesario el uso de frameworks ORM (object relational mapping) para crear una capa de persistencia que acceda a los datos de nuestra aplicación?, si esta pregunta no tiene respuesta para ti, es aconsejable que vayas aquí.

Si en .Net tengo AdoNet 2.0, que me da la posibilidad de comunicarme con la BD, permitiendome recuperar los datos y copiarlos a un DataSet local, ligarlos a mis controles en la IU, y luego persistir los cambios, via SqlCommands ó DataAdapters que realizan las operaciones CRUD de Insert,Update, Select y Delete; no puedo generar una capa de persistencia con esta tecnología?.
Por supuesto que SI, y esta fue la apuesta de la gente de Microsoft hasta la version 2.0 de NET; seguir desarrollando software donde mis entidades de negocio son directamente las filas de las tablas de una BDR (Base de datos relacional). Para esto MS ha desarrollado una artillería de controles (datagrids, combobox, listviews, etc) drag and drop con wizards que facilitan enormemente la programación ligando mis entidades de negocio con mis IU (Win y WebForms). Lamentablemente este tipo de tecnología implica comenzar cada aplicación de software como si se tratase de la 1ra que realizamos, osea : casi nula reutilización de código aunque rapidez en el desarrollo y testeo.
Esto ha permitido que miles de personas puedan estar "capacitadas?" como programadores con un curso intensivo de 3 meses; los cuales sólo podrán seguir desarrollando con las tecnologías MS del tipo "WizarDragAndDropHappyProgramming" salvo que logren ver "más allá" y comiencen a investigar como funcionan los frameworks de desarrollo (Struts de Java, RubyOnRails, CakePhp) que triunfan en la actualidad y que implican mayor conocimiento de programación y arquitecturas de software, especialmente en aplicaciones Web donde ha triunfado largamente el uso del patrón de arquitectura MVC, no es casualidad que en la nueva versión 3.5 de NET se haya desarrollado un framework que aplique esta arquitectura .

Hablabamos de reutilización, la cual es imposible sin un diseño previo que tenga en cuenta los patrones de arquitectura, donde el 3 capas lógicas es el punto por donde comenzar; donde ubicar la persistencia?, pues en la capa de acceso a datos. Ahora si lo que queremos es trabajar con "objetos de negocio" (business objects ó BOs) en las otras 2 capas superiores y no con los DataSets como "entidades de negocio" que representan a las filas de una determinada tabla, deberemos usar algún framework ORM para que haga de intermediario entre los campos de las tablas relacionadas y nuestros objetos de negocios que responden a un Modelo del dominio.

Estos objetos de negocio deben representar el mayor esfuerzo de diseño en el desarrollo de un software (la M de Modelo en un MVC), si lo que deseamos es aplicar un enfoque DDD (Domain Driven Design).
DDD propone que el aspecto más complejo en los proyectos de software no es la implementación, sino el dominio del mundo real al cual el software le da servicio. Lograr que el objetivo principal del proyecto sea el modelo del negocio y mantener un modelo de software que refleje una profunda comprensión del mismo. Esta visión fue desarrollada por Eric Evans en su libro "Domain Driven Design".
Volviendo a la persistencia, podría NO utilizar ningún fwk y codificar mi propias clases ORM?, por supuesto, aunque si desarrollas con .NET ya existen varias posibilidades open source que son excelentes, entre las cuales son de destacar NHibernate y ActiveRecord de Castle; que aplican 2 patrones de persistencia distintos que son el motivo de este post.





Active Record

Propone tener los métodos que me brindan la persistencia en el mismo objeto de negocio, y normalmente las instrucciones del mapeo atributo del objeto-campo de la tabla en la definición del objeto de negocio. Por ej. en el ActiveRecord de Castle:


De esta forma podria crear un objeto Blog y persistirlo así:

Como vemos el uso del motor de persistencia es muy natural y sencillo de usar. El único problema que se plantea es que, desde el pto. de vista de la separación de responsabilidades de las capas; en este caso; estamos acoplando los BOs de la capa de negocios con la persistencia que debería estar en la capa de acceso a datos. Porque esto no es bueno?, porque perdemos independencia y será más costoso el cambio a otra tecnología de persistencia.

Esto es debido a que son nuestros objetos de negocio los que conocen como acceder a los datos persistidos mediante, en este caso, ActiveRecord de Castle; estos métodos de manejo de persistencia no deberían ser conocidos por nuestra capa de negocios, y suele decirse que estamos ensuciando nuestro código. Si a esto le sumamos las instrucciones de mapeo (ej: [PrimaryKey]), nuestras clases que crearán los BOs dejarán de ser POCO (plain old c# objects), y estarán influenciadas por cualquier cambio en la tecnología de acceso a datos subyacente.

Por último cabe aclarar que muchos de estos ActiveRecord, como por ejemplo el DooDads (cuyo código se crea desde MyGeneration), generan el modelo de clases a partir de las tablas y relaciones de la BDR ya creada, lo cual desde mi pto. de vista no es lo correcto, debido a que un modelo de clases es mucho más rico en posibilidad de asociaciones y navegabilidad que un esquema de tablas relacionadas.

Data Mapper

Propone que nuestros objetos de negocio sean POCO (ó POJO en Java), o sea que no tengan nada de código que los acople a una tecnología dada de persistencia, ya que no es su función manejarla. Los objetos de negocio solo deben preocuparse de cumplir con el modelo del dominio vía diseño del diagrama de clases con las asociaciones pertinentes.



Este es el caso de NHibernate, que propone manejar la persistencia a través de una clase administradora de la misma: Session. Esta clase es la que se encarga de hacer las operaciones CRUD a la BDR. Por ej. para persistir nuestro objeto de tipo Salon:

Para ver un tutorial sencillo y completo sobre NHibernate ver este post de Dario Quintana.

De esta forma todo lo que tenga que ver con el DataMapper (NHibernate) puede quedar aislado en su propia capa, fuera de la capa de negocio que posee nuestros BOs. Para poder realizar esta tarea en forma más transparente es necesaria la creación de clases DAO (data access objects) que implementen los métodos más comunes que realiza la capa de persistencia.
Por ej: (DAO del Salon)


Con los DAOs de cada BO trabajarìamos con el sig. còdigo en la implementaciòn de nuestros procesos:

Por supuesto que aprovechando Generics podriamos armar un HibernateDAOAbstracto que realice todas las operaciones comunes de persistencia y de esta forma nuestros DAO especìficos de cada BO heredarìan de èste. Para màs informaciòn al respecto ver el excelente ejemplo de Billy McCafferty.

En Resúmen...

Esta visto que con NHibernate debemos codificar màs, aunque logramos mayor independencia para poder cambiar los DAOs que se implementan con NHibernate por otro que se implemente con Linq Sql por ejemplo. Tambien es importante destacar que NHibernate es un framework con muchisimas funcionalidades (manejos de transacciòn, lazy loadings, Queries tipo HQL, Criterias, interceptores, etc), esto ha hecho que en el caso del ActiveRecord de Castle, se haya implementado usando NHibernate como API base ("no reinventar la rueda", no?).

Desde el punto de vista teórico de los 2 patrones (Martin Fowler. Patterns of enterprise application architecture ), el uso de un Data Mapper nos permite manejar toda la carga y almacenamiento entre el modelo de dominio y la base de datos, logrando que ambos varien independientemente. En el Active Record se mantiene una relacion de uno a uno entre clases y tablas, siendo más dificil la implementacion de modelos de negocio complejos.

Por último, el objetivo de este post no ha sido mostrar una tecnologìa de persistencia en particular, sino revisar los 2 patrones principales que se usan para implementarla y el porque de los beneficios de usarla en un diseño que se guie por un buen diagrama de clases del modelo de dominio de la aplicaciòn a desarrollar; en definitiva promover que los programadores dejemos de lado el uso directo de los registros de las BDR y usemos objetos de negocio en nuestros desarrollos, aprovechando una arquitectura que separa las responsabilidades y posibilite mayor reusabilidad y menor mantenimiento.

Me gustaria que este post sirva para concentrar comentarios sobre el tema de persistencia, y que puedan brindar aqui sus experiencias y dudas en su uso. Nos leemos..