Patrón Modelo-Vista-Modelo de Vista (MVVM) Explicado

Traducción aproximada del artículo Model-View-ViewModel (MVVM) Explained publicado en inglés por Jeremy Likness el 14 de abril del 2010 en su blog C#er:Image.


El propósito de este artículo es dar una introducción al patrón Modelo-Vista-Modelo de Vista (Model-View-ViewModel en inglés y abreviado como MVVM). Aunque he participado en numerosas discusiones en línea sobre el tema, me parece que los que están principiando encuentran poco material disponible y tienen que vadear entre múltiples recursos contradictorios antes de poder usar el patrón en su código. Mi idea no es declarar dogmas, sino más bien agrupar varios conceptos en solo artículo con el fin hacer más fácil la tarea de entender y apreciar el valor de dicho patrón. MVVM es mucho más simple de lo algunos lo hacen parecer.


¿Por qué debería interesarme el MVVM?

¿Qué razón hay, como desarrolladores, para siquiera poner atención al Modelo-Vista-Modelo de Vista? El patrón aporta varios beneficios tanto a WPF como a Silverlight. Antes de continuar, vale preguntarse:


  • ¿Necesito compartir mi proyecto con un diseñador y tener la flexibilidad de que ambos aspectos de diseño y desarrollo se lleven a cabo casi simultáneamente?
  • ¿Requiero pruebas unitarias comprensivas para mis soluciones?
  • ¿Es importante para mí el tener componentes reutilizables tanto dentro de un proyecto como a través de mi organización?
  • ¿Desearía yo tener mayor flexibilidad para poder cambiar la interfase al usuario en una aplicación sin tener que reorganizar su lógica?


Una respuesta afirmativa a cualquiera de estas preguntas indica que es buena idea investigar el MVVM. Estos son sólo algunos de los beneficios que puede otorgarle a sus proyectos.

Me asombran algunos de los diálogos que a veces encuentro en la red. Argumentos como “MVVM sólo tiene sentido en interfaces gráficas extremadamente complejas” o “MVVM conlleva demasiado esfuerzo y es excesivo para aplicaciones pequeñas.” El colmo es escuchar que “MVVM no es adaptable.” En mi opinión, declaraciones como éstas se refieren a ideas preconcebidas o implementaciones específicas de MVVM y no al patrón en sí. Dicho de otra forma, si toma horas ensamblar una aplicación usando MVVM, entonces algo no se está haciendo bien. Si la aplicación no es flexible, la culpa no es del modelo, sino de la forma en la que se le usa. Por ejemplo, sin importar el patrón usado, sería ridículo tratar de enlazar 100 000 artículos a un control ListBox.

Así que, antes de continuar, una pequeña aclaración: en vez de presentarlo como una verdad absoluta, lo que voy a hacer es explicar la forma en la que yo veo MVVM. Los animo a que compartan sus puntos de vista y experiencias en área de comentarios. Si les parece que algo no es correcto, déjenmelo saber y trataré de mantener este artículo actualizado.


MVVM a grandes rasgos

Examinemos las partes principales de MVVM, empezando con un fundamento esencial para toda aplicación: los datos. Estos son contenidos en el modelo.


El Modelo

El modelo se encarga de mantener la información.El modelo representa los datos o información con la que trabajamos y por eso me gusta  llamarlo el objeto del dominio. Un ejemplo de modelo puede ser un contacto (con su nombre, número de teléfono, dirección y demás) o la descripción de un punto de publicación para un medio audiovisual transmitido en vivo.

La clave para recordar el modelo es que contiene la información, pero no las acciones o servicios que la manipulan. No es responsable de darle forma para que se vea bien en la pantalla, o de obtener una lista de elementos de un servidor remoto (de hecho, en tal lista cada elemento sería a su vez un modelo). La lógica de la aplicación o “reglas empresariales” son generalmente mantenidas en clases separadas del modelo y actúan en él. Aunque no siempre es cierto, a veces el modelo puede validar la información.

No es fácil mantener el modelo nítido, especialmente al representar entidades del mundo real. Por ejemplo, el registro de un contacto puede que incluya la fecha en que fue modificado por última vez junto con la identidad de quien hizo la modificación (para efectos de auditoría), demás de identificador único (usado en la base de datos o similar). La fecha de modificación no tiene ninguna conexión con el contacto en la vida real, pero es un efecto secundario asociado con la forma en la utilizamos, le damos seguimiento, y la almacenamos en el sistema.

Veamos, por ejemplo,un posible modelo para mantener información sobre un contacto:


namespace MVVMExample
{
  public class ContactModel : INotifyPropertyChanged
  {
    private string _firstName;

    public string FirstName
    {
      get { return _firstName; }
      set
      {
          _firstName = value;
          RaisePropertyChanged("FirstName");
          RaisePropertyChanged("FullName");
      }
    }

    private string _lastName;

    public string LastName
    {
      get { return _lastName; }
      set
      {
          _lastName = value;
          RaisePropertyChanged("LastName");
          RaisePropertyChanged("FullName");
      }
    }

    public string FullName
    {
      get { return string.Format("{0} {1}",
                                 FirstName,
                                 LastName); }
    }

    private string _phoneNumber;

    public string PhoneNumber
    {
      get { return _phoneNumber; }
      set
      {
          _phoneNumber = value;
          RaisePropertyChanged("PhoneNumber");
      }
    }

    protected void RaisePropertyChanged(string propertyName)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
          handler(this,
                  new PropertyChangedEventArgs(propertyName));
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public override bool Equals(object obj)
    {
      return obj is ContactModel &&
             ((ContactModel) obj).FullName.Equals(FullName);
    }

    public override int GetHashCode()
    {
      return FullName.GetHashCode();
    }
  }
}


La Vista

Mountains lake La vista es la parte con la que estamos más familiarizados y la que ve el usuario. Su papel es representar la información, tomándose a veces ciertas libertades con el fin de hacerla más clara o presentable. Por ejemplo, una fecha podría ser representada en el modelo como el número de segundos contados desde la medianoche del primero de enero de 1970 (Tiempo Unix). Sin embargo, el número es presentado al usuario en forma de día, mes y año en su zona horaria local. Una vista puede también contener ciertos comportamientos, como el aceptar la entrada de datos. La vista se encarga de esta faceta (teclas presionadas, movimientos del ratón, gestos en una pantalla táctil, y así por el estilo) que eventualmente ejerce influencia en las propiedades del modelo.

En MVVM la vista es activa. A diferencia de una vista pasiva sin conocimiento del modelo, y bajo el manejo total de un controlador o presentador, la vista en MVVM contiene comportamientos, eventos y enlaces a datos que, hasta cierto punto, necesitan saber sobre el modelo subyacente y el modelo de vista. Aunque tales eventos y comportamientos son asociados a propiedades, métodos y comandos, la vista es aún responsable de manejar sus propios eventos y no pasa esta tarea al modelo de vista.

Algo digno de recordar sobre la vista es que no es responsable de llevar cuenta de su estado. El modelo de vista se encarga de ello y mantiene la vista al tanto de los cambios.

La siguiente es una vista de muestra expresada en XAML:


<UserControl x:Class="MVVMExample.DetailView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot"
          Background="White"
          DataContext="{Binding CurrentContact}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="Name:"
                   HorizontalAlignment="Right"
                   Margin="5"/>
        <TextBlock Text="{Binding FullName}"
                   HorizontalAlignment="Left"
                   Margin="5"
                   Grid.Column="1"/>
        <TextBlock Text="Phone:"
                   HorizontalAlignment="Right"
                   Margin="5"
                   Grid.Row="1"/>
        <TextBlock Text="{Binding PhoneNumber}"
                   HorizontalAlignment="Left"
                   Margin="5"
                   Grid.Row="1"
                   Grid.Column="1"/>
    </Grid>
</UserControl>


Noten que los diferentes enlaces son los puntos de integración o sincronización con el modelo de vista.


El modelo de vista (Nuestro controlador o presentador)

El controlador actúa como intermediario entre el modelo y la vista.El modelo de vista introduce el concepto de Separación de la Presentación, es decir, mantiene al modelo separado y protegido de los minuciosos detalles de la vista. Por eso es que el modelo de vista es la pieza clave del trío. Esta separación permite que el modelo se limite a contener los datos, en vez de verse obligado a saber la forma en que se presenta una fecha al usuario y tener que hacer la conversión de formato. De igual manera, la vista sólo tiene que presentar la fecha. El controlador trabaja como intermediario entre ambos, recibiendo información de la vista e insertándola en el modelo, o actuando con un servidor para obtener datos del modelo y luego convertirlos en propiedades que pueden ser usadas en la vista.

El modelo de vista también hace disponibles métodos, comandos y otros puntos de acceso que ayudan a mantener el estado de la vista, manipular el modelo en respuesta a acciones de la vista y disparar eventos en la misma.

Si bien ya había estado evolucionando entre bastidores por bastante tiempo, John Gossman introdujo el MVVM al público en general en un artículo de su blog de Microsoft en el 2005 tratando sobre Avalon (el sobrenombre para Windows Presentation Foundation, o WPF). El artículo, titulado Introduction to Model/View/ViewModel pattern for building WPF Apps generó un gran revuelo a juzgar por los comentarios de los que trataban de comprenderlo.

En ocasiones he escuchado al MVVM descrito como una implementación del Patrón de Modelo de Presentación diseñada específicamente para QPF (y posteriormente Silverlight).

Los ejemplos del patrón generalmente enfatizan el uso de XAML para definir la vista y enlaces de datos para los comandos y propiedades. Tales detalles no son intrínsecos del patrón sino más bien detalles de su implementación. Por eso es que señalo el enlace a datos con un color diferente:


Diagrama del papel del enlace de datos en el patrón MVVM.


Abajo presento un ejemplo de un posible modelo de vista donde hemos creado una clase BaseINPC (siglas en inglés para “INotifyPropertyChanged”) proveyendo un método que facilita generar el evento de notificación cuando se altera alguna de las propiedades.


namespace MVVMExample
{
  public class ContactViewModel : BaseINPC
  {
    public ContactViewModel()
    {
      Contacts = new ObservableCollection<ContactModel>();
      Service = new Service();

      Service.GetContacts(_PopulateContacts);

      Delete = new DeleteCommand(
          Service,
          ()=>CanDelete,
          contact =>
            {
                CurrentContact = null;
                Service.GetContacts(_PopulateContacts);
            });
    }

    private void _PopulateContacts(
                             IEnumerable>ContactModel> contacts)
    {
      Contacts.Clear();
      foreach(var contact in contacts)
      {
        Contacts.Add(contact);
      }
    }

    public IService Service { get; set; }

    public bool CanDelete
    {
      get { return _currentContact != null; }
    }

    public ObservableCollection<ContactModel> Contacts
        { get; set; }

    public DeleteCommand Delete { get; set; }

    private ContactModel _currentContact;

    public ContactModel CurrentContact
    {
      get { return _currentContact; }
      set
      {
        _currentContact = value;
        RaisePropertyChanged("CurrentContact");
        RaisePropertyChanged("CanDelete");
        Delete.RaiseCanExecuteChanged();
      }
    }
  }
}


Como se puede notar, este modelo de vista fue diseñado para administrar una lista de contactos, incorporando un comando para eliminarlos y una señal indicando se se permite borrar datos (por lo tanto, manteniendo el estado de la vista). Generalmente la bandera sería parte del comando, pero este ejemplo está basado en Silverlight 3 que no es compatible con el enlace de comandos, y yo quise demostrar una solución simple sin recurrir a una infraestructura excesiva. (Les recomiendo ver este vídeo que demuestra lo fácil que es convertir el ejemplo de Silverlight 3 a 4 y usar el sistema nativo de comandos). El  modelo de vista en el listado anterior hace una referencia concreta al servicio.

Para aplicaciones de mayor escala prefiero conectar la referencia de manera externa o usando una infraestructura de inyección de dependencias. Lo chévere es la flexibilidad de construirlo de esta manera inicialmente y luego reorganizarlo según se necesite—de nuevo, como se puede ver en el ejemplo, no es estrictamente necesario usar una infraestructura o biblioteca externa para implementar el patrón. En nuestro caso, el modelo de vista va y obtiene la lista de contactos inmediatamente. Por el momento es una lista predeterminada con mis detalles y los de alguien un poco más conocido. Por si acaso, los números de teléfono son falsos.

Seamos un poco más específicos y veamos como podríamos implementar esto en una aplicación de muestra. Una vista de rayos X de su configuración en MVVM se vería así:


Diagrama elaborado de una aplicación construida usando MVVM.


¿Qué podemos discernir de este vistazo?

Primero, IConfig representa un servicio de configuración (en un lector de mensajes de la red podría contener información sobre la cuenta y los suministros que son obtenidos), mientras que IService es un servicio específico, tal vez la interfase que trae los suministros de las fuentes RSS al lector.


La vista y el modelo de vista

  • La vista y el modelo de vista se comunican mediante enlaces de datos, métodos, propiedades, eventos y mensajes
  • El modelo de vista expone propiedades (tal como información sobre el estado de la vista, p.ej. el indicador de “ocupado”) y comandos además de modelos
  • La vista se encarga de sus propios eventos relacionados con la interfase al usuario y los pasa al modelo de vista mediante comandos
  • Los modelos y propiedades en el modelo de vista son actualizados desde la vista usando enlaces de datos bidireccionales

Hay dos mecanismos que son frecuentemente  usados en la implementación del patrón, gatillos o disparadores (especialmente los relacionados con datos) en WPF, y el Controlador de Estados Visuales (Visual State Manager o VSM) en Silverlight. Ambos ayudan por medio de unir los comportamientos de la interfase al usuario con los modelos subyacentes. El VSM debería ser la opción principal para coordinar transiciones y animaciones en Silverlight. Más información sobre VSM aquí.


El modelo de vista y el modelo

El modelo de vista es completamente responsable del modelo en este escenario.

Por dicha no está solo:

  • El modelo de vista puede que exponga el modelo directamente o mediante  propiedades relacionadas para uso en enlaces de datos
  • El modelo de vista puede contener interfases a servicios, datos de configuración y similares, con el fin de obtener y manipular las propiedades que ofrece


¿La gallina o el huevo?

Es posible que hayan escuchado controversias sobre quién lleva la delantera, la vista o el modelo de vista. A mí me parece que la mayoría de desarrolladores estarían de acuerdo con que cada vista ha de tener solamente un modelo de vista. No hay necesidad de asociarla con múltiples modelos de vista. Con esta separación de responsabilidades en mente, tiene sentido que si uno tiene un control para contactos enlazado a un modelo de vista para contactos, y un control con información sobre la compañía atado a un modelo de vista que provee esta información, ambos controles son vistas separadas en vez de una sola con dos modelos de vista.

Una vista puede contener otras vistas, cada una con sus propio modelo de vista. Los modelos de vista pueden contener otros modelos de vista cuando sea necesario (no obstante, es común ver a algunos consolidando sus modelos de vista cuando en realidad lo que necesitan es un modo de comunicaciones entre ellos).

Una vista debe tener un único modelo de vista, pero este último puede ser usado por varias vistas (por ejemplo imaginen un asistente (Wizard) con tres vistas pero un sólo modelo de vista que controla el proceso).


La vista como elemento principal

En este enfoque la vista es la que se encarga de crear o importar el modelo de vista. Generalmente usa el modelo de vista como un recurso al que se enlaza ya sea explícitamente, mediante el patrón de localización, o mediante inserción usando MEF, Unity o algo parecido. Es común usar esta técnica en el manejo de vistas y sus modelos de vista. Yo he publicado algunos artículos sobre el tema:

El ejemplo incluido con este artículo usa este método. La vista es creada y luego el modelo de vista es asociado. En el objeto Application se ve de esta manera:


private void Application_Startup(object sender,
                                 StartupEventArgs e)
{
  var shell = new MainPage();
  shell.LayoutRoot.DataContext = new ContactViewModel();
  RootVisual = shell;
}


He mantenido el ejemplo sencillo mediante evitar el uso de infraestructuras auxiliares que ensamblen las interfases y sus implementaciones.


El modelo de vista como elemento principal

Otra forma de conectar los componentes es mediante hacer al modelo de vista responsable de la creación de la vista y los enlaces necesarios. Para un ejemplo de esta técnica pueden ver la presentación de Rob Eisenberg en MIX, Build your own MVVM Framework, en la que crea una infraestructura basada en convenciones de uso.

La moraleja es que hay más de una manera de matarle las pulgas al perro.


Una infraestructura básica para MVVM

En mi opinión, una infraestructura para MVVM básica requiere sólo dos cosas:

  1. Una clase basada en DependencyObject o que implemente INotifyPropertyChanged de manera que sea utilizable en el enlace de datos, y
  2. Algún tipo de mecanismo para comandos

Silverlight 3 cumple hasta cierto grado con el segundo requisito al proveer la interfase ICommand. Sin embargo, ahora en Silverlight 4 tenemos algo más completo: los comandos permiten enlazar eventos en la vista al modelo de vista. Es un detalle de implementación, pero facilita el uso del patrón MVVM.

Recuerden que Blend provee un surtido juego de herramientas para enlaces de datos y uso de comportamientos en su kit de desarrollo. Pueden ver mi vídeo,  MVVM with MEF in Silverlight, para obtener una idea de lo fácil que es implementar el patrón MVVM aún sin el uso de una infraestructura auxiliar. El artículo Usando MEF en vez de PRISM demuestra cómo pueden crear sus propios comandos.

En el ejemplo he creado una clase base que se encarga de los eventos generados por cambios en propiedades:


namespace MVVMExample
{
  public abstract class BaseINPC : INotifyPropertyChanged
  {
    protected void RaisePropertyChanged(string propertyName)
    {
      var handler = PropertyChanged; 

      if (handler != null)
      {
        handler(this,
                new PropertyChangedEventArgs(propertyName));
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;
  }
}


También he implementado un comando. En la mayoría de los casos uno usaría un tipo más general de comando que sea útil en situaciones variadas, pero con el fin de mantenerlo simple, el comando demostrado abajo se limita a la función de borrado.  En mi caso estoy usando un cuadro de diálogo para confirmar la eliminación. En caso de necesitar algo más elegante, como un ventana de tipo ChildWindow, pueden leer los escenarios que describo más adelante para entender mejor cómo incorporar el cuadro de diálogo como un servicio dentro del patrón MVVM.


namespace MVVMExample
{
  public class DeleteCommand : ICommand
  {
    private readonly IService _service;
    private readonly Func<bool> _canExecute;
    private readonly Action<ContactModel> _deleted;

    public DeleteCommand(IService service,
                         Func<bool> canExecute,
                         Action<ContactModel> deleted)
    {
      _service = service;
      _canExecute = canExecute;
      _deleted = deleted;
    }

    public bool CanExecute(object parameter)
    {
      return _canExecute();
    }

    public void Execute(object parameter)
    {
      if (CanExecute(parameter))
      {
        var contact = parameter as ContactModel;
        if (contact != null)
        {
          var result = MessageBox.Show(
              "Are you sure you wish to delete the contact?",
              "Confirm Delete",
              MessageBoxButton.OKCancel);

          if (result.Equals(MessageBoxResult.OK))
          {
            _service.DeleteContact(contact);
            if (_deleted != null)
            {
              _deleted(contact);
            }
          }
        }
      }
    }

    public void RaiseCanExecuteChanged()
    {
      var handler = CanExecuteChanged;
      if (handler != null)
      {
        handler(this, EventArgs.Empty);
      }
    }

    public event EventHandler CanExecuteChanged;
  }
}


Este comando en particular usa un delegado al que llama cuando ha terminado su trabajo, limitándolo a un único suscriptor para el evento. Un delegado o evento múltiple es necesario si que quiere que varios modelos se puedan suscribir.

En Silverlight 4 es posible simplemente enlazar un botón al comando usando el atributo Command. El ejemplo arriba está escrito en Silverlight 3 que no provee tal facilidad. Para crear el enlace usé un disparador (como antes, específico a este proyecto y con el fin de simplificarlo) para invocar el comando, de manera que sea fácil enlazarlo al XAML.

Los ejemplos mostrados acá son parte de la aplicación adjunta al artículo. Tal aplicación es simple y contiene un único servicio y un modelo de vista con una base de datos simulada. Dos vistas se enlazan al mismo modelo de vista de manera que se puede hacer clic en un contacto para ver sus detalles. También es posible borrar contactos.

Recibo comentarios con cierta frecuencia diciendo que los ejemplos en el blog son muy simplistas. Este es lo suficientemente complejo como para demostrar una  aplicación completa sin depender en infraestructuras adicionales, pero no muestra páginas y tipos de vista múltiples. La razón es simple: siendo un asesor y desarrollador independiente, constantemente estoy escribiendo estas aplicaciones y bibliotecas para clientes, y no tengo la libertad de compartir tal código. Además, aunque me es posible crear ejemplos para los artículos, simplemente no tengo tiempo de construir algo más complejo que trabaje bien. Es algo que de fijo me gustaría lograr, pero simplemente no es práctico si quiero publicar este artículo en un tiempo razonable.


El código fuente para el ejemplo puede ser descargado aquí.


También se le puede ver en acción abajo mediante escoger uno de los nombres y luego pulsar el botón Borrar.  (La ligera pausa durante la carga inicial y en la actualización del control luego de eliminar un contacto es simulada.)


Install Microsoft Silverlight


La manera más fácil de aprender el patrón es por medio de observar la implementación de una aplicación completa. Yo demuestro el proceso en MVVM with MEF in Silverlight. En el vídeo construyo algunos modelos de vista sencillos y muestro una vista que es cambiada de forma dinámica dependiendo de la selección del usuario y uso MEF para hacer todas la conexiones. Un caso más complejo es introducido en la segunda parte.

Pero, ¿qué hay de aplicaciones empresariales más complejas… las que tienen más que un solo botón, con múltiples vistas y complicadas funciones y algoritmos? Eso va más allá de lo que se podría cubrir en detalle en este artículo; sin embargo, quisiera discutir algunos problemas comunes y cómo los solucionaría yo usando MVVM.


Escenarios comunes en MVVM

Por experiencia propia, la idea de enlazar comandos y modelos o propiedades es fácil de entender y aplicar. Son ciertas situaciones específicas, como por ejemplo mostrar un cuadro de diálogo o activar una animación que se prestan a confusión. ¿Cómo se pueden resolver esas dificultades comunes?


Lista con Selección

¿Cómo se puede adaptar el caso de una lista en la que se pueden seleccionar uno o más artículos usando MVVM? Resulta que es bastante fácil. Imaginen un caso donde se tiene un ComboBox con una lista de nombres, y otra vista en la misma página que muestra los detalles de la persona cuando es seleccionada. Si uso MEF para unir las dependencias (a la vez mostrando una técnica diferente a la usada en la aplicación de ejemplo), el modelo de vista podría ser de la siguiente manera:


public class ContactViewModel : BaseViewModel,
                                IPartImportsSatisfiedNotification
{
  [Import]
  public IContactService Service { get; set; }

  public ContactViewModel()
  {
    Contacts = new ObservableCollection<Contact>();
  }

  public ObservableCollection<Contact> Contacts { get; set; }

  private Contact _currentContact; 

  public Contact CurrentContact
  {
    get { return _currentContact; }
    set
    {
      _currentContact = value;
      RaisePropertyChanged("CurrentContact");
    }
  }

  public void OnImportsSatisfied()
  {
    Service.FetchContacts(list =>
      {
        foreach(var contact in list)
        {
          Contacts.Add(contact);
        }
          CurrentContact = Contacts[0];
      });
  }
}


En este caso, importamos un servicio para obtener contactos, ensamblar la lista y asignar el contacto preseleccionado. El cuadro desplegable está enlazado a la colección Contacts. La clave es que el nombre seleccionado también tiene un enlace (es aquí donde el modelo de vista mantiene el estado):


...
<ComboBox ItemsSource="{Binding Contacts}"
          SelectedItem="{Binding
          CurrentContact,Mode=TwoWay}"/>
...


Lo que asegura que cada vez que un nombre es seleccionado en la lista, el contacto actual cambia. ¿Recuerdan que mencioné que varias vistas pueden compartir el mismo modelo de vista? En este caso, la vista para los detalles del contacto puede usar el mismo modelo de vista y crear enlaces con la propiedad CurrentContact.


Navegación

Otra situación enfrentada comúnmente es la navegación. ¿Cómo se puede controlar la navegación en una aplicación al estilo MVVM? La mayoría de los ejemplos muestran un único botón en la pantalla y no lidian con aplicaciones compuestas de varias páginas.

La respuesta corta es que, sin importar el mecanismo usado (ya sea usando un sistema propio, el provisto por Silverlight, el administrador de regiones de PRISM o una combinación de todos los anteriores) se deberían ocultar los detalles tras una interfase. Por medio de usar algo como INavigation o similar la navegación se torna ajena a MVVM. Cualquiera que sea el modo escogido, el modelo de vista puede importar INavigation y usar la interfase para ir a otras vistas o generar un evento  de transición según sea necesario.

Mi artículo sobre el uso de MEF en lugar de PRISM demuestra cómo hacer esto usando la Infraestructura de Extensibilidad Administrada. El artículo Auto-discoverable views using a fluent interface trata el uso de asociaciones entre vistas y regiones, y Dynamic module loading with Prism provee una aplicación completa como ejemplo usando la infraestructura de navegación.


Módulos dinámicos

Este caso es parecido al anterior. ¿Qué hay de aplicaciones extraordinariamente grandes? En tales situaciones tiene poco sentido tratar de cargar toda la aplicación de una sola vez. El menú y pantalla principales deben ser visibles de inmediato, mientras que los demás módulos se pueden cargar según sea necesario. El resultado es una reducción significativa en la pausa inicial requerida para el arranque de la aplicación y también muestra respeto por el navegador de red y los recursos de la computadora del usuario, como memoria y ciclos del CPU.

El cargado dinámico no es específico de MVVM, aún así el envío de mensajes entre modelos de vista y entre módulos es obviamente importante.  En estos casos me parece que es mejor usar infraestructuras como MEF y Prism que proveen soluciones a problema. Prism tiene módulos que pueden ser cargados a pedido y MEF ofrece un catálogo de instalación que permite cargar archivos XAP de manera dinámica. La solución de Prism para mensajes a través de la aplicación es la central de eventos (event aggregator). Ofrezco más información sobre las infraestructuras y las soluciones para estos tipos de problemas en el apéndice donde trato sobre las infraestructuras disponibles para uso inmediato.


Cuadros de diálogo

Un artefacto usado frecuentemente en interfases gráficas es el cuadro de diálogo (similar al cuadro de mensajes, pero esperando una respuesta del usuario). He visto a mucha gente estancarse tratando de implementarlos usando MVVM. Especialmente al considerar la restricción en Silverlight de que todo el código debe ser asincrónico.

En mi opinión, la solución es encapsular el cuadro de diálogo tras una interfase y proveer una función de llamada para la respuesta. El modelo de vista puede importar el cuadro y luego, basado en algún cambio de estado o un comando, disparar el servicio de diálogo. La llamada de vuelta contiene la respuesta y la vista puede proceder apropiadamente.

Para una explicación más completa, pueden  leer Simple Dialog Service in Silverlight.


Animaciones

Otro problema común es cómo activar animaciones o transiciones basadas en cambios en la interfase gráfica o en el servidor.

Hay varias soluciones para el problema. Estos son algunos ejemplos:


Configuración y valores globales

Un problema que escucho comúnmente es cómo tratar con variables globales e información de configuración. De nuevo, esto es menos un problema relativo a MVVM y más una decisión arquitectónica. En la mayoría de los casos, se puede hacer disponible la información de configuración con una interfase (IConfiguration) y luego crear una implementación que contenga los valores específicos. Cualquier modelo que requiera dicha información no tiene más que importar la implementación, ya sea mediante MEF, Unity, u otro método similar, asegurándose de tener sólo una instancia de la clase (tal vez usando el patrón de Instancia Única, aunque lo más probable es que sea controlado por el contenedor y no por la clase misma).


Procesos asincrónicos

Otro punto de confusión con Silverlight es que todas la llamadas al servidor son necesariamente asincrónicas. Esto puede parecer extraño al construir el modelo de vista: luego de generar la llamada, ¿cómo se puede saber cuando ha sido completada? Generalmente se hace mediante subscribirse a un evento que es disparado al finalizar el proceso y los resultados se obtienen mediante datos enlazados. Yo prefiero ocultar la los detalles del manejo de eventos tras una función de tipo Action. El artículo Simplifying Asynchronous Calls in Silverlight using Actions muestra un ejemplo de cómo hacer esto.

A veces el trabajo es más elaborado requiriendo múltiples llamadas asincrónicas que se deben ejecutar en secuencia y cada una debe esperar a que la operación previa haya terminado. En tal caso, puede ser mejor investigar el uso de mecanismos que facilitan escribir código para flujos de operaciones consecutivas. Este articulo explica una forma de hacerlo usando co-rutinas, y este otro describe como usar una excelente infraestructura ya existente que maneja las llamadas manera segura usando subprocesos, capturando errores, y  mucho más.


Conjuntos de datos inmensos

Por último, he escuchado aserciones de que MVVM no trabaja bien con grandes bancos de datos. Yo diría más bien que son ciertas implementaciones las que presentan tal problema, no el patrón en sí. La solución frecuentemente es paginar los datos, pero parece que muchos usan un enfoque incorrecto para resolver el problema. Por alguna razón, los desarrolladores insisten en que la paginación es una función de la base de datos y debe ser aislada en la capa de acceso a datos. El simple hecho de tener elementos como página actual y número de páginas en la interfase al usuario da a entender que tal no es un artefacto de la base de datos, sino que está presente en todas la capas de la aplicación y debe ser manejado como tal.

En su forma más básica, se puede usar una colección que crezca a medida que el usuario pasa páginas. Si el conjunto de datos es pequeño, se puede crear una sola colección y mantenerla por completo en el cliente Silverlight, usando un panel virtual para desplegar la información (el problema con algunos paneles es que crean un control para cada elemento en el conjunto entero de datos, destrozando la eficiencia—los paneles virtuales solamente crean los controles necesarios para llenar la parte visible de la pantalla).

Tecnologías como WCF RIA son compatibles con consultas en LINQ. Este tipo de consultas contienen métodos de extensión que permiten tomar únicamente los primeros elementos de una lista en vez de toda la lista de un solo. La infraestructura también provee clases auxiliares como PagedCollectionView para ayudar a filtrar, ordenar y paginar datos.


Lo que MVVM no es

El tema no puede ser cubierto a cabalidad sin considerar lo que MVVM no es.

MVVM no es una infraestructura completa. Es un patrón de diseño y puede que algunas bibliotecas provean facilidades para su implementación, pero no es más que una pieza de la entera solución para la arquitectura de la aplicación. MVVM no está interesado en lo que ocurre en el servidor o la forma en que son implementados los servicios de soporte. En cambio, y esto es una gran ventaja, su principal trabajo es la separación de responsabilidades.

En ninguna parte de este artículo van a encontrar la frase “MVVM no permite usar código subyacente”. El tema es fuertemente debatido, pero el patrón en sí no indica cómo implementar la vista, ya sea con XAML, con código subyacente, o una combinación de ambos. Mi sugerencia es que si están pasando días enteros escribiendo código tan sólo para evitar algo que puede ser resuelto en unos cuantos minutos usando código subyacente, algo está mal.

MVVM no es requerido en WPF o Silverlight. A mi parecer, aplicaciones empresariales, de manejo de datos, o con múltiples ventanas o formularios, son excelentes candidatos. Por otra parte, juegos, sitios Web de entretenimiento programas de dibujo, y otros similares no se adaptan muy bien. Deben estar seguros de usar la herramienta apropiada para cada tarea.

MVVM no debería ser un motivo de retraso. Cualquier patrón o infraestructura requiere cierto tiempo de aprendizaje. Hay que aceptar el hecho de que los desarrolladores tendrán que estudiarlo para poder entenderlo, pero lo que no es aceptable es que el proceso entero de pronto dure más de la cuenta y termine atrasando el proyecto. El patrón es útil si, en cambio, acelera el proceso de desarrollo, mejora la estabilidad y rendimiento de la aplicación, reduce los riesgos del proyecto, y así por el estilo. Cuando lerdea el desarrollo, introduce problemas, y produce escalofríos en los desarrolladores al oír su nombre, puede que sea necesario evaluar la forma en que se está ejecutando.


Conclusión

¡Ok, ya terminamos! Espero haberles ayudado a ver por qué MVVM es tan poderoso en aplicaciones Silverlight y WPF, cuáles son los aspectos principales del patrón, y hasta haber mostrado ejemplos de soluciones a problemas comunes que puede resolver. Ahora, quisiera conocer sus opiniones y comentarios.

Ir al Apéndice A: Orígenes de diversos patrones

Ir al Apéndice B: Infraestructuras disponibles

Mi agradecimiento especial a los siguientes miembros de la comunidad que dedicaron parte de sus ocupados horarios a revisar y dar sus comentarios y sugerencias preliminares para este artículo (en orden alfabético):



Apéndice A: Historia de algunos patrones


Modelo-Vista-Controlador (MVC)

Este patrón fue descrito primero en el contexto de Smalltalk en Xerox en 1979. Si lo desean pueden obtener algunos de los documentos originales (en formato PDF) aquí.


Esquema del patrón Modelo-Vista-Controlador (MVC)



Modelo-Vista-Presentador (MVP)

El patrón Modelo-Vista-Presentador (PDF) fue introducido en 1996 . Se basa en el MVC pero pone algunas restricciones en el controlador cuyo nombre fue cambiado a presentador. Esta es su forma generalizada:


Esquema del patrón Modelo-Vista-Presentador (MVP)


Martin Folwer describe el patrón con dos matices diferentes: El Contolador/Presentador superintendente y la Vista Pasiva. Microsoft también da su propia descripción del MVP.


Modelo de presentación

En el 2004 Martin Fowler publicó su descripción para el Modelo de Presentación. El resumen es conciso: “Abarca el estado y comportamiento de la presentación independientemente de los controles usados en la interfase gráfica al usuario.” Como es evidente, MVVM es una forma especializada de este último patrón:


Esquema del patrón Modelo de Presentación (MP)


Apéndice B: Infraestructuras o bibliotecas de MVVM disponibles

Ahora que ya tenemos una idea de qué es MVVM, no es necesario reinventarlo. Hay varias bibliotecas ya existentes que implementan MVVM. Sin ningún orden en particular:


MVVM Light

Este es un recurso muy popular que incluye entre sus facilidades, una clase base pasa modelos de vista, comandos, mensajería, y platillas de proyectos para comenzar aplicaciones. Es compatible con WPF y Silverlight.


SilverlightFX

El objetivo de esta biblioteca es habilitar la creación de de interfaces al usuario usando un lenguaje declarativo, permitiendo una más fácil separación entre la vista y el código, y lo hace mediante una biblioteca con sólo lo esencial.


Caliburn

Esta biblioteca popular usa la técnica de comenzar con el modelo de vista y es compatible con WPF y Silverlight. Sin embargo, este es tan sólo un aspecto, puesto que es una muy completa infraestructura para la creación de aplicaciones.


nRoute

Otra biblioteca MVVM, con la especialidad de usar comandos reversos que permite enlazar comandos a eventos en la vista a diferencia del modo corriente en que la vista envía comandos al modelo de vista.


MicroModels

Un biblioteca enfocada a sólo lo estrictamente necesario para usar MVVM.


Composite WPF/PRISM

A pesar de que su nombre original es Composite WPF, la infraestructura es compatible con WPF y Silverlight. Y, aunque no provee implementaciones del patrón MVVM, sí contiene guías y recursos para crear aplicaciones compuestas, incluyendo comandos, centralización de eventos, administración de regiones visuales, y más.

La lista no es de ningún modo exhaustiva, pero espero que les dé una idea del apoyo que la comunidad Código Abierto le ha dado al patrón MVVM. También les puede ayudar a escoger una biblioteca estable  para acelerar el desarrollo de sus aplicaciones.

Etiquetas asignadas:
 

21 Respuestas a “Patrón Modelo-Vista-Modelo de Vista (MVVM) Explicado”

  1. Ricardo dice:

    Hola muy interesante tu articulo la verdad muy bien explicado , mira soy un programador de windowsforms y me estoy educando en esto de el patron MVVM pero me ha costado mucho entender ya en la practica todos los conceptos me interersa mucho aprender este patron u otro para desarrollar aplicaciones en WPF, he leido sobre algunos frameworks como caliburn, calcium , que sesupone te ayudan desarrollar bajo este patron pero en mi caso en vez de eso me revuelvo mas no se si me puedas dar una ayudadita diciendome donde puedo encontrar mas ejemplos practicos del uso de este patron pues como te digo se meha dificultado mucho gracias !

    • David Mora dice:

      Ricardo,

      Gracias por el encomio. Quisiera poder publicar artículos con más frecuencia pero debido a estar muy ocupado, se hace difícil. Aún así, estoy preparando una serie de artículos describiendo el proceso de crear un aplicación usando ese patrón. A diferencia otros ejemplos, en este caso es una reseña sobre el diseño e implementación de una aplicación real que está siendo usada por el cliente en este momento. Probablemente tenga varias partes de la serie listas a mediados de Julio.

      Desafortunadamente, ejemplos sólidos para MVVM son todavía escasos. La serie sobre MVVM y MEF de Shawn Wildermuth provee algunos consejos prácticos. También es buena idea explorar el blog the Jeremy Likness. Otra persona conocida por su pericia en MVVM es Josh Smith.

  2. Ricardo dice:

    haa muchas gracias esperare estos articulos con ansiedad la verdad gracias ya que en español hay muy poco sobre este patron y sobre los frameworks ni se diga practicamente no hay nada en español aunque eso no debe suponer gran problema pero al menos a unos como yo no les caeria mal algo en español (mas comodo).
    Ahorita me estoy adentrando a el framework MVVM Litght toolkit con C# ( soy un programador de VB.Net asi que me cuesta algo ). la verdad espero puedas publicar porque se ve que realmente sabes mucho sobre este tema una vez mas gracias!

  3. Ricardo dice:

    hola he seguido estudiando este articulo mas a detalle, nadamas que tengo un problema aun no logro entender estas lineas de codigo del todo no se si me puedas explicar forman parte de la clase ContactModel.

    public override bool Equals(object obj)
    63 {
    64 return obj is ContactModel &&
    65 ((ContactModel) obj).FullName.Equals(FullName);
    66 }
    67
    68 public override int GetHashCode()
    69 {
    70 return FullName.GetHashCode();
    71 }

    • David Mora dice:

      Ricardo,

      Tu pregunta es un tanto general, por lo que te ofrezco una respuesta general. Disculpa si explico conceptos que ya conoces.

      En .NET todas las clases tienen un antepasado común: Object. Tal descendencia es implícita, por lo que no es necesario declararla. Eso quiere decir que ContactModel deriva de Object y hereda ciertos comportamientos de esa clase fundamental. Una de las funciones heredadas es Equals. En su forma fundamental, el método compara referencias. Es decir, Equals es cierto cuando ambas referencias apuntan al mismo objeto.

      En el caso de ContactModel, el autor original (Jeremy) ha decidido que la igualdad debe ser evaluada a un nivel conceptual: dos contactos son el mismo si su nombre completo es idéntico. Esto es debido a que se puede dar la situación de tener dos objetos completamente separados que contengan el mismo nombre y la función heredada de Object diría que son diferentes, lo cual no es cierto (por lo menos dentro de la reglas establecidas por esta aplicación).

      Un consecuencia de alterar el comportamiento de Equals, es que también se necesita modificar GetHashCode. Esta función devuelve un valor cuasi-único para cada objeto y .NET lo usa para crear tablas de referencia tanto internas como explícitas. El HashCode también es usado para evaluar la igualdad de objetos. En el caso anterior, el autor ha tomado ventaja de que el código hash de una cadena de caracteres es calculado a partir de la secuencia particular de la cadena. De esa manera, el valor obtenido es el mismo para cadenas idénticas. Como puedes ver, nuevamente el valor depende del nombre completo del contacto.

      Para más detalles puedes consultar las entradas para Object.Equals y Object.GetHashCode en MSDN.

      En el artículo, el código no hace uso explícito de este comportamiento alterado, sin embargo, la regla sería útil una vez que las funciones de añadido, búsqueda y borrado de contactos sean más sofisticadas.

      Espero que la respuesta te haya ayudado. Si no lo hizo o si todavía tienes dudas, por favor déjame saber.

  4. Ricardo dice:

    Gracias que pena me da la verdad, al parecer me falta bastante por aprender, mira como te comentaba en respuestas anteriores soy un programador de VB y la verdad C# me cuesta (mas bien no me gusta) estoy revisando el codigo de ejemplo que adjuntaste en este articulo y la verdad me he quedado impresionado pues llevo ya varios meses estudiando este modelo de programacion y aun no puedo atar los cabos sueltos, se que para este tipo de modelos se requiere cierto nivel de conocimientos pero hay algunas cosas que aun no logro comprender por ejemplo . en el codigo fuente vienen clases como el IService , Service,que aun no tengo muy claro cual es el papel que juegan, ademas los Commands entiendo el concepto pero aun tengo problemas en su aplicacion perdona que te moleste con conceptos tal vez muy triviales o tontos pero la verdad este es el unico lugar que he encontrado donde se han respondido muchas de mis dudas.
    Mira en estos meses desarrolle una humilde aplicacion en WPF tratando de aplicar este modelo pero al final me di cuenta que lo hice todo mal ya que no pude desacoplar del todo las capas te presento un video de mi aplicacion, http://www.youtube.com/watch?v=K8UULFUCIgQ
    gracias! y espero me puedas seguir orientando.

  5. Carlos dice:

    Hola, me parece muy bueno tu articulo, mi consulta es que si para cada modelo debo crear un view model?, ya que en mi aplicacion tengo varias tablas (unas 20) y debo crear una ventana de mantenimiento para cada una, entonces trabajar con mvvm me lleva a crear 1 clase modelo por cada tabla mas 1 clase view model mas la vista esto es 3 clases por cada una, hay alguna manera de reducir esto o de acelerar el proceso? ya que las tablas tienen diferentes campos y esto se me esta volviendo un problema, gracias

    • David Mora dice:

      Carlos,

      Algo que yo he hallado importante es tener en mente que se trata de un patrón y no una receta. La diferencia es algo sutil, pero significativa. Una receta te da los pasos a seguir y desviarse del procedimiento tiende a ser riesgoso. Un patrón, por lo menos en nuestro contexto, se trata de una estrategia a grandes rasgos, sin detalles muy definidos. Uno tiene que rellenar donde falte. Es en parte por esto que los patrones son un poco difíciles de digerir puesto que son necesariamente ambiguos. Otra consecuencia es que cada caso tiende a ser diferente, incluso si se aplica el mismo patrón al dos soluciones diferentes, la arquitectura resultante casi de seguro será distinta en cada caso.

      El MVVM no dicta una correspondencia uno a uno entre modelo, modelo de vista y vista. No sería práctico puesto que los tres se desenvuelven en entornos diferentes. Te digo de primeras que es común ver un modelo de vista por cada vista, pero tampoco es una regla. La misma variedad se ven el caso del modelo. Algunos consideran cada tabla, consulta o clase como un modelo. Otros agrupan diferentes entidades en modelos conceptuales. Puesto que yo tiendo a diseñar usando la filosofía del DDD y BDD, mis modelos son más del segundo tipo.

      Bueno, luego de esta hablada, mi sugerencia es que examines tu aplicación desde el punto de vista de la interfase gráfica. Si tienes por ejemplo páginas o pantallas en las que muestras varias tablas asociadas por un concepto o tal vez una relación de maestro/detalle, las diferentes áreas de presentación pueden ser vistas (me refiero a vista en MVVM) y usar un único modelo de vista que les sirva de puente al modelo. De hecho, usar un modelo de vista común entre varias vistas es una estrategia a veces usada para proveer comunicaciones entre la vistas (otra forma es mediante mensajería).

      Como mencionas, el crecimiento desmedido en el número de clases puede ser fuente de muchos dolores de cabeza en un futuro, y complica a veces el proyecto de manera innecesaria. Si tienes forma de combinar la interacción de varios modelos usando un único modelo de vista, entonces ¡adelante! No obstante evita acumular la llamada deuda técnica que se produce al desviarse de los principios SOLID.

      Finalmente, aplicaciones de gestión en la que se provee una interfase gráfica para administrar una base de datos tienden a ser un caso fronterizo. Es decir no se adaptan al modelo general “promedio” (por falta de mejor expresión) de una aplicación RIA. Esto debido a que las tablas son vistas fuera de contexto. En tal caso, el gran número de clases resultantes puede ser tedioso, pero no necesariamente nocivo puesto que no hay que mantener relaciones complejas entre las entidades.

  6. [...] La traducción de Maromas Digital del artículo de Jeremy Likness aquí. [...]

  7. Christian Astúa dice:

    Buenas. Muy interesante tu artículo. Estaba leyendolo pero en muchas cosas todavía estoy pérdido. Nunca he programado en WPF, ya que yo sólo me dedicaba a Forms común y silvestres. El XAML por tags no es tan díficil, pero me gustaría saber si este patrón puede aplicarse en forms normales. Es que no me queda tan claro la verdad y me gustaría una pequeña luz para aclarar las cosas. Seguiré leyendo en inglés a ver si tambiéne so me ayuda.

    De antemano muchas gracias por todo.

    • David Mora dice:

      Chistian,

      Desde el punto de vista de ser un patrón de diseño, MVVM puede ser aplicado a Windows Forms. De hecho hay varios ejemplos disponibles en la red y en libros (por ejemplo, este artículo en MSDN).

      La última sección de esta página, menciona MVP en dos variantes, vista pasiva y el controlador superintendente. Las diferencias son algo sutiles pero importantes. Entiendo que lees bien el inglés, por lo que te sugiero leer los documentos enlazados en el apéndice para familiarizarte con los patrones envueltos. En fin, en términos prácticos, el mecanismo disponible para enlace de datos tiene mucho que ver con el patrón específico que mejor de adapte.

      Para aplicaciones empresariales de cierto tamaño, Microsoft provee varias guías y una infraestructura completa de diseño llamada Smart Client Software Factory. En el pasado usé una versión anterior (conocida como Composite UI Application Block o CAB, ya obsoleta) y es buena pero, debido a la cantidad de infraestructura, no vale la pena para aplicaciones pequeñas. No sé si la nueva versión es más liviana.

      Lo que yo te sugeriría es separar tus objetivos. Ya sea aprender XAML junto con su sistema de enlaces de datos (que, aunque comparten la idea general usada en Windows Forms, son mucho más efectivos y mejor portados) sin preocuparte mucho por patrones de diseño hasta que ya tengas un poco de práctica, o seguir con Windows Forms y estudiar los patrones de diseño hasta que estés familiarizado con sus características y aplicaciones.

  8. [...] El patrón de diseño Modelo-Vista-Modelo de vista es más una estrategia, una idea general de cómo estructurar la solución a un problema. En vez de listas de pasos, necesariamente lo que encontramos son explicaciones de los componentes principales del patrón y algunos ejemplos de su aplicación. Para los que todavía no están familiarizados con el patrón, Jeremy Likness ha escrito una muy buena introducción al tema. [...]

  9. [...] En las siguientes semanas voy a publicar una serie de artículos explicando un proyecto de fuente abierta que acabo de lanzar llamado Jounce. Su proposito es suministrar guías sobre cómo crear aplicaciones modulares en Silverlight usando la infraestructura de extensibilidad administrada (MEF por sus siglas en inglés) y el patrón Modelo-Vista-Modelo de Vista (MVVM). [...]

  10. [...] he usado el patrón MVVM para realizar este proyecto aunque no he seguido todos los [...]

  11. Ariel dice:

    Excelente artículo David. Solo quisiera preguntarte si conoces un buen libro que explice, en detalles o a fondo, todo acerca de este y otros tipos de patrones. No importa si el lenguaje es en inglés o en español, aunque si es en español, mejor aún.
    Muchas gracias por tu tiempo y saludos fraternales.

    • David Mora dice:

      Los patrones son estrategias para el diseño y construcción de aplicaciones. Un error común es buscar qué patrones utilizar en un proyecto. La táctica correcta es busca la solución del problema y luego ver si hay patrones que se amoldan al diseño general del programa o sistema.

      El libro original que puso ne marcha el movimiento de patrones de diseño es Design Patterns: Elements of Reusable Object-Oriented Software. Aunque ya es algo antiguo, es todavía válido y autoritario. Sin embargo su lectura es difícil puesto que está escrito como tomo de texto y más como una referencia que una guía.

      Para una introducción más suave al tema yo recomiendo los siguientes dos libros: Head First Design Patterns y Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development. El primero explica de una manera mucho más interesante varios de los patrones definidos en Design Patterns y también presenta su aplicación. Aunque el segundo libro menciona UML en su título, no te dejes fastidiar por eso. Si bien el tomo presenta aspectos de la notación en UML, también explica muy bien cómo uno puede “encontrar” patrones a medida que construye la aplicación.

      Hay otros libros, pero esos son útiles para empezar. Si sólo puedes obtener uno, yo sugiero Head First Design Patterns.

  12. Keni dice:

    Muy buen articulo David, me gusto mucho la sencillez con la que explicaste el patrón, sin duda ayudará a mucha gente a comprender su funcionamiento, pero sobre todo me gustaron tus conclusiones finales y los consejos y advertencias.
    Cada vez mas gente asocia WPF o Silverlight al uso obligado MVVM, complicándose el desarrollo en proyectos que quizá se podrían haber resuelto de manera mas fácil. El uso de este patrón como el uso de cualquier otro, siempre debe concebirse como una solución a un problema encontrado y no una receta para trabajar con una tecnología.
    Debemos evaluar lo que MVVM nos ofrece y si es adecuado como solución a nuestro problema ya que WPF/Silverlight nos ofrece un abanico de herramientas muy potentes que también podríamos usar para muy diferentes y varados problemas; RoutedEvents, RoutedCommands, Separacion Árbol Lógico-Árbol Visual, ControlTemplates, Lookless Control capabilities, Controles de Navegación, Animación/Medios, Interoperabilidad, etcconclusiones finales y los consejos y advertencias sobre este.
    Cada vez mas gente asocia WPF o Silverlight al uso obl

    • David Mora dice:

      Gracias por tus comentarios. Debo, sin embargo, hacer énfasis en que es una traducción al español del artículo por Jeremy Likeness. Aún así, estoy de acuerdo contigo en que Jeremy explica muy bien el tema, y su punto de vista balanceado ha servido como guía, tanto para mí, como para muchos otros desarrolladores.

Responder



Licencia de uso

El contenido de las traducciones está sujeto a los términos de protección de derechos de uso de los autores originales quienes han autorizado su publicación en este blog. Asegúrese de entender los terminos de la licencia de cada autor antes de usar tal contenido.

Mis propios artículos son publicados bajo los términos de la Licencia Reconocimiento-Compartir bajo la misma licencia 3.0 Estados Unidos de Creative Commons:

Creative Commons License
Blog de Maromas Digitales by Maromas Digitales, LLC is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 3.0 Estados Unidos License.

License

The contents of all translated articles is subject to the copyright and licensing terms of the original authors and has been published here with their express permission. Verify the original author's licensing terms before using the contents of these articles.

My own articles are licensed under the Creative Commons Attribution-Share Alike 3.0 United States License:

Creative Commons License
Blog de Maromas Digitales by Maromas Digitales, LLC is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.