ReactiveUI, View / ViewModel injection y DI en general

Últimamente, estoy tratando de meterme en la nueva era del desarrollo de IU y descubrí ReactiveUI. Me encanta su carácter declarativo.

Quería hacer un cambio completo, así que intenté entender cómo se hacen las cosas en este nuevo mundo de ReactiveUI. Elijo ReactiveUI porque he visto que lo mantiene un tipo muy inteligente (Paul C. Betts).

Soy muy nuevo en eso y probablemente estaré inundando StackOverflow con preguntas al respecto porque tengo un gran poder y creo que merece ser aprendido y dominado .

Vamos a entrar en los detalles:

Siempre he usado View-First. Soy un usuario veterano de Cinch Framework ( http://cinch.codeplex.com/ )

Utiliza MEF para inyectar los ViewModels a cada Vista. Solo tiene que decorar su ViewModel con [ViewModel (“SampleView”)] y agregar una propiedad adjunta a su vista (ViewModelLocator.ViewModel = “SampleView”), y cada vez que se carga la vista, el ViewModel correspondiente se crea una instancia y se inyecta DataContext con el ciclo de vida que elijas.

Este mecanismo, si bien es válido, tiene algunos inconvenientes. Lo peor de ellos: utiliza un localizador.

Como Mark Seemann sugiere en su libro, ServiceLocator es un antipatrón que debe evitarse.

  1. Entonces, mi primera pregunta es: ¿ReactiveUI está construido sobre una infraestructura basada en Locator?
  2. View-First o ViewModel-First? ¿Qué es mejor en términos de buenas prácticas, desacoplamiento, SÓLIDO y cosas como estas que preocupan a un amante loco y pro-código limpio de Microsoft como yo? ¿Cuál me hará dormir mejor y proporcionará mi aplicación con todas esas cualidades?

Es probable que Paul contribuya con la respuesta oficial, pero pondré $ 0.02 como persona que ha usado el marco para algunos proyectos, pero de ninguna manera es un experto.

1) Soy un gran fanático de Mark Seemann y estoy de acuerdo con su conclusión sobre el anti-patrón ServiceLocator. Si bien ReactiveUI usa el Localizador “Splat”, no lo consideraría construido sobre una infraestructura basada en el Localizador. Hay algunos elementos globales que se utilizan como progtwigdores de subprocesos y algunas configuraciones importantes, pero estos se configuran principalmente en el inicio de la aplicación (como cualquier contenedor DI) y no los trata directamente en sus clases en su mayor parte. La única ubicación real es el control ViewModelHost , que utiliza una interfaz específica ( IViewFor ) en las vistas para registrarse en ViewModels. Esto es mejor que el método de atributo, ya que mantiene a ViewModels felizmente inconsciente de las Vistas. Pero esto sucede en el control en sí mismo y forma parte del marco, por lo que no creo que se trate de un abuso del anti-patrón ServiceLocator. No siento que sea diferente a registrar cualquier otra cosa en la configuración de un contenedor DI.

2) Solo en mi experiencia desde el uso de ReactiveUI, mis vistas se han vuelto súper simples. Básicamente, aplique un poco de XAML básico para obtener el aspecto y el diseño correctos, implemente IViewFor en el código que se encuentra detrás, y haga todos mis enlaces en el constructor. a). Entonces todo lo lógico se hace en los ViewModels. Creo que generalmente hago un enfoque de ViewModel First solo por el hecho de que necesito tenerlo (o al menos su interfaz) definido para implementar IViewFor<> para él en la Vista. Me gusta la comprobación de tipos y otras cosas (otra razón por la que me gusta enlazar en el constructor no en XAML). Pero no creo que haya una razón fuerte para hacerlo de una manera u otra, desde mi experiencia.

ServiceLocator es un anti-patrón que debe evitarse.

En general, creo que muchos de los consejos sobre IoC / DI son bastante malos en el ámbito de las ‘aplicaciones móviles multiplataforma’, porque hay que recordar que muchas de sus ideas se escribieron para aplicaciones web, no para aplicaciones móviles o de escritorio.

Por ejemplo, la gran mayoría de los contenedores IoC populares se refieren únicamente a la velocidad de resolución en una caché cálida, mientras que básicamente ignoran el uso de la memoria o el tiempo de inicio, esto es 100% correcto para las aplicaciones de servidor, porque estas cosas no importan; pero para una aplicación móvil? El tiempo de inicio es enorme .

La ubicación del servicio de Splat resuelve varios problemas para RxUI:

  1. La ubicación del servicio es rápida y casi no tiene gastos generales para configurar.
  2. Encapsula varios modelos diferentes de vida útil de objetos comunes (es decir, ‘crear nuevos cada vez’, ‘singleton’, ‘perezoso’), simplemente escribiendo el Func de manera diferente
  3. Es Mono Linker amigable (en general)
  4. La ubicación del servicio nos permite registrar tipos en el código específico de la plataforma, pero usarlos en el código PCL.

La mejor manera de usar Service Locator

De hecho, en general estoy de acuerdo con Mark Seemann, ya que la inyección del constructor es la forma preferida de hacerlo, este es el patrón que realmente me gusta:

  public SuspensionHost(ISuspensionDriver driver = null) { driver = driver ?? Locator.Current.GetService(); } 

Esto utiliza una interfaz de Servicio Localizado para la interfaz predeterminada, pero solo si la persona que llama no dio una explícita en el constructor. Mucho más sencillo de probar en un corredor de pruebas unitarias que tratar de construir un contenedor de IoC simulado, pero aún recurre a una implementación predeterminada en tiempo de ejecución.

View-First o ViewModel-First?

Si puede usar enrutamiento basado en VM (es decir, RoutedViewHost, IScreen, RoutingState y amigos) en ReactiveUI depende de la plataforma en la que se encuentre:

  • WPF, Xamarin Forms: Absolutamente
  • WP8, WinRT: puedes hacerlo funcionar, pierdes algunas transiciones y sutilezas
  • Android, iOS nativo: muy difícil de hacer funcionar