29 julio 2011

Repository y UnitOfWork con EF 4.1

Hola a tod@s,
en estos días he estado trasteando un poco con Entity Framework 4.1 Code First (EF) y su integración en proyectos ASP.NET MVC3 y, como es habitual, al trastear te surgen dudas sobre cual/cuales serian los patrones y buenas prácticas que se deberían aplicar al trabajar con un motor de ORM. Dos de los patrones que están ampliamente aceptados al trabajar con ORM’s son el patrón repositorio (Repository pattern definido por Martin Fowler) y el patrón unidad de trabajo (Unit of Work también definido por Martin Fowler).
Parece claro pues que es una buena opción aplicar estos patrones si tenemos que “lidiar” con un ORM en nuestro proyecto. Normalmente todos los ORM ya proporcionan una implementación de estos patrones, por ejemplo, con EF, los IDbSets<TEntity> proporcionan los repositorios para nuestras entidades y el DbContext proporciona la unidad de trabajo.
La principal duda que surge una vez hemos decidido aplicar estos patrones es si debemos hacer una abstracción de los patrones repositorio y unidad de trabajo o, por el contrario, podemos trabajar directamente con la implementación de estos patrones que proporciona el ORM. En la comunidad hay partidarios y detractores de cada una de las dos posturas, y cada uno de ellos expone varias razones que les llevan a decantarse por su opción.
Entre los argumentos que esgrimen los partidarios de crear una abstracción encontramos:
  • Se pueden definir operaciones de consulta específicas para cada agregado.
  • Tener un repositorio propio nos permite dotar a los agregados de las funcionalidades que necesitan y solo de estas, cada agregado se puede personalizar para ofrecer solo aquello que debe.
  • Permite centralizar más fácilmente en el repositorio opciones de monitorización, logging y también opciones particulares que queremos que se apliquen siempre que se trabaje con el agregado que representa el repositorio.
  • Los consumidores de los repositorios dependen del ORM concreto (EF en nuestro caso) y hay una dependencia entre estos consumidores (normalmente la capa de servicios) con la capa de acceso a datos.
  • Es más fácil hacer unit testing ya que podemos hacer mocks o stubs de la interfaz que cumple cada uno de nuestros repositorios.
y a favor de usar la abstracción que proporciona el ORM:
  • El más argumento clave que esgrimen los partidarios de usar la abstracción que proporciona el ORM es la simplicidad: ¿para que vamos a reinventar la rueda? Si ya tenemos un repositorio proporcionado por el ORM ¿para que necesitamos implementar el nuestro?
  • Implementar una abstracción de patron repositorio tenia sentido cuando Fowler lo definió por que los ORM no lo proporcionaban, hoy en día carece de sentido puesto que la mayoría de ORM ya proporcionan esta abstracción “de serie”.
  • Cada operación de consulta de debe definir e implementar en los agregados, ¿para qué? esto ya lo tenemos implementado…
  • Se ve como un intento de proteger a los usuarios de los repositorios al “caparles” funcionalidad.
  • En el caso particular de EF los repositorios implementan la interfaz IDbSet<TEntity> con lo cual podemos hacer unit testing igual que si usáramos nuestra abstracción.
Después de leer los argumentos de las dos posturas y ver que, como casi siempre, hay argumentos validos a favor de la abstracción y también en contra me di cuenta que lo primero que tenia que hacer era una prueba de concepto con cada una de las implementaciones y esto es lo que pretendo mostrar en este post: ver los pasos a seguir para aplicar los patrones repositorio y unidad de trabajo con EF partiendo de una implementación “directa”, sin ninguna abstracción y después ver los pasos a realizar para abstraer los repositorios. Este ejemplo nos permitirá entender cada una de las dos opciones y podremos avaluar “con un poco de conocimiento de causa” pros y contras de cada una de ellas.

Opción 1: usando los repositorios de EF

La primera alternativa consiste en usar directamente la implementación del patrón repositorio que proporciona EF.
En esta aproximación solo debemos crear una clase que hereda del contexto de EF (DbContext) y que expone los repositorios IDbSet<TEntity> con los que va a trabajar:
public class MyUnitOfWork : DbContext
{
private IDbSet<FooEntity> FooEntities;
}
Con esta aproximación hay que tener en cuenta que:
  • Todo es muy sencillo, solo debes crear la clase que hereda de DbContext y añadir un atributo público IDbSet>TEntity> para cada repositorio.
  • Nuestro servicio tiene una dependencia a EF, desde el proyecto donde se usen los repositorios y la unidad de trabajo tenemos que añadir una referencia a la dll de EF.
  • Nosotros no creamos los repositorios implementado la interfaz IDbSet<TEntity>, usamos la implementación DbSet<TEntity> que proporciona EF.
  • Los repositorios implementan la interfaz IDbSet<TEntity> con lo cual podemos hacer unit test de los servicios usando mocks o stubs de estos repositorios.
  • La unidad de trabajo tiene los repositorios como atributos, para acceder a un repositorio debemos crear una unidad de trabajo y acceder a este.
  • Es una buena opción para hacer testing usando mocks o stubs hacer que la clase que representa la unidad de trabajo y nos da acceso a los repositorios hereda de DbContext implemente una interfaz con las operaciones operaciones propias de la unidad de trabajo y los getters a los repositorios.
  • Como los repositorios dependen de EF no es tan importante hacer que nuestra unidad de trabajo implemente una interfaz para eliminar esta dependencia.

Opción 2: creando nuestra abstracción para los repositorios

La segunda alternativa es hacer una abstracción de la unidad de trabajo y los repositorios que nos proporciona EF para independizar nuestra capa de servicios del ORM usado en la capa de datos.
Este ejemplo no es un ejemplo funcional, solo pretende mostrar como se harían estas abstracciones. Solo se muestra la operación Add del repositorio y la operación Commit de la unidad de trabajo.
Primero creamos un repositorio para cada agregado que tengamos en nuestra aplicación. Estos agregados implementaran una interfaz con las operaciones típicas (Add, Remove, Attach, etc…) y la implementación de cada una de estas operaciones se delegará al correspondiente DbSet<TEntity>. En el código solo se muestra la operación Add para un agregado FooEntity:
public interface IFooRepository
{
void Add(FooEntity entity);    
}
public class FooEntitiesRepository : IFooRepository
{
private IDbSet<FooEntity> baseRepository;
public FooEntitiesRepository(IDbSet<FooEntity> baseRepository)
{
this.baseRepository = baseRepository;
}
public void Add(FooEntity entity)
{
baseRepository.Add(entity);
}    
}
Bueno, al menos esto es lo que salió en el primer ciclo de Red, Green, Refactor. Fue al crear el segundo repositorio cuando, en la fase de refactoring, nos dimos cuenta que se podía crear un repositorio genérico del que heredaran todos nuestros repositorios (DRY):
public interface IRepository<TEntity> where TEntity : class
{
TEntity Add(TEntity item);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private IDbSet<TEntity> baseRepository;
public Repository(IDbSet<TEntity> baseRepository)
{
this.baseRepository = baseRepository;
}
public TEntity Add(TEntity item)
{
return this.baseRepository.Add(item);
}
}
a partir de aquí surge otra de los debates interesantes (que queda fuera del ámbito de este post): ¿como realizar las consultas a estos repositorios? Aquí tenemos varias opciones y cada una tiene sus pros y contras:
  • Devolver IQueryable<T> y que sea el cliente el que especifique las consultas a realizar directamente con LINQ
  • Proporcionen métodos de consulta explícitos
  • Implementar el patrón de especificación de consultas Specification pattern.
Una vez creados los repositorios procedemos a crear la abstracción de la unidad de trabajo mediante una interfaz IMyUnitOfWork que exponga nuestros repositorios en vez de exponer IDbSet<TEntity> y su correspondiente implementación:
public interface IMyUnitOfWork
{
IRepository<FooEntity> FooEntities { get; }
int Commit();
}
public class MyUnitOfWork : DbContext, IMyUnitOfWork
{
private IRepository<FooEntity> fooEntities;
public IRepository<FooEntity> FooEntities
{
get
{
if (fooEntities == null)
fooEntities = new Repository<FooEntity>(this.Set(typeof(FooEntity)) as IDbSet<FooEntity>);
return fooEntities;
}
}
public int Commit()
{
return base.SaveChanges();
}
}
Como veis, la implementación de esta abstracción delega en el DbContext de EF las operaciones relacionadas con las tareas propias de la unidad de trabajo (Commit, Rollback, etc…). Como ya he comentado antes, solo se muestra la operación Commit de la unidad de trabajo y un único repositorio de entidades de tipo FooEntity.
Con esta aproximación hay que tener en cuenta que:
  • Bastante mas complejo inicialmente, hay que hacer la implementación genérica del repositorio.
  • Posiblemente estas creando una abstracción de algo que ya tenemos, recordad que los DbSets<TEntity> son una implementación del patrón repositorio.
  • Nuestro servicio NO tiene una dependencia de EF, el servicio usara las interfaces definidas para los repositorios y la unidad de trabajo y estas deberían estar colocadas en un proyecto diferente al que contenga las implementaciones dependientes del ORM.
  • Nuestros creamos nuestros propios repositorios heredando de Repository<TEntity> que es la abstracción que hemos creado para implementar el patrón repositorio. Esta implementación es dependiente del contexto de EF.
  • Los repositorios implementan su propia interfaz (para proporcionar consultas explicitas por ejemplo) y nuestra interfaz genérica IRepository
  • La implementación de nuestra unidad de trabajo contiene los DbSet<TEntity> propios
  • Igual que con la primera aproximación, la unidad de trabajo tiene los repositorios como atributos, para acceder a un repositorio debemos crear una unidad de trabajo y acceder a este.

Conclusión

En este post hemos visto dos opciones a la hora de acceder a nuestro ORM mediante los patrones repositorio y unidad de trabajo, cada opción con sus ventajas e inconvenientes. Personalmente, escribir este post me ha servido para clarificar estas dos de las alternativas y me ha permitido comprender un poco más los argumentos a favor y en contra de cada una de ellas. Escoger una opción u otra dependerá, en gran medida, del tipo de aplicación a desarrollar, lo que espero que después de leer este post os sea un poco mas fácil decantaros hacia una opción u otra.
Saludos, Josep Maria
Nota: los siguientes enlaces me han servido de referencia para escribir este post:

27 julio 2011

Inversion of Control con Dependency Injection y/o Service Locator

Hola a tod@s,
leyendo el excelente artículo de Paul Hiles sobre cómo no hacer Dependency Injection (DI) en ASP.NET MVC 3 voy a intentar poner en orden mi cabeza escribiendo lo que he entendido sobre IoC (Inversion of Control), DI (Dependency Injection), Service Locator (SL) y como aplicarlo “correctamente” en un proyecto ASP.NET MVC 3.

La frase más genial y con la que abre Paul el artículo es: Dependency Injection NO es igual a usar un contenedor de IoC, joder!! con perdón, esto da que pensar… vamos a ver, si usamos un contenedor de IoC estamos haciendo DI, ¿no?, pues parece que no, podemos no estar haciendo DI y usar un contenedor de IoC… Ummmm, entonces ¿tampoco estamos aplicando IoC? Bueno, podemos estar aplicando IoC con un contenedor de IoC pero usando el patrón SL en vez de DI… ¿y eso es bueno? ufffff, pues bajo mi punto de vista, para aplicaciones MVC, es mejor hacer usar DI que SL…

¿Liado? Yo también ;-)!! vamos por partes e intentemos dar un poco de luz a todos todos estos conceptos analizando como se relacionan entre ellos:

Después analizar IoC, DI y SL y de leer detenidamente el artículo Inversion of Control Containers and the Dependency Injection pattern de Martin Fowler he llegado a las siguientes conclusiones:
  • Aplicar IoC en nuestras aplicaciones es una buena práctica porqué permite reducir el acoplamiento (siempre deseable)
  • Podemos conseguir IoC usando varios patrones, los más comunes son Service Locator y Dependency Injection
  • Dependency Injection es un patrón que nos proporciona IoC y se basa en delegar la instanciación de las dependencias de nuestra clase en un servicio externo (lo más común es que este servició encargado de resolver dependencias sea un contenedor de IoC) y inyectar estas dependencias a nuestra clase (ya sea en el constructor o bien mediante setters)
  • Service Locator es otro patrón que puede proporcionar IoC y que también se basa en delegar la instanciación de las dependencias de nuestra clase en un servicio externo (el Service Locator) pero, en este caso, estas dependencias no se inyectan a la clase dependiente.
  • Las dos implementaciones proporcionan el desacoplamiento que buscamos con IoC.
  • La diferencia mas importante entre los dos patrones es que mientras con SL nuestra clase llama explícitamente al servicio de resolución de dependencias para obtener las dependencias, en cambio, si aplicamos DI NO existe ninguna llamada explicita al servicio de resolución de dependencias, estas aparecen “como por arte de magia”.
  • Usando SL nuestras clases tienen una dependencia explicita con el servicio de resolución de dependencias, con DI no.
  • SL oculta las dependencias reales de nuestra clase, DI hace estas dependencias explicitas.
  • Según Martin Fowler, tanto con SL como con DI se puede conseguir que nuestros componentes sean fácilmente testeables, con DI es clarísimo y con SL dependerá de la implementación que hagamos. Personalmente creo que con DI los componentes son mucho más fáciles de testear ya que la misma implementación del patrón hace que las dependencias de un componente sean “mockeables”, “fakeables” o “stubables”
  • Se puede mezclar SL con DI, podemos pasar el locator a nuestra clase mediante DI y usarlo luego para resolver las dependencias. Con esto conseguimos que nuestra clase no tenga una dependencia explicita de la implementación del Service Locator sino a una interfaz de este.
  • Actualmente hay algunas opiniones que consideran SL como un anti-patron porqué oculta las dependencias reales de nuestra clase, hay bastante controversia en la red sobre este tema.
Conceptualmente podemos representar los patrones DI y SL de la siguiente forma:
ServiceLocator&DependencyInjection

Veamos algunos ejemplos para aclarar los conceptos anteriores, suponed que tenemos una clase FooClass con una dependencia a un servicio FooService que implementa la interfaz IFooService, veamos distintas formas de resolver esta dependencia:

 

Dependencia sin IoC

public interface IFooService { }
public class FooService : IFooService { }
public class FooClass
{
IFooService service;
public FooClass()
{
this.service = new FooService();
}
}
en este ejemplo estamos resolviendo la dependencia del modo “tradicional”, hacemos un new de la implementación del servicio que necesitamos y listos.

 

IoC con Service Locator

public interface IFooService { }
public class FooService : IFooService { }
public class MyServiceLocator
{
public IFooService GetService()
{
return new FooService();
}
}
public class FooClass
{
IFooService service;
public FooClass()
{
this.service = new MyServiceLocator().GetService();
}
}
en este ejemplo delegamos la creación del servicio a la clase MyServiceLocator, FooClass ya no depende de la implementación concreta de FooService. Estamos haciendo IoC porque la dependencia la esta proporcionando MyServiceLocator pero no estamos haciendo DI porque no estamos inyectando la dependencia y FooClass tiene una dependencia explícita con el Service Locator.

 

IoC con Service Locator usando un contenedor de IoC

public interface IFooService { }
public class FooService : IFooService { }
public class FooClass
{
IFooService service;
public FooClass(IUnityContainer container)
{
this.service = container.Resolve<IFooService>();
}
}
habíamos dicho que se podía usar un contenedor de IoC y no estar haciendo DI, ¿verdad?. En este ejemplo vemos que estamos delegando la creación del servicio a un contendor de IoC (Unity en este caso) pero realmente NO estamos usando DI, simplemente usamos el contendor de IoC como Service Locator para conseguir IoC. No estamos inyectando la dependencia a nuestro controlador, usamos el contenedor de IoC para obtener el servicio pero tenemos una dependencia explícita con el contenedor de IoC. En este ejemplo estamos suponiendo que el contenedor de Unity se pasa a FooClass con la dependencia a IFooService registrada.

 

IoC con Dependency Injection usando un contenedor de IoC

public interface IFooService { }
public class FooService : IFooService { }
public class FooClass
{
IFooService service;
public FooClass(IFooService service)
{
this.service = service;
}
}
en este ejemplo estamos inyectando la dependencia en el constructor de nuestra clases, fijaros que ahora NO tenemos ninguna dependencia de nuestra clase con la implementación del servicio ni con el contenedor de IoC. Esta magia se puede conseguir de varias formas, dependiendo del tipo de aplicación que estemos construyendo, por ejemplo, en ASP.NET MVC3 simplemente tienes que registrar como “resolvedor” de dependencias al contenedor de IoC y el framework se encarga de la magia.

En este post pretendía analizar como conseguir IoC en nuestras aplicaciones ASP.NET MVC 3 pero me he enrollado mucho con la teoría “general” y empezar ahora a aplicarlo al caso concreto de aplicaciones MVC creo que seria demasiado duro por hoy… lo dejaremos para el siguiente post.

Saludos, Josep Maria

Nota: Hay muchísima literatura en la red sobre IoC, DI y SL, los siguientes enlaces me han servido de referencia para escribir este post:

25 julio 2011

El patrón ViewModel en ASP.NET MVC 3

Hola a tod@s,

creo que una de las mejores formas de poner orden a tus ideas es escribiéndolas en un papel (bueno, hoy en día un blog también vale). En estos momentos estoy empezando a hacer mis primeros “pinitos” con ASP.NET MVC 3 y, como siempre que empiezas a trabajar con una tecnología “nueva”, te surgen dudas y te planteas cuestiones sobre su uso. En las siguientes entradas del blog voy a hablar sobre mis progresos con ASP.NET MVC3 plasmando aquí las soluciones que he dio adoptando.

En este primer post voy a enumerar las decisiones de diseño que he aplicado para definir los ViewModels en una aplicación ASP.NET MVC3, para ello plantearé las preguntas que me han surgido durante el desarrollo y expondré las conclusiones a las que he llegado después de analizar y/o probar diferentes alternativas.

A groso modo las alternativas que tenemos para definir el ViewModel son tres:

  • Usar las entidades de dominio directamente como nuestro ViewModel.
  • Usar una clase intermedia (un contenedor) que contenga las entidades del dominio que necesite la vista mas algunas propiedades de presentación.
  • Crear clases nuevas que solo contengan los campos necesarios para la vista y la lógica de presentación para representar nuestro ViewModel y mapear de/a estas clases las entidades del dominio.

¿Usar las entidades del dominio directamente como ViewModel?

La primera decisión a tomar es si vamos a usar como ViewModel directamente nuestras entidades del dominio o vamos a crear una abstracción nueva que represente el ViewModel.

El uso de las entidades del dominio directamente como ViewModel tiene un conjunto de desventajas importantes:

  • En aplicaciones multicapa muchas veces no es posible pasar directamente las entidades del dominio entre las diferentes capas de la aplicación.
  • Se pueden “degenerar” las entidades del dominio con lógica de presentación.
  • Si una vista necesita varias entidades del dominio se crearan “agregados” ficticios el la capa de dominio para resolver una problemática de presentación

La única ventaja que veo en el uso directo de entidades del dominio es que no hay que duplicar la lógica de validación y que requiere un esfuerzo de codificación menor.

El uso de una clase intermedia como contenedor solventa la degeneración de las entidades del dominio ya que permite agregar a la clase contenedor la lógica relacionada con la presentación, también solventa el problema de la creación de “agregados” ficticios en la capa del dominio y permite reaprovechar la lógica de validación pero sigue ligando las entidades del dominio a la capa de presentación, con esta aproximación seguimos teniendo que adecuar el formato de los datos del dominio a la capa de presentación y recibimos toda la información contenida en las entidades del dominio aunque no la necesitemos para la vista que queremos mostrar.

Usar un contenedor intermedio puede ser una buena solución para algunos casos en los que se quiera mostrar toda la información de las entidades de negocio y estas se pueden pasar entre las diferentes capas de la aplicación.

Bajo mi punto de vista el ViewModel de una vista es un concepto relacionado única i exclusivamente con la presentación y, como tal, solo debe lidiar con conceptos relacionados con la representación de los datos, nunca con conceptos de negocio. Si aceptamos la premisa anterior, es un error tratar de usar nuestras entidades del dominio como ViewModel ya que estaríamos introduciendo lógica de presentación en ellas (la entidades de negocio deberían ser agnósticas respecto a la presentación).

Mi opción preferida es crear clases nuevas para representar el ViewModel y hacer mapping entre estas clases y las entidades del dominio. Creo que esta solución mantiene el código mucho mas claro y con una separación de responsabilidades mayor. Como puntos en contra de esta aproximación tenemos la necesidad de duplicar la lógica de validación y un esfuerzo de codificación mayor.

¿Hay una relación 1:1 entre los ViewModel y las entidades del dominio? ¿Y con las vistas?

Claramente NO tiene porqué haber una relación 1:1 entre las entidades del dominio y los ViewModels, de hecho esta es una de las razones que motivan no utilizar las entidades del dominio como ViewModels. En cambio casi siempre hay una relación 1:1 entre el ViewModel y la vista que lo renderiza.

¿No estamos duplicando trabajo?

Si, como casi siempre, la flexibilidad que tenemos al usar ViewModels separados de las entidades del dominio es a costa de un mayor esfuerzo de codificación para crear los ViewModels específicos de cada vista y duplicar las validaciones de las entidades del dominio. Pensad, por el contrario, que un ViewModel bien definido debería reducir a 0 el código de formateo de datos de la vista.

¿Como construimos los ViewModels a partir de las entidades del dominio? ¿Y las entidades del dominio a partir del ViewModel?

La opción más simple y usada que he estado probando para construir el ViewModel a partir de las entidades del dominio es Automapper (se puede instalar vía paquete de NuGet en vuestro proyecto MVC3). En la red hay mucha información sobre el uso de Automapper y como integrarlo correctamente en aplicaciones ASP.NET MVC, algunas consideraciones que a tener en consideración son:

  • Se pude usar Automapper para mapear varias entidades del dominio a un ViewModel.
  • Normalmente dejo las convenciones por defecto para trasladar los atributos de las entidades del dominio a atributos del ViewModel.
  • Llamar a CreateMap solo una vez al inicializar la aplicación, no debemos hacerlo en el código de cada action.

Existen aproximaciones para no tener que realizar los mapeos en cada una de las actions, como la que explica Jimmy Bogart en esté post usando filtros para no tener que realizar siempre este mapeo, pero todavía no he podido analizar-lo ni probarlo :-(

La respuesta a la segunda pregunta puede parecer obvia, ¿no? Si usamos Automapper para construir el ViewModel a partir de las entidades del dominio pues también usaremos Automapper para hacer el paso inverso… pues NO, Automapper no está pensado para realizar un mapeo two-way entre modelo del dominio y ViewModel, solo nos ayudará en el mapeo Modelo –> ViewModel (tenéis una justificación en esta entrada del creador de Automapper). En mi caso estoy haciendo este mapeo de forma manual, creando un DTO y pasándolo a la capa de servicios ¿alguna otra idea? ¿cómo lo hacéis?

Resumen

Para la mayoría de proyectos complejos crearemos, para cada vista, su ViewModel asociado construirlo a partir de las entidades del dominio (o de DTO’s en caso de tener servicios distribuidos), y ubicaremos ahí toda la lógica de presentación que pueda requerir la vista para ser renderizada correctamente.

Saludos, Josep Maria