11.29.2010

Utilizando Unity para Resolver un Problema de Negocio - 3

Siguiendo con el uso de Unity para trabajar problemas de negocios de una forma menos dependiente entre los componentes que desarrollamos, vamos ahora a tratar el caso en donde la clase recién instanciada tiene una referencia a otra clase que a su vez debe ser resuelta por el contenedor de IoC.

Supongamos que cada usuario tiene una relación de agregación con la interface IEmpresa y que dependiendo de la empresa se paga un cargo diferente cuando se realiza alguna transacción. La interface IEmpresa tendrá un método que solamente le aplica el cargo a la transacción. La relación de clases en el problema actual es la siguiente:

image

En nuestro código la implementación de nuestras clases lucirá así:

Interface IEmpresa

namespace Core.LogicaDeNegocios
{
public interface IEmpresa
{
void AplicarCargos();
}
}



Clase Oficina: Implementa IEmpresa



using System.Diagnostics;

namespace Core.LogicaDeNegocios
{
public class Oficina: IEmpresa
{
public void AplicarCargos()
{
Trace.WriteLine("Aplicar Cargos Oficina");
}
}
}


Clase EmpresaExterna: Implementa IEmpresa



using System.Diagnostics;

namespace Core.LogicaDeNegocios
{
public class EmpresaExterna: IEmpresa
{
public void AplicarCargos()
{
Trace.WriteLine("Aplicar Cargos Empresa Externa");
}
}
}



En la interface IUsuario agregamos la relación de agregación antes representada:



public interface IUsuario
{
IEmpresa Empresa { get; set; }

IUsuario Autenticar();
void Autorizar(object _form);
}



Ahora modificamos la clase Usuario, para que tenga una implementación de IEmpresa. Nótese que la clase debe implementar la propiedad expuesta en la interface y no necesariamente el mismo tipo en el atributo, ya que con solo tener una clase que implemente la interface, ya podemos crear la asociación.



public class Usuario : IUsuario
{
Oficina _oficina;

public Usuario(string pNombreUsuario, string pPassword)
{
Trace.WriteLine(string.Format("Datos del usuario. NombreUsuario: {0}, Password: {1}", pNombreUsuario, pPassword));
}

public IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autenticar Usuario");
}

public IEmpresa Empresa
{
get
{
return _oficina;
}
set
{
_oficina = value as Oficina;
}
}

}



Lo mismo ocurrirá con la clase Usuario_Web, con la diferencia que en Usuario_Web si vamos a crear un atributo del tipo IEmpresa.



public class Usuario_Web: IUsuario
{
IEmpresa _empresa;

public Usuario_Web(string pNombreUsuario, string pPassword)
{
Trace.WriteLine(string.Format("Datos del usuario. NombreUsuario: {0}, Password: {1}", pNombreUsuario, pPassword));
}

public virtual IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario Web");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autorizar Usuario Web");
}

public IEmpresa Empresa
{
get
{
return _empresa;
}
set
{
_empresa = value;
}
}
}


Por otro lado, vamos a crear una clase que hereda de Usuario_Web y que implementa su propia implementación de IEmpresa.



public class OtroUsuario : Usuario_Web
{
IEmpresa _empresa;

public OtroUsuario(string pNombreUsuario, string pPassword)
:base(pNombreUsuario, pPassword)
{
Trace.WriteLine(string.Format("Datos del usuario. NombreUsuario: {0}, Password: {1}", pNombreUsuario, pPassword));
}

public override IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Otro Usuario Web");
return this;
}

public IEmpresa Empresa
{
get
{
return _empresa;
}
set
{
_empresa = value;
}
}

}



Por último agregamos el nuevo mapping para tenerlo entre la lista de clases que pueden ser resueltas.



  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<
alias alias="IUsuario" type="Core.LogicaDeNegocios.IUsuario, Core.LogicaDeNegocios" />
<
namespace name="Core.LogicaDeNegocios" />
<
assembly name="Core.LogicaDeNegocios" />
<
container>
<
register type="IUsuario" name="usuario" mapTo="Usuario" />
<
register type="IUsuario" name="usuarioWeb" mapTo="Usuario_Web" />
<
register type="IUsuario" name="otroUsuario" mapTo="OtroUsuario" />
</
container>
</
unity>



En la parte del UI, agregamos el nuevo tipo de usuario a través de la empresa C.



private void btnLogin_Click(object sender, EventArgs e)
{
string _tipoUsuario = string.Empty;
if (cmbEmpresa.SelectedItem.ToString() == "Empresa A")
_tipoUsuario = "usuario";
else if (cmbEmpresa.SelectedItem.ToString() == "Empresa B")
_tipoUsuario = "usuarioWeb";
else
_tipoUsuario = "otroUsuario";

UsuarioActual = AdministradorUsuario.ObtenerInstancia(_tipoUsuario, txtNombreUsuario.Text, txtPassword.Text).Autenticar();

}



Si ejecutamos el código tal y como esta – y llevando la continuación del post anterior – veremos lo siguiente:



image



Como vemos en la figura, la instancia de empresa del tipo que resolvió Unity esta en nulo. Sin duda no es el comportamiento que queremos. Pero como hacer para que la clase que estamos instanciando pueda resolver la empresa que desea en tiempo de ejecución? Para este problema en específico, Unity me permite crear inyección para las propiedades con lo cual puedo definir dentro del registro del tipo para mapear, como debe de cargarse una propiedad de la clase que se va a resolver. Para lograr esto vamos a modificar nuestro archivo de configuración de la siguiente forma:



  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<
alias alias="IUsuario" type="Core.LogicaDeNegocios.IUsuario, Core.LogicaDeNegocios" />
<
namespace name="Core.LogicaDeNegocios" />
<
assembly name="Core.LogicaDeNegocios" />
<
container>
<
register type="IEmpresa" name="empresaMap" mapTo="EmpresaExterna" />
<
register type="IEmpresa" name="oficinaMap" mapTo="Oficina"
/>
<
register type="IUsuario" name="usuario" mapTo="Usuario" >
<
property name="Empresa" dependencyName ="oficinaMap" dependencyType="IEmpresa"></property
>
</
register
>
<
register type="IUsuario" name="usuarioWeb" mapTo="Usuario_Web" />
<
register type="IUsuario" name="otroUsuario" mapTo="OtroUsuario" >
<
property name="Empresa" dependencyName ="empresaMap" dependencyType="IEmpresa"></property
>
</
register
>
</
container>
</
unity>



Como podemos ver en el texto en negrita, primera vamos a crear dos mapas nuevos para los tipos recién creados que implementan la interface IEmpresa.



<register type="IEmpresa" name="empresaMap" mapTo="EmpresaExterna" />
<
register type="IEmpresa" name="oficinaMap" mapTo="Oficina" />



Seguidamente vamos a modificar los registros para los usuarios deseados y vamos a establecer la instancia que queremos sea inyectada en la propiedad del tipo de IEmpresa.



<register type="IUsuario" name="otroUsuario" mapTo="OtroUsuario" >
<
property name="Empresa" dependencyName ="empresaMap" dependencyType="IEmpresa"></property>
</
register>



      <register type="IUsuario" name="usuario" mapTo="Usuario" >
<
property name="Empresa" dependencyName ="oficinaMap" dependencyType="IEmpresa"></property>
</
register>





En este caso hemos establecido que cuando se vaya a crear una instancia del tipo Usuario la propiedad IEmpresa se instancie con el tipo Oficina, y si por lo contrario creamos una instacia del tipo OtroUsuario vamos a tener la propiedad IEmpresa con una instancia del tipo EmpresaExterna. Si creamos una instancia de Usuario_Web la instancia de la propiedad IEmpresa no se podrá resolver y por lo tanto será null.



Si seleccionamos Empresa C –> OtroUsuario el resultado será:



image



Si seleccionamos Empresa A –> Usuario el resultado será:



image



Y si seleccionamos Empresa B –> el resultado será:



image







Technorati Tags: ,,

11.23.2010

Utilizando Unity para Resolver un Problema de Negocio - 2

En el post anterior presentamos un problema el cual resolvimos usando Unity, sin embargo, este problema se presentó de una manera muy simple y un poco corto en realidad. En este post vamos a agregarle un par de situaciones que se presentan normalmente en este tipo de sistemas.

En primer lugar, cuando creamos la instancia del usuario que necesitamos, le tuvimos que indicar de forma explícita al método AdministradorDeUsuario.ObtenerInstancia utilizando un generic, algo que por supuesto no es deseado ya que obliga al cliente de la aplicación a estar conciente de los tipos de usuario que existen y esto limita la aplicación a trabajar con los usuarios existentes y no nos permite agregar nuevos usuarios sin tener que recompilar la aplicación.

En segundo lugar estamos utilizando clases para los usuarios que no contienen datos y por lo tanto no son inicializados cuando se crea la instancia, por lo que el método Autorizar no funcionaría en un escenario real ya que no tiene los datos que el usuario utilizó para loguearse.

Mejoras

Para atacar el primer problema vamos a cambiar la forma en que le solicitamos nuestras instancias a Unity. Con los contenedores de IoC tenemos la gran ventaja de que podemos solicitarles que resuelvan el tipo en base al nombre del mapeo que queremos utilizar. El primer paso es cambiar el archivo de configuración para que trabaje con un solo contenedor de la siguiente forma:

<?xml version="1.0" encoding="utf-8" ?>
<
configuration>
<
configSections>
<
section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</
configSections>
<
unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<
alias alias="IUsuario" type="Core.LogicaDeNegocios.IUsuario, Core.LogicaDeNegocios" />
<
namespace name="Core.LogicaDeNegocios" />
<
assembly name="Core.LogicaDeNegocios" />
<
container>
<
register type="IUsuario" name="usuario" mapTo="Usuario"
/>
<
register type="IUsuario" name="usuarioWeb" mapTo="Usuario_Web"
/>
</
container
>
</
unity>
</
configuration>



Seguidamente quitamos el parámetro del tipo que estamos solicitando en el método ObtenerInstancia ya que como dije anteriormente vamos a dejar que Unity resuelva el tipo en base al nombre del mapa que queremos utilizar. Los posibles nombres para los mapas son:



<register type="IUsuario" name="usuario" mapTo="Usuario" />
<
register type="IUsuario" name="usuarioWeb" mapTo="Usuario_Web" />



Además al método ObtenerInstancia le vamos a agregar dos parámetros más, el usuario y el password para que pueda agregarlos como valores al usuario que se vaya a crear – problema 2. La invocación del método desde nuestra pantalla de login ahora se ve así:



string _tipoUsuario = string.Empty;
if (cmbEmpresa.SelectedItem.ToString() == "Empresa A")
_tipoUsuario = "usuario";
else
_tipoUsuario = "usuarioWeb";

UsuarioActual = AdministradorUsuario.ObtenerInstancia(_tipoUsuario, txtNombreUsuario.Text, txtPassword.Text).Autenticar();



El siguiente paso y para trabajar en el problema 2, es crear un constructor para cada tipo de usuario de forma tal que reciba el usuario y el password como parámetros y que pueda hacer la autenticación con los mismos. Las clases modificadas son las siguientes:



public class Usuario_Web: IUsuario
{

public Usuario_Web(string pNombreUsuario, string pPassword)
{
Trace.WriteLine(string.Format("Datos del usuario. NombreUsuario: {0}, Password: {1}", pNombreUsuario, pPassword));
}


public IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario Web");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autorizar Usuario Web");
}
}



public class Usuario : IUsuario
{
public Usuario(string pNombreUsuario, string pPassword)
{
Trace.WriteLine(string.Format("Datos del usuario. NombreUsuario: {0}, Password: {1}", pNombreUsuario, pPassword));
}


public IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autenticar Usuario");
}
}



Ahora solo nos queda modificar el método ObtenerInstancia para que a través de Unity se pueda resolver el tipo que deseamos instanciar en base al tipo de usuario que queremos utilizar y además que los datos del usuario puedan ser inyectados a través del constructor de la clase a instanciar:



using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Core.LogicaDeNegocios
{
public static class AdministradorUsuario
{
public static IUsuario ObtenerInstancia(string mapName, string pUsuario, string pPassword)
{
using (IUnityContainer container = new UnityContainer())
{
container.LoadConfiguration();
return container.Resolve<IUsuario>(mapName, new ParameterOverrides { { "pNombreUsuario", pUsuario }, { "pPassword", pPassword } });

}
}
}
}



Con esto ya podemos ejecutar nuestra aplicación y crear la instancia que deseamos con los datos enviados.



image



image



Technorati Tags: ,,,,

11.22.2010

Utilizando Unity para Resolver un Problema de Negocio - 1

En días pasados me encontré con un problema en el cual se podría utilizar IoC para resolverlo de forma sencilla y elegante. En este post voy a reproducir este fix con un problema un tanto diferente pero en el cual se puede ver como de forma sencilla podemos aprovecharnos de las bondades de Unity y a la vez hacer nuestra aplicación más versátil y fácil de hacer crecer.

El Problema

Supongamos que tenemos un sistema que hace una seria de funciones para la empresa y que luego de una fusión con otra empresa, tenemos un sistema similar pero que además realiza unas funciones extras. Resulta que cada sistema tiene su propia tabla de usuarios ( así es, como siempre primero se hacen los sistemas y luego se piensa en la seguridad y no a la inversa como debería ser ) y se quiere hacer una versión de forma rápida que mezcle las funcionalidades de ambas aplicaciones. La aplicación va a tener un ComboBox en donde el usuario indica a cual empresa originalmente pertenece y el sistema debe resolver a donde debe de ir a autenticarse el usuario. En primera instancia, la primera aplicación es desktop y la segunda aplicación es Web. El problema radica en cómo manejar estos tipos diversos de usuario en una sola aplicación sin necesidad de andar previendo con cual tipo estamos trabajando.

La Solución

La solución a este problema esta por el lado del polimorfismo, ya que si definimos una interface IUsuario, podemos trabajar con la interface y no con el tipo concreto, lo cual nos ahorraría el peso de estar manejando un tipo de usuario X en la aplicación cuando se requiera. El siguiente diagrama nos muestra lo expuesto anteriormente.

image

El código de cada una de las clases es el que se presenta a continuación:

namespace Core.LogicaDeNegocios
{
//Este usuario se autentica en una base de datos para usuarios Web
public class Usuario_Web: IUsuario
{
public IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario Web");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autorizar Usuario Web");
}
}
}



namespace Core.LogicaDeNegocios
{
//Este usuario se autentica utilizando una base de datos de usuarios locales
public class Usuario : IUsuario
{
public IUsuario Autenticar()
{
Trace.WriteLine("Autenticar Usuario");
return this;
}

public void Autorizar(object _form)
{
Trace.WriteLine("Autenticar Usuario");
}
}
}



Ahora el punto es como hacer que la aplicación construya la instancia que corresponda – dependiendo de la selección del comboBox – sin necesidad de estar creando clases concretas por toda la aplicación. Para este caso es que se decidió utilizar Unity. Con Unity tenemos la posibilidad de registrar los tipos que deseamos y mapearlos con clases concretas para cuando solicitemos el tipo, se nos retorne la instancia que deseamos. Para registrar nuestras clases anteriores vamos a utilizar el archivo app.config de nuestra aplicación desktop y vamos a agregar la siguiente configuración.



<?xml version="1.0" encoding="utf-8" ?>
<
configuration>
<
configSections>
<
section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</
configSections>
<
unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<
alias alias="IUsuario" type="Core.LogicaDeNegocios.IUsuario, Core.LogicaDeNegocios" />
<
namespace name="Core.LogicaDeNegocios" />
<
assembly name="Core.LogicaDeNegocios" />
<
container>
<
register type="IUsuario" name="usuario" mapTo="Usuario"
/>
</
container
>
<
container name="UsuarioWeb"
>
<
register type="IUsuario" name="usuarioWeb" mapTo="Usuario_Web"
/>
</
container
>
</
unity>
</
configuration>



Como podemos ver en el xml anterior, estamamos registrando dos tipos con la interface IUsuario: Usuario y Usuario_Web, para que cuando solicitemos el tipo Unity tenga como resolver y pueda crear la instancia que deseamos. El siguiente paso es utilizar el contenedor de Unity para que nos resuelva el tipo y dado que no queremos que el UI se tenga que preocupar por este block, vamos a crear una clase estática que nos ayude retornando la instancia a partir de un tipo especificado como parámetro en una función que vamos a crear para crear la instancia de acuerdo al tipo que solicita el usuario.



//Unity
using Microsoft.Practices.Unity;

namespace Core.LogicaDeNegocios
{
public static class AdministradorUsuario
{
public static IUsuario ObtenerInstancia<T>() where T:IUsuario
{
using (IUnityContainer container = new UnityContainer())
{
return container.Resolve<T>();
}
}
}
}


Nótese el constraint en el Generic, el cual nos delimita los tipos de datos que pueden ser T, en este caso T tiene que implementar IUsuario. Por último procedemos a crear el código en la forma de log in, en donde de acuerdo a la opción seleccionada por el usuario vamos a seleccionar el tipo que queremos pasar como T a la función ObtenerInstancia<T>.



IUsuario _usuarioActual;

public IUsuario UsuarioActual
{
get { return _usuarioActual; }
set { _usuarioActual = value; }
}

private void btnLogin_Click(object sender, EventArgs e)
{
if (cmbEmpresa.SelectedItem == "Empresa A")
UsuarioActual = AdministradorUsuario.ObtenerInstancia<Usuario>().Autenticar();
else
UsuarioActual = AdministradorUsuario.ObtenerInstancia<Usuario_Web>().Autenticar();

}



En este caso específico, estamos pasando el tipo concreto al método que nos devuelve una instancia de la clase solicitada, y como ambas clases deben de implementar la interface IUsuario podemos invocar el método Autenticar que es parte de este contrato. Este método nos devuelve una instancia de IUsuario el cual podemos utilizar en nuestra aplicación para operaciones posteriores de Autorización. Para cerrar el post vemos la estructura de proyecto utilizada, la cual como veremos en el siguiente post nos va a permitir cargar clases de lógica de  negocios dependiendo de la forma en que se configure el sistema.



image



Technorati Tags: ,,

11.20.2010

Actualizar una Entidad Utilizando el ObjectDataSource y el EntityFramework

Continuando con el post respecto a utilizar el EntityFramework en conjunto con el ObjectDataSource en una aplicación ASP.NET, vamos a ver como actualizar una entidad utilizando esta combinación de componentes. En primera instancia vamos a tener una tabla de usuarios la cual una vez creado el modelo en el EntityFramework vamos a tener una estructura como la que se ve en la siguiente figura.

image

Luego procedemos a crear nuestra lógica de negocio en donde vamos a tener un método que nos permite obtener una instancia única del contexto de las entidades del modelo del EntityFramework, este método lo podemos ver a continuación.

Public Class SeguridadBL
Public Shared Contexto As SeguridadEntities

Public Shared Function ObtenerContexto() As SeguridadEntities
If Contexto Is Nothing Then
Contexto = New SeguridadEntities
End If
Return
Contexto
End Function


El siguiente método es el que nos sirve para actualizar la entidad. Como podemos ver en el método, vamos a recibir una instancia de una variable tipo Usuario, la cual vamos a tener que trabajar un poco más para poder actualizar los datos en la base de datos.



    Public Function ActualizarUsuario(ByVal pUsuario As Usuario) As Integer

Dim
resultado = From u In ObtenerContexto.Usuarios _
Where u.Id = pUsuario.Id _
Select u
Dim tmpUsuario As Usuario = resultado.SingleOrDefault
tmpUsuario.Nombre = pUsuario.Nombre
tmpUsuario.Apellido1 = pUsuario.Apellido1
tmpUsuario.Apellido2 = pUsuario.Apellido2
tmpUsuario.Activo = pUsuario.Activo
tmpUsuario.Email = pUsuario.Email
tmpUsuario.Password = pUsuario.Password
Return ObtenerContexto.SaveChanges()
End Function



Como la instancia de la clase usuario que viene en el parámetro no pertence al contexto actual que estamos utilizando, vamos a tener agregarla al contexto. Sin embargo, para poder agregar la instancia, tendríamos que agregarle el entityKey, el cuál de por si ya existe en el contexto. En este caso, vamos a ir a traer la instancia utilizando una simple operación de select y luego, le vamos a setear los valores desde la instancia que viene por parámetro – en mi opinión una solución no muy elegante, pero al parecer la más practica. Pot último, le decimos al contexto que guarde los cambios en la base de datos con SaveChanges.



Del lado de la página ASP.NET, vamos a crear un objeto del tipo ObjectDataSource y vamos a proceder a configurarlo de la siguiente manera:



1. Primero seleccionamos la clase desde la cual vamos a tener el método de actualización, en nuestro caso SeguridadBL.



image



2. Luego procedemos a configurar el método de actualización. Cuando el objectDataSource detecta que el parámetro es un tipo complejo, establece la propiedad DataObjectTypeName con el nombre del tipo del parámetro el cual utiliza para crear una instancia de la clase cuando es invocado el método.



image



3. Seguidamente le asociamos el ObjectDataSource al GridView.



image



4. El siguiente paso es crear el botón de comando para tener la opción de editar.



image



Con esto finalizamos el proceso de edición utilizando el ObjectDataSource, el gridView y el EntityFramework.



image



Sin duda la ventaja principal con este esquema, es que podemos seguir utilizando nuestra lógica de negocios utilizando aplicaciones Web y através del ObjectDataSource no vamos a tener la necesidad de escribir código ni para seleccionar ni para actualizar datos.



Technorati Tags: ,,

11.16.2010

¿Qué paso aquí?–> Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0

Después de instalar VS 2010 y por consiguiente el framework 4.0 procedí a crear un servicio en WCF utilizando VS 2008, ya que el proyecto con el que vengo trabajando utiliza esta herramienta y el framework 3.5 para llevar a cabo sus tareas. Luego de crear el servicio, procedo a probarlo desde la consola del IIS 7 y plop!… me aparece el siguiente error en el browser.

image

Después de una búsqueda rápida me di cuenta que el problema esta en los application pools. Cómo se puede ver en la siguiente figura, la mayoría de mis sitios web corren sobre el application pool que esta por defecto en el IIS – DefaultAppPool – ya que normalmente uno no lo cambia hasta que lo va a sacar a producción { sin duda un tema completo para otro post ya que son muchas las ventajas de tener corriendo las aplicaciones en diferentes application pools}.

image

Cuando abrí la configuración del DefaultApplicationPool me di cuenta que este esta utilizando en framework 4.0 para ejecutar el proceso que administra mis sitios web.

image

Por supuesto, al estar creando yo mi aplicación en VS 2008, estoy en realidad utilizando el framework 2.0 y por lo tanto procedi a cambiarlo para que utilizara este framework.

image

y listo, despues de esto el sitio Web volvió a funcionar correctamente. Ahora, la pregunta que surge es ¿qué pasa si tengo que ejecutar aplicaciones en ambos frameworks? Pues bien, cuando se instala el Framework 4, se crean un par de application pools que tienen el framework configurado por defecto los cuales son los que se deben utilizar a la hora de utilizar el IIS. Nótese que existe uno integrado y otro clásico, esta diferencia se da por la forma en que queremos que IIS procese nuestros request, utilizando el esquema tradicional de IIS 6 [no recomendado], o el nuevo esquema de IIS 7+ [MUY RECOMENDADO]

image

A la pregunta de como cambiar el Application Pool de nuestra aplicación Web, se debe de ir a la aplicación web en el sitio web en que este creada, y en la parte derecha darle click a la opcoón Advanced Settings, seguidamente se selecciona la elipsis de Application Pool y se escoje el Application Pool deseado.

image

Technorati Tags: ,

11.12.2010

El patrón MVC y sus Repercusiones en las Arquitecturas Orientadas a Servicios

El patrón Model-View-Controller ha existido desde hace muchisismo años. Incluso, las aplicaciones Web que se desarrollan en Java lo implementan por defecto desde hace más de 10 años. Sin embargo, en el stack de tecnologías de Microsoft su uso se viene masificando desde la introducción del mismo con ASP.NET. Esto es una gran noticia porque nos permite aplicarle un patrón a la capa de presentación. En este post sin embargo no me voy a enfocar en las ventajas que podríamos obtener utilizando el MVC si no más bien los problemas que tendríamos si usamos el MVC de manera incorrecta.

El MVC me permite separar la lógica del negocio – dominio – de la forma en que se va a presentar al usuario la información. Esto nos da muchisimas ventajas puesto que puedo variar no solo la forma en que se presentan las pantallas, si no que también no dependo estrictamente de la tecnología que este utilizando en el UI. Algunas otras ventajas se pueden encontrar aquí. Este es el esquema generalizado del patrón MVC.

Sin embargo, cuando pensamos en aplicaciones del tipo “enterprise” tenemos que tener encuenta algunas cosas que siempre nos harán la vida más sencilla a la hora de diseñar y extender nuestras aplicaciones. Por ejemplo, nuestra lógica de negocios no siempre va ser accedida por interfaces de usuario creadas por nosotros mismos, ya que en el mundo interconectado en que vivimos es probable que nuestras organizaciones se comuniquen e integren con otras organizaciones para expander sus posibilidades de negocio, y estos partners no van a querer poner nuestro UI en las máquinas de sus agentes, sino que van a desear consumir nuestro negocios desde sus sistemas. Esto implica que debería existir un servicio – o varios – que le permitan al partner integrar sus sistemas con los nuestros. En este contexto lo ideal es que la lógica de negocios se reutilice a través de una capa de servicios tal y como se muestra en esta imágen tomada de pattern and practices y que reutilicé en un post anterior.

Esto le va a permitir al negocios ventajas tales como:

  • La empresa se asegura que todos los consumidores de la lógica de negocio, utiliza los mismos procesos o flujos, con lo cual podemos tener un proceso estandarizado para todos los usuarios del mismo.
  • Existe verdaderamente reutilización, lo que nos permite ahorrar en el costo de la implementación.
  • Cuando hay un cambio en la lógica del negocio, solo hay que llevar a cabo ese cambio en un solo lugar.
  • Aplico esquemas de autenticación y autorización de forma uniforme en el mismo sitio.
  • La integración con otras aplicaciones es más simple.
  • Interactuar con la nube es más sencillo – es decir llevar aplicaciones desde nuestro datacenters a Windows Azure por ejemplo.

En este contexto, cual sería el esquema de arquitectura que deberíamos utilizar? A continuación se presenta una esquema genérico en donde obtenemos las ventajas mencionadas anteriormente.

image

¿Y que tiene que ver esto con el MVC? Pues bien, el MVC es un patrón para la capa de UI. Esto permite como dije anteriormente crear interfaces más versátiles y más fáciles de cambiar. Sin embargo, si la interacción con la lógica de negocios no esta bien separada, vamos a terminar utilizando el controller como lógica de negocios, y en este caso vamos a quedar con toda la funcionalidad encapsulada y lista para ser utilizada exclusivamente en nuestra aplicación. Esto no esta mal si la aplicación es una unidad de negocio que no interactúa ni expone funcionalidad a otras unidades – aplicaciones – en el contexto de la empresa, lo cual es dificil de encontrar. Además, vamos a disminuir la posibilidad de reutilización ya que la funcionalidad va a queda en el sitio Web – es cierto que existen formas de accederla desde otras aplicaciones pero eso no es la idea, sino más bien lo que se busca es que este disponible directamente desde nuestros servidor de aplicaciones. En lo que respecta a mantenimiento, cualquier cambio que requiera la empresa en su funcionamiento, va a tener que ser hecho en todas las aplicaciones que de alguna forma u otra tienen que ver con el procedimiento, y siendo asi el MVC también debería tener e cambio.

Por lo tanto, el MVC en nuestra esquema anterior de arquitectura debería lucir como se ve en la siguiente figura.

image

Technorati Tags: ,