1 may 2011

Patrones de Diseño: Pluggable Structure

Hace mucho que no posteaba en mi blog de tecnología...así que hoy vuelvo al ruedo.
Intentaré hacer posteos de forma mas seguida y de paso google no me baja su pagerank!
Tenía ganas de retomar el blog para presentar una solución a un problema que seguramente se habrán enfrentado y quizás (por no decir casi seguro) lo habrán resuelto de una manera no muy elegante. No quiero decir que esta solución pretenda ser la mejor ni mucho menos, pero aunque sea de forma didáctica está más que interesante.
El problema es el siguiente: Supongamos que tenemos que grabar un mensaje de log en diferentes salidas, una podría ser enviar un mensaje a través de un servicio WCF, otra en el FileSystem, otra en el EventLog de windows y la última en una base de datos.
Ya sé que muchos dirán.....ufff tenés un montón de librerías que hacen eso, como log4net por ejemplo que 100% customizable desde un archivo .config.
La idea de esta entrada no es reemplazar una funcionalidad ya existente, como el logging por ejemplo, sino mostrar a través de este ejemplo un patrón que lo podemos llamar Pluggable Structure. Por qué el nombre? Bueno, porque podés cambiar dinámicamente, esto es, sin recompilar, ni tocar el código .net, el proveedor de Logging, y todo con solo cambiar el nombre en un .config.
Voy a presentar mi app.config de esta forma:





















Si observamos, lo primero que hice fue definir una sección personalizada "myLogggingProvider" donde voy a setear los providers soportados y el que se usa por defecto. Si observamos tenemos una etiqueta "providers". Aquí se colocan los 4 proveedores de los que hablé antes. Por último tenemos un atributo "defaultProvider", aquí se coloca el proveedor que queremos usar. Listo, con eso ya estaría nuestro .config. Ahora lo que vamos a hacer es definir las clases que le den soporte a esta configuración.
Esta sería la clase que mapea contra nuestra sección "myLoggingProvider":


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace TestPatternsConsole.Code.Configuration
{
public class LogProviderConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("providers")]
public ProviderSettingsCollection Providers
{
//gets the providers in the app.config file
get { return (ProviderSettingsCollection)base["providers"]; }
}

///
/// Gets the default provider in the app.config file
///

[StringValidator(MinLength = 1)]
[ConfigurationProperty("defaultProvider", DefaultValue = "WCFLogProvider")]
public string DefaultProvider
{
get { return (string)base["defaultProvider"]; }
set { base["defaultProvider"] = value; }
}
}
}


Como vemos, tiene definidas 2 propiedades: Providers y DefaultProvider, que luego seteamos en el app.config.
Atención: Debemos incluir en nuestro proyecto referencia a System.Configuration.dll.
Luego veamos la estructura general del proyecto, así se dan una idea:



Como ven tenemos los 4 proveedores de logging: DbLogProvider, EventLogLogProvider, WCFLogProvider y FileLogProvider.
Todas estas clases implementan la interfaz ILogProvider:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestPatternsConsole.Code.Base
{
///
/// Innterface for Logging providers
///

public interface ILogProvider
{
void Log(string logMessage);
}
}


Lo que me permite este factory, es trabajar contra la interfaz, independientemente del provider que la implemente.
Así por ejemplo la clase que loguea en WCF hará algo así:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestPatternsConsole.Code.Base;

namespace TestPatternsConsole.Code
{
public class WCFLogProvider : ILogProvider
{
public void Log(string logMessage)
{
Console.WriteLine("This providers logs on a WCF Service: {0} ", logMessage);
}
}
}


Y ahora la parte más importante...la clase que va a llamar el cliente y que va a "levantar" la configuración del app.config.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using TestPatternsConsole.Code.Configuration;
using TestPatternsConsole.Code.Base;

namespace TestPatternsConsole.Code
{
public static class LogProviderLoader
{
private static ILogProvider _defaultProvider = null;
private static object _syncroot = new object();

public static void Log(string message)
{
SetDefaultProvider();
_defaultProvider.Log(message);
}

private static void SetDefaultProvider()
{
if (_defaultProvider == null)
{
lock (_syncroot)
{
//retrieves all the providers from the app.config file
LogProviderConfigurationSection section = (LogProviderConfigurationSection)ConfigurationManager.GetSection("sectionLoggingProviders/myLogggingProvider");

//gets the providers
Dictionary<string,ILogProvider> _logs = new Dictionary<string,ILogProvider>();

//generates instances for each provider
foreach (ProviderSettings p in section.Providers)
{
_logs.Add(p.Name,(ILogProvider)Activator.CreateInstance(Type.GetType(p.Type)));
}

_defaultProvider = _logs[section.DefaultProvider];
}
}
}
}
}


Aquí se aplican varios patrones, entre ellos el Singleton, que asegura tener una única instancia de ILogProvider. Como se ve en la clase de arriba, nunca se hace referencia directa a un proveedor en particular, más cuando se instancia un proveedor (haciendo uso de la clase Activator) se castea contra la interfaz, y la implementación queda para la clase en particular.
Luego desde un cliente se puede hacer:


namespace TestPatternsConsole
{
class Program
{
static void Main(string[] args)
{
LogProviderLoader.Log("hola");
}
}
}


Aquí subo el código.
y listo! El patrón implementado y funcionando.
Saludos,
Mike

24 dic 2010

Unity - Pasar cadenas de conexión al constructor

Actualmente me encuentro desarrollando la arquitectura de un sistema orientado al dominio (Domain Driven Design), bajo C# en Visual Studio 2010, utilizando el nuevo Entity Framework 4. Estoy utilizando Unity como resolvedor e inyectador de dependencias. Ahora bien, como expliqué en posts pasados, utilicé las plantillas T4 para generar mis entidades y mi contexto de conexión. Estaba trabajando instanciando en cada consulta al contexto que me generaba el EF. Cuando hablo de contexto, me refiero a la clase parcial cuyo nombre lo toma en base al nombre que ingresamos cuando hicimos click en [Add Code Generation Item...].
Básicamente borré esa clase e hice que mis repositorios heredaran directamente de ObjectContext. Un ejemplo de una clase repositorio es la siguiente:
  
namespace mtcholakian.samples.TestDDD.Data.Repositories
{
public class CustomerRepository : GenericRepository<Customer>, ICustomerRepository
{
public CustomerRepository(string connectionString)
: base(connectionString)
{
}

}
}


Si observan en el constructor de la clase, estamos esperando una cadena de conexión. Esta cadena la tomo desde el App.Config o archivo de configuración. Ahora bien, el contenedor de Unity es el que me devuelve una instancia de CustomerRepository, pero cómo hago para pasarle ese parámetro de conexión? Fácil, nuestro App.Config tendrá que lucir de la siguiente manera:

  













Aquí se le dice que el valor del connectionString es "SampleDbEntities", lo cual es el nombre del key de la sección connectionString que va a estar declarada dentro del App.Config también.
Ahora, una cosa más y lo más interesante de todo es que tenemos un atributo typeConverter. Lo que nos dice es que al pasarle al constructor el parámetro connectionString lo resuelva esa clase, que tenemos que definir más arriba de la siguiente forma por ejemplo:

  



Y ahora simplemente vemos la definición en sí de la clase:

  
namespace mtcholakian.samples.TestDDD.Utils
{
public class ConnectionStringTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
return ConfigurationManager.ConnectionStrings[value.ToString()].ConnectionString;
}
}
}


Lo que hace es recibir un valor, en nuestro caso será el que definimos en el parámetro param, "SampleDBEntities" y en base a ese string devuelve la entrada de connectionStrings del App.Config que contiene la conexión a la base de datos.
Listo!
Una cosa muy importante es que la declaración de los tipos del unity aplica únicamente a Unity 2.0, no a la versión 1.4, ya que utilizaba un elemento typeConfig del tipo TypeInjectionElement que no viene más a partir de la versión 2.0.
Espero les haya sido útil.
Saludos,

Mike

9 dic 2010

Unity - Inyectar dependencias genéricas

Siguiendo con mis entradas anteriores y con la implementación de mi patrón Repositorio, se me ocurrió inyectar una dependencia en el constructor de una clase.
Unity resuelve en forma automática las dependencias en un constructor, lo cual significa que no tenemos que declarar ese parámetro explícitamente dentro de la sección <types>. En mi caso estoy declarando los mapeos en el archivo de configuración (App.Config), entonces cuando el contenedor detecte esa dependencia en el constructor, automáticamente le inyectará la implementación que hayamos declarado.
Lo interesante es cómo inyectar una dependencia y que esta además sea genérica.
Paso a detallar mi clase en cuestión:
    

public class CustomerRepository : GenericRepository<Customer>, ICustomerRepository
{
//la interfaz genérica es la que el contenedor de Unity debe resolver
public CustomerRepository(IContext<Customer> context) : base(context)
{
}

}


Nuestro archivo de configuración tendrá un aspecto similar al siguiente:


<typeAlias alias="IContext`1" type="mtcholakian.samples.TestDDD.Business.Core.IContext`1,Business.Core"/>
<typeAlias alias="Context`1" type="mtcholakian.samples.TestDDD.Data.Context.Context`1,Data"/>


Observen cómo se declara un generics y luego la clase que lo implementa.
Finalmente dentro de nuestro container declaramos el mapeo:
    
<container name="RootContainer">
<types>
<type type="IContext`1" mapTo="Context`1" name=""></type>
</types>
</container>


Luego, cuando desde la aplicación instanciemos CustomerRepository obtendremos una instancia en el constructor con la clase indicada.
Espero les haya sido útil.
Saludos,
Mike

5 dic 2010

Entity Framework 4 - Cómo obtener un objeto por su primary key

Implementando mi patrón Repository, me encontré con un problema al tratar de hacer un método del estilo GetObjectById(int id), que básicamente devolvería un objeto a partir de su clave primaria en la base de datos.
Por más que revisé toda la web, no encontré la solución, así que luego de estar un largo rato probando voy a plasmar aquí la forma de resolverlo.
Básicamente lo que hago es un método donde le paso un array de objects, ya que la clave primaria en la BD puede estar formada por varios campos, donde cada elemento es una clave.
Aquí el método en cuestión:


public T GetEntityById(params object[] keys)
{
using (SampleDBEntities context = new SampleDBEntities(SampleDBEntities.ConnectionString))
{
EntitySet en = context.CreateObjectSet<T>().EntitySet;
EntityKeyMember[] entityKeys = new EntityKeyMember[en.ElementType.KeyMembers.Count];

for(int i=0;i < en.ElementType.KeyMembers.Count;i++)
{
entityKeys[i] = new EntityKeyMember();
entityKeys[i].Key = en.ElementType.KeyMembers[i].Name;
entityKeys[i].Value = keys[i];
}

EntityKey entityKey = new System.Data.EntityKey { EntityContainerName = en.EntityContainer.Name, EntityKeyValues = entityKeys, EntitySetName = en.Name };
object outObject = null;

context.TryGetObjectByKey(entityKey, out outObject);

return (T)outObject;
}
}



Luego desde un main podrían usarlo de la siguiente forma:


static void Main(string[] args)
{
//aquí uso Unity para resolver implementaciones
ICustomerRepository repo = ProxyGenerator.GetImplementation<ICustomerRepository>("CustomerMappging");

//obtengo el cliente por su primary key

Customer customer = repo.GetCustomerById(1);
}


Espero que haya sido útil.
Saludos,
Mike

28 nov 2010

Inyección de Dependencias con Unity

Voy a iniciar este tema, ya que comenzó a interesarme a raíz de un draft que estoy leyendo de microsoft, sobre arquitecturas orientadas al dominio (Domain Driven Design).
Lo pueden bajar desde aquí.
La idea de inyectar dependencias es un tema muy interesante que nos va a servir en el momento de desacoplar capas y facilitar los procesos de test.
Para armar mi solución me basé en el proyecto del link que transcribo arriba, la cual simpliqué bastante, a modo de poder realizar rápidamente las pruebas que me interesaban.
Mi solución consta de los siguientes proyectos:
  • Business.MainModule. Contiene los servicios, que son el punto de entrada de las aplicaciones ASP .NET MVC, WinForm o RIA y las interfaces de los contratos para los repositorios.
  • Business.MainModule.Entities. Contiene las entidades del dominio. Basándome en mi ejemplo, fueron generadas gracias las plantillas T4 de Entity Framework 4. El tipo de entidades que generé fueron del tipo POCO (Plain CLR Objects). Este tipo de entidades no está ligado a ninguna tecnología en particular, o sea, no tienen referencia a ninguna library específica de modo que queden relacionados a la capa de datos. Prefería este tipo de plantillas a las IPOCO, ya que si bien estas últimas vienen preparas para WCF, me parecieron más complejas de implementar.
  • Data. Es la capa de infraestructura de acceso a Datos. Contiene el modelo .edmx de EF 4 y la clase T4 para generación del contexto. Esta capa implementa los repositorios que definimos en Business.MainModule.
  • Data.Mock. Es mi proyecto de test, donde se ve la potencia de DI, al reemplazar "on the fly" la capa de infraestructura por un "fake", para realizar los test.
  • TestDomainDrivenDesign. Es mi capa de presentación, desde donde realizo las pruebas.
No voy a entrar en detalle, ya que en el pdf que nombré más arriba está más que claro. Mi modelo es más simplificado puesto que no uso proyectos Core en Business o en Data.
Aquí expongo como se vería el proyecto:


Mi idea al probar unity es NO hacer referencia desde la capa de presentación, en este caso, TestDomainDrivenDesign hacia la capa Data, es decir, no instanciar directamente los repositorios, sino que sea el contenedor de Unity el que nos de la instancia.
La idea es la siguiente: cuando te pida la interfaz del tipo "IInterfaz" devolveme "Clase".
Hay varias formas de establecer esta relación, o mejor dicho, este mapeo entre interfaz y clase implementadora, yo opté por la opción de hacer estas definiciones en el App.Config o Web.Config (dependiendo de nuestra capa de presentación).
Primeramente hay que bajarse las dlls de Unity, lo pueden hacer desde aquí.
A su capa de presentación deberan agregar las referencias a: Microsoft.Practices.Unity y Microsoft.Practices.Configuration.
Pasemos a la configuración de nuestro archivo de configuración ejemplo:



























Como podemos ver,hay varias secciones que nos interesan:
  1. Tenemos dentro de configSections una sección llamada "unity". Luego la definiremos más abajo y es la que contendrá la definición de los mapeos. Es más recomendable hacer referencia a un archivo externo que tenga la configuración del unity y no mezclarlo con el que usamos en nuestra aplicación. En este caso, como es una aplicación pequeña opté por tenerlo todo en junto. Pero es algo a tener en cuenta.
  2. Tengo una sección connectionString con la conexión al modelo de Entity Framework 4.
Lo que primero debemos hacer es definir nuestros "alias", que son las clases e interfaces que vamos a usar en el mapeo y en que assemblies están definidas.







Luego, viene la parte donde le decimos que interface se mapea a que clase y algo MUY importante el "name".






Ahora veamos como hacer la llamada al contenedor de unity para que nos devuelva una instancia del repository "real", en este caso, CustomerRepository. El main, junto con las pruebas a realizar se verías más o menos así:

public class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

section.Configure(container,"RootContainer");

ICustomerRepository repo = container.Resolve<icustomerrepository>("CustomerMappging");

//creates a new customer
Customer customer = new Customer { CustomerCode = "123", CountryId = 1, CompanyName = "Prueba", ContactName = "Miguel", ContactTitle = "Ing" };

//adds a new customer
repo.AddCustomer(customer);

//retrieves all the customers
List<customer> list = (List<customer>)repo.GetAllCustomers();

foreach (Customer c in list)
{
Console.WriteLine("Id: {0}, Name: {1}", c.CustomerId, c.ContactName);
}

}
}

Si nos fijamos nunca hicimos referencias a la clase, siempre contra la interface.
Por ello sería muy válido, y ahora viene la parte interesante y que nos va a ayudar en el momento de las pruebas, que es, reemplazar nuestro repositorio por otro "fake".
Bastará con hacer este simple cambio en el App.Config:














Listo! no tuvimos que cambiar nada NI en la capa de presentación. El contenedor nos devuelve una instancia de CustomerRepositoryMock con nuestra implementación "fake" los métodos de la interfaz.
Por último: para hacer las pruebas en el bin\debug hay que pegar las .dlls del proyecto de Data y Data.Mock, sino el reflection no encontraría las clases que definimos en el App.Config.

Pueden descargar el código completo para Microsoft Visual Studio 2010 desde aquí.
Aquí dejo el script que deberán correr sobre una base de datos para que la aplicación quede 100% funcional.
Saludos,
Mike

21 nov 2010

Gestión de Excepciones - Parte II

  • No manejar errores atrapando excepciones no específicas, como aquellas que heredan de System.Exception. El siguiente es un mal uso:

public class MalManejoExcepciones
{
public void DoWork(){//Hacer algo que dispare una excepción}
}

public void MethodWithBadHandler()
{
try
{
DoWork();
}
catch (Exception e)
{
//Atrapar la excepción y continuar ejecutando
}
}

  • Hay ocasiones en las que no se deben atrapar las excepciones y dejar que la aplicación "explote" y termine.
  • Atrapar las excepciones que sabemos que debemos hacer en cada caso. No atrapar excepciones no específicas y re lanzarlas.
  • Atrapar las excepciones que sabemos que podemos continuar con la ejecución de nuestra aplicación. Por ejemplo: si recibimos una excepción del tipo "FileNotFoundException", se puede atrapar y permitirle al usuario que especifique un archivo diferente. En cambio si se recibe un error desconocido y no sabemos si es seguro que la aplicación en ese estado continúe no se debe atrapar la excepción.
  • Usar el bloque try-finally preferentemente al try-catch. El bloque catch permite atrapar excepciones, mientras que el finally liberar recursos.
  • Disparar únicamente utilizando la palabra "throw", de esta manera preservamos el call stack trace. Ejemplo:


public void DoWork(Object anObject)
{
// Do some work that might throw exceptions.
if (anObject == null)
{
throw new ArgumentNullException("anObject","Specify a non-null argument.");
}
// Do work with o.
}

public void MethodWithBadCatch(Object anObject)
{
try
{
DoWork(anObject);
}
catch(ArgumentNullException e)
{
System.Diagnostics.Debug.Write(e.Message);
// Incorrecto
throw e;
// Debería ser:
// throw;
}
}

Gestión de Excepciones - Parte I

En este artículo voy a explicas unas guías para tener en cuenta al momento de trabajar con excepciones.

Las excepciones son el mecanismo estándar para reportar errorres. Las aplicaciones y librerías no deberían usar códigos de errores para devolver errores. Además permite disparar errores desde miembros como constructores que no tienen un tipo de datos de retorno.

Guías para disparar excepciones
Las excepciones se disparan cuando un miembro no puede hacer con éxito aquello para lo cual fue diseñado. Por ejemplo
si tengo que conectarme a un end point de WCF y el mismo no responde, disparo una excepción.
A tener en cuenta:

  • No devolver códigos de error. Las excepciones son el medio primario para reportar errores.
  • No usar excepciones para controlar el flujo normal de la aplicación. Siempre que se pueda tratar de no pensaren programar para disparar excepciones. Si se pueden evitar, mejor. Ejemplo:


public class Disparo
{
public static void ShowMessage(string mensaje)
{
if(mensaje == null)
{
throw new ArgumentNullException("mensaje");
}
}

}

public class Testeo
{
public static void Procesar(List<string> mensajes)
{
foreach(string mensaje in mensajes)
{
if(mensaje !=null)
{
Disparo.ShowMessage(mensaje);
}
}
}
}


  • Tener en cuenta el gasto de performance que implica disparar excepciones.
  • No usar miembros públicos que disparen una excepción basado en un código de error. Ejemplo: void ParseoString(string value, bool dispararExcepcion);
  • Usar métodos helpers de construcción de excepciones ya que la misma excepción puede dispararse de diferentes lugares. Pero ojo, estos helpers no deben disparar la excepción, solo inicializar propiedades, sino alteraríamos el stack trace.
  • No disparar excepciones desde la cláusula finally.