Articulo de referencia

Modelo-vista-modelo de vista

El modelo-vista-modelo de vista ( MVVM ) es un diseño de arquitectura de capas en software informático que facilita la separación del desarrollo de una interfaz gráfica de usuar...

El modelo-vista-modelo de vista ( MVVM ) es un diseño de arquitectura de capas en software informático que facilita la separación del desarrollo de una interfaz gráfica de usuario (GUI; la vista ), ya sea mediante un lenguaje de marcado o código GUI, del desarrollo de la lógica de negocio o lógica de back-end (el modelo ), de manera que la vista no dependa de ninguna plataforma de modelo específica.

El modelo de vista de MVVM es un convertidor de valores, [ 1 ] lo que significa que es responsable de exponer (convertir) los objetos de datos del modelo de manera que puedan ser gestionados y presentados fácilmente. En este sentido, el modelo de vista es más modelo que vista , y maneja la mayor parte (si no toda) la lógica de visualización de la vista. [ 1 ] El modelo de vista puede implementar un patrón mediador , organizando el acceso a la lógica de back-end en torno al conjunto de casos de uso admitidos por la vista.

MVVM es una variación del patrón de diseño Presentation Model de Martin Fowler . [ 2 ] [ 3 ] MVVM es muy similar al patrón Model-view-presenter . Fue inventado por los arquitectos de Microsoft Ken Cooper y Ted Peters específicamente para simplificar la programación orientada a eventos de las interfaces de usuario. El patrón se incorporó a Windows Presentation Foundation (WPF) (el sistema gráfico .NET de Microsoft ) y Silverlight , la aplicación derivada de WPF para Internet. [ 3 ] John Gossman, arquitecto de Microsoft WPF y Silverlight, anunció MVVM en su blog en 2005. [ 3 ] [ 4 ]

El patrón Modelo-Vista-Modelo de Vista también se conoce como Modelo-Vista-Enlazador , especialmente en implementaciones que no involucran la plataforma .NET . ZK , un marco de trabajo para aplicaciones web escrito en Java , y la biblioteca JavaScript KnockoutJS utilizan Modelo-Vista-Enlazador. [ 3 ] [ 5 ] [ 6 ]

Componentes del patrón MVVM

Modelo
El término "modelo" se refiere bien a un modelo de dominio , que representa el contenido del estado real (un enfoque orientado a objetos), o bien a la capa de acceso a datos , que representa el contenido (un enfoque centrado en los datos).
Vista
Al igual que en los patrones modelo-vista-controlador (MVC) y modelo-vista-presentador (MVP), la vista es la estructura, el diseño y la apariencia de lo que un usuario ve en la pantalla. [ 7 ] Muestra una representación del modelo y recibe la interacción del usuario con la vista (clics del ratón, entrada de teclado, gestos de toque en la pantalla, etc.), y reenvía el manejo de estos al modelo de vista a través del enlace de datos (propiedades, devoluciones de llamada de eventos, etc.) que se define para vincular la vista y el modelo de vista.
Ver modelo
El modelo de vista es una abstracción de la vista que expone propiedades y comandos públicos. En lugar del controlador del patrón MVC o del presentador del patrón MVP, MVVM tiene un enlazador que automatiza la comunicación entre la vista y sus propiedades enlazadas en el modelo de vista. El modelo de vista se ha descrito como un estado de los datos en el modelo. [ 8 ]
La principal diferencia entre el modelo de vista y el presentador en el patrón MVP es que el presentador tiene una referencia a una vista, mientras que el modelo de vista no. En cambio, una vista se enlaza directamente a las propiedades del modelo de vista para enviar y recibir actualizaciones. Para funcionar de manera eficiente, esto requiere una tecnología de enlace o la generación de código repetitivo para realizar el enlace. [ 7 ]
En la programación orientada a objetos , el modelo de vista a veces puede denominarse objeto de transferencia de datos . [ 9 ]
Aglutinante
El enlace de datos y comandos declarativo es implícito en el patrón MVVM. En la pila de soluciones de Microsoft , el enlazador es un lenguaje de marcado llamado XAML . [ 10 ] El enlazador libera al desarrollador de la obligación de escribir lógica repetitiva para sincronizar el modelo de vista y la vista. Cuando se implementa fuera de la pila de Microsoft, la presencia de una tecnología de enlace de datos declarativo es lo que hace posible este patrón, [ 5 ] [ 11 ] y sin un enlazador, normalmente se usaría MVP o MVC en su lugar y habría que escribir más código repetitivo (o generarlo con alguna otra herramienta).

Razón fundamental

MVVM se diseñó para eliminar prácticamente todo el código de la interfaz gráfica de usuario ( código subyacente ) de la capa de vista, utilizando funciones de enlace de datos en WPF (Windows Presentation Foundation) para facilitar la separación del desarrollo de la capa de vista del resto del patrón. [ 3 ] En lugar de exigir a los desarrolladores de experiencia de usuario (UX) que escriban código de interfaz gráfica, pueden usar el lenguaje de marcado del marco (por ejemplo, XAML ) y crear enlaces de datos al modelo de vista, que es escrito y mantenido por los desarrolladores de la aplicación. La separación de roles permite a los diseñadores interactivos centrarse en las necesidades de UX en lugar de programar la lógica de negocio. De este modo, las capas de una aplicación pueden desarrollarse en múltiples flujos de trabajo para una mayor productividad. Incluso cuando un solo desarrollador trabaja en todo el código base, una separación adecuada de la vista del modelo es más productiva, ya que la interfaz de usuario suele cambiar con frecuencia y al final del ciclo de desarrollo en función de los comentarios de los usuarios finales.

El patrón MVVM busca obtener las ventajas de la separación del desarrollo funcional que ofrece MVC, aprovechando al mismo tiempo las ventajas de los enlaces de datos y el framework al vincular los datos lo más cerca posible del modelo de aplicación puro. [ 3 ] [ 4 ] [ 12 ] Utiliza el enlazador, el modelo de vista y las funcionalidades de verificación de datos de cualquier capa de negocio para validar los datos entrantes. El resultado es que el modelo y el framework controlan la mayor parte de las operaciones, eliminando o minimizando la lógica de la aplicación que manipula directamente la vista (por ejemplo, el código subyacente).

Crítica

John Gossman ha criticado el patrón MVVM y su aplicación en usos específicos, afirmando que MVVM puede ser excesivo al crear interfaces de usuario sencillas. Para aplicaciones más grandes, considera que generalizar el modelo de vista de antemano puede ser difícil y que el enlace de datos a gran escala puede conducir a un menor rendimiento. [ 13 ]

Implementaciones

Frameworks .NET

  • Kit de herramientas de la comunidad .NET
  • Avalonia
  • Caliburn, Caliburn.Micro
  • Chinook.DynamicMvm Código abierto
  • DevExpress MVVM
  • Proyecto de código abierto DotVVM
  • FreshMvvm
  • Medusa
  • Kit de herramientas Mugen MVVM
  • Kit de herramientas MVVMLight
  • MvvmCross
  • MvvmZero
  • Biblioteca Prisma
  • Rascl
  • Interfaz de usuario reactiva
  • Plataforma Uno - Código abierto

Bibliotecas de componentes web

  • Microsoft RÁPIDO
  • Omi.js

Marcos de trabajo de Java

marcos de trabajo de JavaScript

Frameworks para C++ y XAML (Windows)

  • C++/WinRT
  • Xamlcc

Ejemplos

Los siguientes son ejemplos sencillos de una implementación del patrón MVVM.

C++

Este es un ejemplo usando C++ .

exportar módulo wikipedia.ejemplos.mvvm ;importar std ;usando std :: string ;exportar espacio de nombres wikipedia :: ejemplos :: mvvm {clase Modelo { privado : int contador = 0 ; público : [[ nodiscard ]] int getCounter () const noexcept { return contador ; }void increment () noexcept { contador ++ ; }void decrement () noexcept { contador-- ; } } ;clase ViewModel { privado : Model & modelo ; público : ViewModel explícito ( Model & m ) : modelo { m } {}void incrementCounter ( ) noexcept { model.increment ( ); }void decrementCounter ( ) noexcept { model.decrement ( ); }[[ nodiscard ]] int getCounterValue () const noexcept { return model . getCounter (); } };clase View { private : ViewModel & viewModel ; public : explicit View ( ViewModel & vm ) : viewModel { vm } {}void run () { string input ; while ( true ) { std :: println ( "Contador: {}" , viewModel . getCounterValue ()); std :: print ( "Ingrese el comando (i=incrementar, d=decrementar, q=salir): " ); std :: getline ( std :: cin , input );if ( input == "i" ) { viewModel . incrementCounter (); } else if ( input == "d" ) { viewModel . decrementCounter (); } else if ( input == "q" ) { break ; } else { std :: println ( "Comando desconocido." ); } } } };}

Entonces, la aplicación podría ejecutarse de la siguiente manera:

importar wikipedia.ejemplos.mvvm ;using namespace wikipedia :: examples :: mvvm ;int main ( int argc , char * argv [ ]) { Modelo m ; ViewModel vm ( m ); Vista v ( vm ); v.run ( ); return 0 ; }

DO#

Este es un ejemplo usando C# .

Modelo.cs :

espacio de nombres Wikipedia.Ejemplos.Mvvm ;clase pública Modelo { entero público Contador { obtener ; conjunto privado ; } = 0 ;public void Incremento () => Contador ++ ; public void Decremento () => Contador -- ; }

ViewModel.cs :

espacio de nombres Wikipedia.Ejemplos.Mvvm ;clase pública ViewModel { privado readonly Model _model ;public ViewModel ( Model model ) { _model = model ; }public void IncrementCounter () => _model . Increment (); public void DecrementCounter () => _model . Decrement (); public int CounterValue => _model . Counter ; }

Vista.cs :

espacio de nombres Wikipedia.Ejemplos.Mvvm ;usando el sistema ;clase pública View { private readonly ViewModel _viewModel ;public View ( ViewModel viewModel ) { _viewModel = viewModel ; }public void Run ( ) { string input = String.Empty ; while ( true ) { Console.WriteLine ( $ "Contador: {_viewModel.CounterValue}" ) ; Console.Write ( " Ingrese el comando ( i= incrementar , d=decrementar, q=salir): " ) ; input = Console.ReadLine (); switch ( input ) { case "i" : _viewModel.IncrementCounter (); break ; case " d" : _viewModel.DecrementCounter ( ) ; break ; case " q" : return ; default : Console.WriteLine ( "Comando desconocido. " ) ; break ; } } } }

Entonces, la aplicación Main.cs podría ejecutarse de la siguiente manera:

espacio de nombres Wikipedia.Ejemplos ;usando Wikipedia.Examples.Mvvm ;public class Main { public static void Main () { Model model = new (); ViewModel viewModel = new ( model ); View view = new ( viewModel ); view . Run (); } }

Java

Este es un ejemplo usando Java .

Modelo.java :

paquete org.wikipedia.examples.mvvm ;clase pública Modelo { entero privado contador = 0 ;public int getCounter () { return counter ; }public void increment () { contador ++ ; }public void decrement ( ) { contador-- ; } }

ViewModel.java :

paquete org.wikipedia.examples.mvvm ;clase pública ViewModel { privado final Model modelo ;public ViewModel ( Model model ) { this . model = model ; }public void incrementCounter () { modelo.incremento ( ) ; }public void decrementCounter () { modelo.decremento ( ) ; }public int getCounterValue () { return model . getCounter (); } }

View.java :

paquete org.wikipedia.examples.mvvm ;import java.util.Scanner ;clase pública View { privado final ViewModel viewModel ;public View ( ViewModel viewModel ) { this . viewModel = viewModel ; }public void run ( ) { Scanner stdin = new Scanner ( System.in ) ; String input ; while ( true ) { System.out.printf ( " Contador: %d%n" , viewModel.getCounterValue ( ) ); System.out.print ( " Ingrese el comando (i= incrementar, d=decrementar, q=salir): "); input = stdin.nextLine ( ) ; switch ( input ) { case " i " : viewModel.incrementCounter ( ) ; break ; case " d " : viewModel.decrementCounter ( ) ; break ; case " q " : return ; default : System.out.println ( " Comando desconocido . " ) ; } } } }

Entonces, la aplicación Main.java podría ejecutarse de la siguiente manera:

paquete org.wikipedia.examples ;import org.wikipedia.examples.mvvm.* ;public class Main { public static void main ( String [] args ) { Model m = new Model (); ViewModel vm = new ViewModel ( m ); View v = new View ( vm ); v . run (); } }

Óxido

Este es un ejemplo usando Rust .

usar std :: io ;pub struct Modelo { contador : i32 , }impl Model { pub fn new () -> Self { Model { counter : 0 } }pub fn get_counter ( & self ) -> i32 { self . counter }pub fn increment ( & mut self ) { self . counter += 1 ; }pub fn decremento ( & mut self ) { self . contador -= 1 ; } }pub struct ViewModel <' a > { model : & ' a mut Model , }impl <' a > ViewModel <' a > { pub fn new ( model : & ' a mut Model ) -> Self { Self { model } }pub fn increment_counter ( & mut self ) { self . model . increment (); }pub fn decrement_counter ( & mut self ) { self . model . decrement (); }pub fn get_counter_value ( & self ) -> i32 { self . model . get_counter () } }pub struct View <' a > { view_model : & ' a mut ViewModel <' a > , }impl <' a > View <' a > { pub fn new ( view_model : & ' a mut ViewModel <' a > ) -> Self { Self { view_model } }pub fn run ( & mut self ) { loop { println! ( "Contador: {}" , self . view_model . get_counter_value ());print! ( "Ingrese el comando (i=incrementar, d=decrementar, q=salir): " ); io :: stdout (). flush (). unwrap ();let mut input : String = String :: new (); io :: stdin (). read_line ( & mut input ). unwrap (); let input : String = input . trim ();match input { "i" => self . view_model . increment_counter (), "d" => self . view_model . decrement_counter (), "q" => break , _ => println! ( "Comando desconocido." ), } } } }

Entonces, la aplicación main.rs podría ejecutarse de la siguiente manera:

mod mvvm ;use mvvm ::{ Modelo , Vista , ViewModel };fn main () { let mut m : Model = Model :: new (); let mut vm : ViewModel = ViewModel :: new ( & mut m ); let mut v : View = View :: new ( & mut vm ); v . run (); }

Véase también

Referencias

  1. 1 2 Smith, Josh; et  al. "Pensamiento: MVVM elimina el 99% de la necesidad de ValueConverters" . Google Groups .
  2. Martin Fowler (19 de julio de 2004). "El patrón de diseño del modelo de presentación" . Martin Fowler.com.
  3. 1 2 3 4 5 6 Smith, Josh (febrero de 2009). "Aplicaciones WPF con el patrón de diseño Modelo-Vista-ViewModel" . Revista MSDN .
  4. 1 2 Gossman, John (8 de octubre de 2005). "Cuentos del cliente inteligente: Introducción al patrón Modelo/Vista/ViewModel para la creación de aplicaciones WPF" .
  5. 1 2 Massey, Simon (9 de abril de 2011). "Patrones de presentación en ZK" . Recuperado el 24 de marzo de 2012 .
  6. Steve Sanderson. "KnockoutJS" .
  7. 1 2 "El patrón MVVM" . msdn.microsoft.com . 4 de octubre de 2012. Consultado el 29 de agosto de 2016 .
  8. Pete Weissbrod. "Patrón Modelo-Vista-Modelo de Vista para WPF: Otro enfoque más" . Archivado del original el 1 de febrero de 2008.
  9. Microsoft (3 de abril de 2024). "Tutorial: Crear una API web con ASP.NET Core" .
  10. Wildermuth, Shawn (11 de mayo de 2010). "Enlace de datos de Windows Presentation Foundation: Parte 1" . Microsoft . Consultado el 24 de marzo de 2012 .
  11. "ZK MVVM" . Potix . Consultado el 24 de marzo de 2012 .
  12. Karl Shifflett. "Aprendiendo WPF MV-VM" . Archivado del original el 13 de abril de 2009. Consultado el 5 de junio de 2009 .
  13. Gossman, John (4 de marzo de 2006). "Historias del cliente inteligente: ventajas y desventajas de MV-VM" . AI Skills Challenge .