viernes, 31 de mayo de 2013

La fiesta de los bocazas. (Blowhard Jamboree)

Buscando en Internet los antipatrones para refrescarlos en mi mente y redactar el post anterior he caído en un antipatrón (título de este post) que aunque no es muy común en los ambientes que me muevo actualmente es muy fácil caer en ellos y además refleja la paradoja de que yo mismo soy un bocazas.

Este antipatrón consiste en tomas decisiones y asumir cosas simplemente con la información salida de lo que ha publicado un señor cualquiera en un medio de comunicación. Por ejemplo, este blog.

En mi caso en concreto me ha pasado con "el lado oscuro" de los patrones de diseño.



GenericRepository


Existe un patrón llamado Layer Supertype Pattern. Es muy común que en una capa de una arquitectura, muchas o todas las clases pertenecientes a esa capa tengan métodos que internamente realizan la misma tarea. Para facilitar el mantenimiento y asegurar un control, se mueve ese código a una clase que actuará como supertipo de estas clases pertenecientes a la capa de arquitectura.

Esto se ha aplicado en la capa de acceso a datos para crear lo que se llama un "Repositorio Genérico" en el cual se implementan las acciones comunes que realizarán los repositorios concretos de las entidades.
//Clase Base ó Layered-Supertype de Repositories
public class GenericRepository : IRepository
Al implementar el repositorio de la entidad Productos este quedaría así:
//Clase Repository para entidad Product
public class ProductRepository : GenericRepository, IProductRepository
Y queda cojonudo... hasta el día que lees un post cuyo título es "GenerycRepository es un Antipatrón". En ese post te cuentan como en un repositorio genérico se implementan acciones como Add, Remove, Attach y Modify y que cuando una entidad en un dominio en concreto no deba ser modificada o borrada hay que sobrescribir el método heredado del repositorio genérico en el repositorio de la entidad y lanzar una excepción (NotAllowedException). El repositorio genérico obliga a exponer funcionalidades que no se deben usar según el dominio. Y al final acaba con una frase de forma muy taxativa "¡NO uses repositorios genéricos!" Joder, pues tiene razón...

Pues va uno, le hace caso y se carga el repositorio genérico tan chulo que había implementado, implementa un repositorio para cada entidad exponiendo simplemente las funcionalidades que debe tener cada repositorio concreto y se encuentra que vuelve al problema principal; un montón de código repetido en un montón de diferentes repositorios.

El problema está en que el "bocazas" (sin intención de ofender) no ha reconocido que el antipatrón no es el diseño de un repositorio genérico, el antipatrón está en el uso incorrecto del repositorio genérico. Yo digo : SÍ que puedes (si quieres) usar un repositorio genérico para no repetir código, pero no como Layer Supertype (y aquí esta el truco), si no como una dependencia que debes inyectar en los repositorios concretos.
public class ProductRepository : IProductRepository
{
  private IRepository _genericRepository;
  public ClasificationRepository(IRepository _genericRepository)
  {
    _genericRepository = genericRepository;
  }
}
El repositorio de productos expondrá (a través de su interfaz) únicamente las acciones de persistencia que se puedan realizar con los productos (Add,  Modify pero no Remove, por ejemplo)  y llamará al repositorio genérico interno para realizar las acciones que ya estén implementadas en él; por otra parte implementará las acciones concretas con los productos que no puedan ser puestas en el repositorio genérico.
public void Add(Producto nuevoProducto){
    _genericRepository.Add(nuevoProducto)
}

ServiceLocator 


No voy a extenderme mucho porque este ejemplo es muy parecido al anterior.

ServiceLocator es otro patrón de diseño que te da unas ventajas muy bonitas. Lo implementas y te pones a resolver, por todas partes de tu código, justo antes de que los vayas a usar, los servicios que necesitas. Y queda chulo y molón... hasta que lees un post que dice "ServiceLocator es un Antipatrón". Que si bla,bla,bla. Que si yada, yada, yada."¡NO uses ServiceLocator porque hace que tu clase dependa de casi cualquier cosa en tiempo de ejecución!" Joder, pues tiene sentido esto que me acaba de contar...

Me cargo el ServiceLocator que es un antipatrón muy feo y ya está... pues no. Yo digo ¡SÍ que puedes (i quieres) usar ServiceLocator! pero junto con un contenedor de inyección de dependencias. Si estructuras bien la arquitectura y configuras adecuadamente el árbol de dependencias, podrás utilizar el ServiceLocator en una sola capa de tu aplicación, y en puntos muy definidos,  para resolver el servicio superior, al que se le han inyectado todas las dependencias (y las dependencias de las dependencias, etc), y utilizar ese servicio manteniendo siempre bajo control el uso del ServiceLocator pero aprovechando sus ventajas.

No te creas al 100% lo que lees en los medios de comunicación.
No te creas lo que acabas de leer.
Soy un bocazas.

No hay comentarios:

Publicar un comentario