viernes, 25 de abril de 2008

First Look at Unity

El pasado 4 de Abril del 2008, fue liberada la versión de producción del proyecto Unity.  Este es un IoC Container o contenedor de servicios, que nos permitirá a las aplicaciones existentes desacoplarlas con gran facilidad o las nuevas crearlas desacopladas.  De hecho ya esta Michael Puleilo trabajando en hacer una nueva versión de WCSF con Unity (Ver en: http://blogs.msdn.com/mpuleio/archive/2008/04/04/converting-the-composite-web-application-block-to-unity-intro.aspx ).

Una de las ventajas de Unity es que es un framework liviano que aprendiendo un par de métodos del framework estamos listos para desarrollar soluciones desacopladas.  En este primer ejemplo vamos a ver como Unity nos facilita el trabajo versus realizar el desacoplamiento aplicando el patrón de Dependency Injection a pie.

Veamos el siguiente código escrito en C# 3.0:

 

Tenemos una entidad de negocio llamada cliente:

namespace MyFirstUnityApp.ServicioClienteFld
{
    public class Cliente
    {
        public int? CodigoCliente
        {
            get;
            set;
        }
        public string RazonSocial
        {
            get;
            set;
        }
        public string Direccion
        {
            get;
            set;

        }
    }
}

Y tenemos una intefase que definie un metodo que devuelve un listado de dicha entidad:

 

using System.Collections.Generic;

namespace MyFirstUnityApp.ServicioClienteFld
{
    public interface IClienteServicio
    {
        IList<Cliente> ListarTodo();
    }
}

Ahora una clase que implemente esta interface:

using System.Collections.Generic;

namespace MyFirstUnityApp.ServicioClienteFld
{
    public class ClienteServicio : IClienteServicio
    {
    

       public IList<Cliente> ListarTodo()
        {
            return new List<Cliente>
{

new Cliente

                 {

CodigoCliente = 1, RazonSocial = "Cliente la estrella", Direccion = "zona 10"

                  } ,
new Cliente

                  {

CodigoCliente = 2, RazonSocial = "Ingenio", Direccion = "zona 15"

                  }

            };
        }

      }
}

Recuerda estamos en C# 3.0 podemos crear el contenido del arreglo en la declaración de una vez.  Usualmente aquí hacemos una llamada a la capa de datos, para obtener la información de algún proveedor de datos, pero no es de importancia ahora.

Luego nuestra clase que consumirá nuestro servicio:

namespace MyFirstUnityApp.ServicioClienteFld
{
    public class MostrarListadoClientes
    {
        public MostrarListadoClientes() { }

        public MostrarListadoClientes(IClienteServicio   clienteServicioInyectado)
        {
            _clienteServicio = clienteServicioInyectado;
        }

        private readonly IClienteServicio _clienteServicio;

        public IClienteServicio ClienteServicio { get; set; }

        public IList<Cliente> ListadoClientes()
        {
            return ClienteServicio.ListarTodo();
        }

        public IList<Cliente> ListadoClientesV2()
        {
            return _clienteServicio.ListarTodo();
        }
    }
}

Para este ejemplo definimos tanto un constructor o una propiedad de la clase donde le inyectaremos el servicio.  Esto al momento de hacer en un aplicación real se decide que camino tomar.

Ahora veamos como se consumen los servicios manualmente en las clases que dependen de ellas.

En el primer ejemplo veremos como inyectamos el servicio en el constructor:

MostrarListadoClientes mostrarClientes =

new MostrarListadoClientes(new ClienteServicio());

IList<Cliente> ListadoInstanciaPorConstructor = mostrarClientes.ListadoClientesV2();
ImprimirListado(ListadoInstanciaPorConstructor);

Dentro del constructor MostrarListadoClientes estamos pasmándole la clase que implementa la interface IClienteServicio, como se muestra en la imagen abajo.

image

Ahora veamos como la inyectaríamos el servicio en la propiedad:

MostrarListadoClientes mostrarClientesPorPropiedad = new MostrarListadoClientes();

           mostrarClientesPorPropiedad.ClienteServicio = new ClienteServicio();


       ImprimirListado(mostrarClientesPorPropiedad.ListadoClientes());

Si vemos este código podemos notar que creamos en memoria el objeto primero y luego inyectamos es servicio a la propiedad y por ultimo consumimos el método de la clase que tiene servicios dependientes. 

Ahora esto no es nada complicado, pero imaginese que la clase que implementa IClienteServicio tiene otro servicio que de pende esta misma y esta a otra y así sucesivamente esto tiende a complicarse y hacer engorroso la escritura del código.  Veamos el código de lo que estoy planteando:

IContectividadServicio NuevaConectividadServicio = new ConectividadServicio();

IPermisoServicio NuevoPermisoSerivcio = new PermisoServicio(NuevaConectividadServicio);

IClienteServicio NuevoClienteSerivico = new ClienteServicio(PermisosServicio);

MostrarListadoClientes mostrarClientes =

new MostrarListadoClientes(new ClienteServicio());

IList<Cliente> ListadoInstanciaPorConstructor = mostrarClientes.ListadoClientesV2();
ImprimirListado(ListadoInstanciaPorConstructor);

Aquí es donde entra Unity en acción el código anterior quedaría en Unity de la siguiente forma:

Primero registramos los servicios disponibles en nuestra aplicación, de la siguiente forma:

IUnityContainer container = new UnityContainer()
                .RegisterType<IClienteServicio, ClienteServicio>()
                .RegisterType<IPermisoServicio, PermisoServicio>()
                .RegisterType<IConectividadServicio, ConectividadServicio> ();

Nos pegamos a la interfase que define el contrato del contenedor IoC y luego le pasamos la instancia de UnityContiner y luego registramos todos los servicios, primero la interfase y luego la clase que implementa esta interfase.  Ahora consumamos la clase de la cual depende todos estos servicios y obtengamos el listado del cliente:

IList<Cliente> ListadoInstanciaPorPropiedad = container.Resolve<MostrarListadoClientes>().ListadoClientes();
       

Resolve se utiliza para resolver todas las dependencias de la clase no necesitamos indicarle el momento que debe de inyectarlo, ni siguiera crear en memoria la clase dependiente el lo hace por nosotros.  Si es importante el orden de registrar los servicios debemos empezar del servicio padre o base al servicio hijo o dependiente.

Solo necesitamos etiquetar con un atributo de dependencia en la clase consumidora o dependiente a si como muestro abajo en el código en cada una de las clases. En el orden de dependencia se los muestro a continuación:

public class MostrarListadoClientes
    {
        public MostrarListadoClientes() { }

        [Dependency]
        public IClienteServicio _clienteServicio { get; set; }

        public IList<Cliente> ListadoClientes()
        {
            return _clienteServicio.ListarTodo();
        }

}

 

public class ClienteServicio : IClienteServicio
  {
      [Dependency]
      public IPermisoServicio PermisoServicio
      {
          get;
          set;
      }

      #region IClienteServicio Members
      public IList<Cliente> ListarTodo()
      {
          if (PermisoServicio.IsInRole("usuario", "ListarClientes"))
          {
              return new List<Cliente>
              {
                  new Cliente
                  {
                      CodigoCliente = 1,
                      RazonSocial = "Cliente la estrella",
                      Direccion = "zona 10"
                  }
              ,
                  new Cliente
                  {
                      CodigoCliente = 2,
                      RazonSocial = "Ingenio",
                      Direccion = "zona 15"
                  }
              }
              ;
          }
          else
              return null;
      }

      #endregion
  }

public class PermisoServicio : IPermisoServicio
   {
       [Dependency]
       public IConectividadServicio ConectividadServicio
       {
           get;
           set;
       }

       #region IPermisoServicio Members

       public bool IsInRole(string usuario, string opcion)
       {
           if (ConectividadServicio.EstablecerConectividad())
               return true;
           else
               return false;
       }

       #endregion
   }

public class ConectividadServicio: IConectividadServicio
{
   #region IConectividadServicio Members

    public bool EstablecerConectividad()
    {
        return true;
    }

    #endregion
}

Bueno y esto es solo una muestra sencilla de todo lo que podemos hacer en Unity... En otro artículo vamos a ver como obtenerlo de un archivo de configuración y las distintas alternativas que tenemos en Unity.. además veremos como se implementa el patrón MVP con Unity en un aplicación Windows.  Hasta la próxima Code4Fun !.

Su amigo,

Manolo Herrera

domingo, 20 de abril de 2008

Que paso con los buenos modales y la buena formación

Revisando un código, me di cuenta que por alguna razón se nos esta olvidando los buenos modales y la buena formación y me refiero cuando escribimos código. Los siguientes tips, sin ser los únicos, si hacen la diferencia en algún momento en nuestro código. Estos tips se basan en la disciplina de "Refactoring" que nos indica que cada vez que modificamos algo tenemos la oportunidad de mejorar su funcionamiento interno sin alterar el externo y esto acompañado con las pruebas necesarias que nos garanticen que no estamos rompiendo la funcionalidad de nuestro código. Aquí les va:

En VB.Net para definir un tipo utilizamos las palabras reservadas Dim y as como sigue:

Dim x as NuevaClase

... pero esto no es lo mismo en C# podemos utilizar la palabra reservada as para comprobar en una sola línea si al tipo que deseamos castear es valido de lo contrario en vez de devolverme un error me devuelve un nulo como se muestra a continuación:

NuevaClase _nueva = objecto as NuevaClase;

Esto es equivalente a:

NuevaClase _nueva;

if (objecto is NuevaClase) _nueva = (Nuevaclase)objecto;

Este única palabra o prepocisión de C# hace muy eficiente nuestro código, veamos este ejemplo:

Es usual in ASP.NET utilizar el objeto ViewState para guardar información que necesitamos persistir por lo que normalmente definimos dentro de la clase parcial de la pagina una propiedad utilizando el ViewState, de la siguiente manera:

private ClaseUsuario ClaseUsuarioSeleccionada

{

get

{

if (ViewState["ClaseUsuarioSeleccionada"] != null &&

ViewState["ClaseUsuarioSeleccionada"] is ClaseUsuario)

{

return (ClaseUsuario)ViewState"ClaseUsuarioSeleccionada"];

}else

return null;

}

set{ViewState["ClaseUsuarioSeleccionada"] = value;}

}

Ahora veamos el mismo código optimizado por la cláusula "as":

private ClaseUsuario ClaseUsuarioSeleccionada

{

get

{

return ViewState["ClaseUsuarioSeleccionada"] as ClaseUsuario;

}

set{ViewState["ClaseUsuarioSeleccionada"] = value;}

}

Arriba en el getter si no puede castearlo devuelve nulo y listo, nuestro código esta fuera de peligro de generar alguna excepción.

Así mismo desde la version 2.0 del .NET framework tenemos del TypeBase.TryBase(); donde TypeBase puede ser cualquier tipo base del framework como int, decimal, double, bool, etc.

No es recomendable utilizar el Convert.ToInt32() o el Int.Parse() porque si no puede castearse levantará una excepción es mejor utilizar el TryInt. Veamos un ejemplo:

int CodigoObtenido;

if (int.tryParse(TextBox1.Text, out CodigoObtenido)

{

..... //Segmento de Codigo

}else

MessageBox.Show("Valor ingresado debe de ser entero");

Este es mejor que:

int CodigoObtenido = int.Parse(TextBox1.Text);

y mucho mas eficiente que:

try

{

int CodigoObtenido = int.Convert(TextBox1.Text);

}

Catch(Excepcion as ex)

{

MessageBox.Show("Valor ingresado debe de ser entero");

}

Otras recomendaciones:

No es recomendable escribir código en los métodos invocados con eventos sino crear un método que encapsulen la tarea, esto es porque puede ser reutilizando dicha operaciones y por otro lado si cambia la pagina es mucho mas facil ubicarla, veamos el siguiente ejemplo:

protectec void PersistirInfo_Click(object sender, EventArgs e)

{

PersistirInformacionIngresada();

}

Utilicemos los nombres con claridad, encapsulado segmentos de código en métodos esto lo hace mas legible y fácil de encontrar lo que buscamos, veamos el siguiente ejemplo:

protected void OtrosMovimientosConfirmarNuevo_Click(object sender, EventArgs e)
{
Page.Validate("Otros");

if (Page.IsValid)
{
try
{
ConciliacionBancariaDetalleOtrosMovimientos conciliacionOM = new ConciliacionBancariaDetalleOtrosMovimientos();
conciliacionOM.CodigoConciliacionBancaria =
OtrosMovimientosListaConciliaciones.ConciliacionBancariaSeleccionada != null
? OtrosMovimientosListaConciliaciones.ConciliacionBancariaSeleccionada.CodigoCorrelativo: null;

conciliacionOM.CodigoTipoOperacionBancaria =
OtrosMovimientosTipoOperacionBancaria.TipoOperacionBancariaSeleccionada.
CodigoTipoOperacionBancaria;

conciliacionOM.Descripcion = OtrosMovimientosDescripcion.ValorSeleccionado;
conciliacionOM.Fecha = OtrosMovimientosFecha.FechaSelected.Value;
conciliacionOM.NumeroReferencia = OtrosMovimientosNumeroReferencia.Text;
conciliacionOM.Valor = OtrosMovimientosValor.ValorSeleccionado;
conciliacionOM.UsuarioSistema = Page.User.Identity.Name;
ConciliacionBancariaDetalleOtrosMovimientosBLL.Crear(conciliacionOM);

ConfirmaLabel.Text = "Se ingreso un nuevo registro exitosamente."

OtrosMovimientosNumeroReferencia.Text = null;
OtrosMovimientosDescripcion.ValorSeleccionado = null;
conciliacionOM.Valor = null;

if (ConciliacionBancariaSeleccionada != null)
{
string NombreEmpresa = ObtenerNombreEmpresa(ConciliacionBancariaSeleccionada.CodigoEmpresa);
PrepararEdicionConciliacion(NombreEmpresa, ConciliacionBancariaSeleccionada.NombreCuenta, ConciliacionBancariaSeleccionada.FechaInicial.Value.ToShortDateString(), ConciliacionBancariaSeleccionada.FechaFinal.Value.ToShortDateString(), ConciliacionBancariaSeleccionada.CodigoCYBConciliacionBancaria.Value, ConciliacionBancariaSeleccionada.CodigoCorrelativo.Value);

}

}
catch (Exception Error)
{
ErrorLabel.Text = Error.Message;
//throw;
}

}
}

Que Entiende ud. en este código, y ud. me dirá acaso yo conozco las reglas de su negocio o yo se para que escribieron este código?.. y son validas al ver el código de Arriba pero que sucede si usted ve lo siguiente:

protected void OtrosMovimientosConfirmarNuevo_Click(object sender, EventArgs e)
{

PersistirOtrosMovimientosConciliacionBancaria();

}

private void PersistirOtrosMovimientosConciliacionBancaria()

{

If (EsValidaCapturaUsuario())

{

ConciliacionBancaria NuevaConciliacion = ObtenerInfoConciliacion();

PersistirNuevaConciliacion(NuevaConciliacion);

}

}

De Inmediato primero por el nombre del método sabemos de que se trata y luego en 3 líneas de código sabemos lo que hace, validar la información capturada llenar la entidad de negocio y luego persistir la información capturada.

Amigos, regresemos a los buenos modales y a la buena formación. Que bueno será que cuando nos revisen nuestro código o el legado que dejemos sea grato a los ojos de otro socio de la industria..

Code4Fun!,

Manolo Herrera

miércoles, 9 de abril de 2008

Web Client Software Factory Que es y que no es?

No es un generador de código, no amigos...para nada. Una Software Factory es mucho mas que eso y es necesario mencionarlo para apreciar una gema del software que tendrá un futuro prominente que seguramente alcanzará una madurez sin precedentes.

Si nos metemos en los pensamientos de algunos desarrolladores podaríamos expresar:

"Desarrollar con las WCSF es ordenarse...es programar elegantemente.. es complicar las cosas que suelo hacer con menos código.. es gastar mi tiempo en escribir mas código detallado... donde genero mis controles de usuario.. no es simplemente bonito, ordenado, "desacoplado" o por el otro lado.. necesito escribir mas código al que estoy acostumbrado.."

Para no pasar de noche y apreciar el trabajo y el potencial y madurez que podemos alcanzar desarrollando software con esta conjunto de modelos, patrones, mejores prácticas, automatización del esquema de trabajo, infraestructura "plug & ready", para la seguridad, manejo de errores, registro de bitácora, navegación, inyección de caché, validación de datos, inyección de servicios a nivel de configuración en tiempo de corrida, recetas de cocina para la creación de componentes basados en el modelo Model View Presenter, programación orientada a aspectos, Dependency Inyection, Inversion of Control container y muchos mas.

Solo devengándonos un momento a pensar en el trabajo duro y a la dedicación que debe darse a un equipo desarrollo para que tan siquiera de luces de trabajar bajo estándares, modelos, patrones, mejores prácticas y garantizar que no se pasen de la raya, que tengan un camino y una infraestructura disponible que sea suficientemente bien diseñada para que pueda acoplarse aunque no se desarrolle en el mismo equipo y mantenga una apariencia consistente, y una reutilización de código real y eficiente.. esto a sido exitosamente alcanzado por la WCSF y sigue madurando.

La WCSF para un arquitecto es un sueño plasmado en una infraestructura lista para trabajar y para el desarrollador la forma en que su trabajo complementará y contribuirá con el socio de al lado. Podemos decir que WCSF es : Pro-Testing. Pro-Modularity. Pro-Team Work. Pro-Improve QA.

Veamos algo de historia:

Imagine construir una aplicación que a pesar de su complejidad y tamaño, necesita descomponer se y desarrollarse en varios equipos, que se ensamble en tiempo de corrida, unos encargados en la infraestructura común y a su vez que la apariencia de la interfase de usuario de cada modulo sea congruente y desacopladas entre cada uno de ellos. Que se puedan exponer servicios y se puedan compartir entre los módulos. Este escenario fue inicialmente resuelto por la Composite UI Application Block (CAB) y luego por Smart Client Software Factory. Luego este escenario fue dirigido para Windows Mobile 5: Mobile Client Software Factory. Y para las aplicaciones Web integradas la Web Client Software Factory fue desarrollada. (Extraído del siguiente articulo: http://blogs.msdn.com/francischeung/archive/2008/01/28/composite-wpf-guidance.aspx )

Para comprender como todo esta infraestructura trabaja en conjunto basta con echar un vistazo a los elementos de las componen:

1) En la parte de Application Blocks tenemos:

La Composite Web Application Block , el Object Builder y las famosas Enterprise Library en su version 3.1.

En la CWAB tenemos toda la tubería responsable de la infraestructura de una aplicación Web orientada al modelo MVP (Model View Presenter; incluye la definición de como se inyecta el presenter en la pagina web (Presenter<TView>)) , la definición de los modulos, los servicios de contexto (HttpContext), de sesión (HttpSessionState y StateValue<T>, los servicios que descubre del servidor (HttpServerUtility) y la infraestructura de seguridad definida por roles y reglas. También podemos encontrar la librería para acceder los serivicos a través de la configuración, y la reutilización de proveedores bajo el modelo desacoplado el sitemap y Autorization providers.

No menos importante, tenemos dentro del mismo dll, el amigo Object Builder, encargado de contener e instanciar en memoria todos los servicios que a lo largo y ancho de la WCSF son inyectados. No hay una clara separación entre la CWAB y el contenedor de servicios es mas una mezcla de ambos, de allí el éxito sin precedentes que tendra UNITY el contenedor de IoC que no solo es liviano sino que esta claramente separado y definidas sus tareas y responsabilidades, esto no da una efectiva aplicación de un diseño desacoplado sobre aplicaciones que no lo eran y que gradualmente pueden mutarse a un diseño con una solución excepcional en la búsqueda del desarrollo por componetes, modularidad y testing de nuestras aplicaciones. Puedes saber mas al respecto visita: http://msdn2.microsoft.com/en-us/library/aa137950.aspx .

Las Enterprise Library 3.1 (May 2007) Estas proveen de un alto contenido de servicios de infraestructura paras las WCSF´s que el desarrollador puede disponer inmediatamente de los mismos. Entre estos servicios tenemos: Caché, Encripción, mejores practicas de acceso a datos y manejo de excepciones, bitácora (logging), seguridad que se funciona con la solución de la CWA, validación y la inyección de cada uno de estos servicios como políticas que pueden ser implementadas de una forma excepcional, como si fuera poco todo esto configurable a través del archivo de configuración de la aplicación web y el manejo de atributos dentro de las clases de .net. Si amigo hay mucho porque sacarle raja a las WCSF!. (Mas información en: http://msdn2.microsoft.com/en-us/library/aa138002.aspx )

2) La automatización de las recetas o Guidance Automation:

Si ud. se ha preguntado para que tiene que instalar las GAX (Guidance Automation Extensions) y la GAT (Guidance Automation Tool Kit) he aquí la respuesta.

la GAX esta dirigida al desarrollador para automatizar tareas como al momento de crear una pagina bajo el modelo MVP, es necesario invocar las librerías de la CWA y de las Enterprise library y crear los archivos con código en diferentes módulos esto le permite al desarrollador ahorrar tiempo y le al arquitecto la tranquilidad que hay una receta que respeta este modelo de arquitectura MVP, entre uno de los muchos modelos y patrones que tiene embebida la WCSF. Para el arquitecto esta dirigida la GAT ya que le permitirá crear "Templates" para automatizar ciertas tareas bajo la arquitectura definida en la WCSF. Es decir no es un generador de código, sino dentro de las capacidades y limitaciones de los templates de VSTO facilita algunas tareas que pueden ser susceptibles al error de escritura o a romper el modelo y patrones de la WCSF, esto permitirá de alguna forma garantizar que la solución creada será altamente desacoplada, bajo estándares y mejores practicas orientada al Testing para garantizar la calidad del producto que se desarrolla en especial para equipos de trabajo que lidian con el problema de acoplar las partes y dar una apariencia de composición integrada.

3) Por ulitmo cabe mencionar que las WCSF aplica los siguientes patrones de diseño de la industria de software mundialmente reconocidos:

Application Controller: Crea un objeto separado para controlar y centralizar el flujo de la pagina y la lógica de la navegación de la vista.

Dependency Injection (Mi Favorito) Expresión declarativa de las dependencias en la definición de una clase, que utiliza un objeto constructor para obtener instancias de los objetos dependientes durante su creación o inicialización.

Inversion of Control (El éxtasis) Delega la función de seleccionar una implementación concreta de un tipo para las clases dependientes de un componente externo o fuente. Nos hace el trabajo de contener los servicios requeridos para inyectarlos cuando se requieren. Ejemplo de esta Implementación es UNITY (Mua!).

Model View Presenter (Hecho para desarrollar componentes que pueden ser probados) Separa las responsabilidades para el despliegue visual y el comportamiento del manejo de los eventos dentro de diferentes clases (View & Presenter) . La Vista maneja los controles de la pagina y dispara los eventos al presentador. Este contiene la lógica para responder los eventos, actualizar el modelo (la lógica de negocio y la info. de la aplicación) y guardar el estado de la vista.

Module Interface Separation Para crear soluciones para equipos de trabajo ser requiere sea separada modularmente una solución que garantice su futuro acoplamiento. Este patrón tiene como objetivo cubrir esta necesidad. El modulo es partido en dos ensamblados el de interfaces y el de la implementación del modulo. El primero contiene interfaces de los servicios y las entidades de negocio, el segundo solo información referente al modulo en sí.

Responsivness Patterns Básicamente son patrones de ajax que estan enfocados a crear Interfaces de usuario de responden rápido a la entrada del usuario. Entre estos están: Display Morphing, Live Form, Live Search, Progress Indicator, User Action, etc. Mas información en: http://msdn2.microsoft.com/en-us/library/cc304779.aspx .

Service Locator Contiene la referencia de los servicios y encapsulan la lógica de los mismos. Este obtiene la instancia de los servicios disponibles.

Bueno espero haber despertado el interes, aclarado algunas dudas y motivado a si quiere desarrollar una aplicación orientada a las pruebas para garantizar la calidad, y tiene las complicaciones del los equipos de trabajo y quiere utilizar toda la experiencia, tecnicas y servicios que le provee la WCSF esta es una solución adecuada y que su facil o bajo mantenimiento le pagará devuelta la inversión que haga incialmente para incorporar esta solución.

En el futuro estaremos escribiendo uno a uno los servicios de la WCSF para aprovechar todo el potencial esta solución y para motivarlo amigo bloguero a que mejore su calidad de código y aprecie el esfuerzo de los amigos de P&P que han entregado en sus manos para que ud. y yo mejores. Pronto estaré hablando de UNITY que es una solución tan práctica y poderosa tanto que nuestro amigo Michael Puleio, esta creando una nueva version WCSF con Unity (http://blogs.msdn.com/mpuleio/archive/2008/04/04/converting-the-composite-web-application-block-to-unity-intro.aspx).

Hasta la vista, Code4Fun!,

Manolo Herrera