Welcome to Kartones.Net Sign in

El framework de coco

No te acostaras sin saber una o dos cosas mas ...

La Capa de Presentación : El Patrón MVP

El patrón Modelo Vista Presentador (MVP) es un patrón derivado del patrón Modelo Vista Controlador (MVC) que nos ayuda a ofrecer una clara separación entre la vista, el modelo y el controlador.

La clave del patrón MVP es una estricta regulación de la interacción entre la vista y el controlador, aunque en el patrón MVP, al controlador se le conoce como presentador.

La vista y el modelo de datos son claramente separados a través de un contrato (interfaz) que expone la vista y al cual el presentador accede de modo polimórfico.

Resumiendo, podemos decir que el patrón MVP es una mejora del patrón MVC basado en tres características :

  • La vista no conoce el modelo.
  • El presentador es independiente de la tecnología de interfaz de usuario.
  • La vista y el presentador es testeable puesto que esta basada en un contrato.

Mediante el uso de un contrato en la vista, podemos testear la propia vista y el presentador de modo independiente :

patronMVP[1]

En aplicaciones web ASP.NET, las vistas se representan a través de formularios web, y en aplicaciones Windows a través de formularios Windows.

En la implementación de la vista, tenemos dos opciones :

  1. Una vista pasiva
  2. Una vista activa

Si optamos por una vista pasiva, obtendremos un mayor grado de testeabilidad por que la lógica representada por el contrato se reducirá al mínimo, sin embargo aumentaremos la complejidad en el presentador.

Si optamos por una vista activa que contiene lógica como el enlace y el formateo de datos, necesitaremos implementar una funcionalidad extra que convertirá la vista en menos testeable.

El presentador es el componente encargado de “presentar” las acciones del usuario al sistema y obtener la respuesta del mismo.

El presentador se ubica entre la vista y el modelo, y actúa de la siguiente manera :

  1. Recibe datos de la vista
  2. Convierte los datos de la vista en acciones que se ejecutan contra el sistema
  3. Con la respuesta del sistema, actualiza los datos de la vista.

Las acciones del usuario que requieran navegación a otra vista, deberán ser delegadas en el presentador, el cual será responsable de aplicar la redirección a la vista correspondiente.

El patrón MVP, es un patrón que no puede ser implementado sin haber hecho un análisis  previo que determine que miembros deben formar parte del contrato de cada vista.

Una vez que tenemos claro el contrato que debe implementar cada vista, podemos desarrollar la lógica de presentación de forma paralela al diseño gráfico.

El patrón MVP puede ser caro de implementar en aplicaciones relativamente sencillas, sin embargo brilla en escenarios de grandes aplicaciones.

SecuenciaMVP[1]

En un escenario de patrón Modelo Vista Presentador, lo primero que debemos hacer es definir el contrato de cada vista, cada formulario tiene su propia interfaz para hablar con el presentador correspondiente.

El contrato de la vista identifica el modelo de datos que soporta la vista.

Veamos un ejemplo :

EjemploVistaMVP[1]

La funcionalidad de la vista de la imagen anterior, esta basada en permitir la edición y el alta de empleados, partiendo de esta base, podemos implementar el siguiente contrato para la vista :

public interface IVistaEmpleado
{
    int IDEmpleado { get; set; }

    int IDCentro { get; set; }

    string Nombre { get; set; }

    string Apellido1 { get; set; }

    string Apellido2 { get; set; }

    int IDCategoria { get; set; }

    int IDDepartamento { get; set; }

    int IDEmpleadoResponsable { get; set; }
}

El uso de modificadores “get” y “set” en los miembros de la interfaz, dependerá de las características que queremos que soporte la vista, en nuestro ejemplo la vista será utilizada para modificar y dar de alta empleados, por tanto necesitaremos ambos modificadores.

El siguiente fragmento de código representa la implementación de la vista mediante un formulario ASP.NET :

public partial class frmEditarEmpleado : Page, IVistaEmpleado
{
    #region IVistaEmpleado Members

    public int IDEmpleado
    {
        get { return int.Parse(txtIDEmpleado.Text); }
        set { txtIDEmpleado.Text = value.ToString(); }
    }

    public int IDCentro
    {
        get { return int.Parse(ddlIDCentro.SelectedValue); }
        set { ddlIDCentro.SelectedValue = value.ToString(); }
    }

    public string Nombre
    {
        get { return txtNombre.Text; }
        set { txtNombre.Text = value; }

    }

    public string Apellido1
    {
        get { return txtApellido1.Text; }
        set { txtApellido1.Text = value; }
    }

    public string Apellido2
    {
        get { return txtApellido2.Text; }
        set { txtApellido2.Text = value; }
    }

    public int IDCategoria
    {
        get { return int.Parse(ddlIDCategoria.SelectedValue); }
        set { ddlIDCategoria.SelectedValue = value.ToString(); }
    }

    public int IDDepartamento
    {
        get { return int.Parse(ddlIDDepartamento.SelectedValue); }
        set { ddlIDDepartamento.SelectedValue = value.ToString(); }
    }

    public int IDEmpleadoResponsable
    {
        get { return int.Parse(ddlIDResponsable.SelectedValue); }
        set { ddlIDResponsable.SelectedValue = value; }
    }

    #endregion

    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

Cuando la vista se carga por primera vez, se debe crear una instanciar del presentador y guardarla internamente en un campo privado :

public partial class frmEditarEmpleado : Page, IVistaEmpleado
{
    private PresentadorEmpleado presentador;

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        presentador = new PresentadorEmpleado(this);
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            presentador.InicializarVista();

            if (Request["Id"] != null)
            {
                int IdEmpleado = int.Parse(Request["Id"]);

                presentador.CargarEmpleado(IdEmpleado);
            }
        }
    }

    // [ IVistaEmpleado Members ]
}

Como podemos observar la vista contiene una referencia al presentador, y el presentador contiene una referencia a la vista.

La mejor forma de crear una clase presentador es con los siguientes miembros :

  • Un método de inicialización
  • Un método de actualización de la vista
  • Un conjunto de métodos que ejecutan métodos de la capa de servicios / negocio

Veamos la implementación de nuestro presentador :

public class PresentadorEmpleado
{
    private readonly IVistaEmpleado _vista;

    public PresentadorEmpleado(IVistaEmpleado vista)
    {
        _vista = vista;
    }

    public void CargarEmpleado(int IdEmpleado)
    {
        // Llamada a la capa de servicios / negocio ..
        Empleado emp = RepositorioEmpleado.Obtener(IdEmpleado);

        ActualizarVista(emp);
    }

    public void InicializarVista()
    {
        _vista.Apellido1 = string.Empty;
        _vista.Apellido2 = string.Empty;

        // ..
    }

    public void ActualizarVista(Empleado empleado)
    {
        _vista.Apellido1 = empleado.Apellido1;
        _vista.Apellido2 = empleado.Apellido2;
        _vista.IDCategoria = empleado.Categoria.ID;

        // ..
    }
}

Como se puede observar, el presentador cuelga una referencia a la vista y desconoce por absoluto si se trata de una vista ASP.NET o una vista WinForms, todo lo que sabe es que tiene una referencia a un objeto que implementa una interfaz.

El presentador lee y escribe el estado de la vista a través de los miembros de la interfaz.

A través de la interfaz de la vista, el presentador recoge todos los datos que necesita para ejecutar la acción solicitada en la capa de servicios / negocio.

Para actualizar la vista, el presentador solo tiene que asignar nuevos valores a las propiedades expuestas por la interfaz de la vista.

Para ayudarnos a implementar el patrón MVP, podemos apoyarnos en los componentes y librerías reusables de Web Client Software Factory (WCSF) ya que nos permiten aplicar varias prácticas y patrones en aplicaciones ASP.NET.

Podemos descargar Web Client Software Factory desde esta URL :

http://webclientguidance.codeplex.com/

Como comentamos antes, una de las responsabilidades del presentador es exponer funcionalidad para la navegación entre vistas, uno de los beneficios de usar WCSF, es que disponemos de un bloque para implementar flujos de interfaz de usuario a través de formularios web.

Mediante el bloque PFAB (Page Flow Application Block) podemos orquestar la secuencia de formularios web que necesitamos para completar los flujos de interfaz de usuario.

El bloque PFAB de Web Client Software Factory está basado en Windows WorkFlow Foundation y Enterprise Library.

Y eso ha sido todo por hoy ..



Leave a Comment

(required ) 

(required ) 

(optional )

(required ) 


Captcha