La mia applicazione sta diventando sempre più complessa.
Attualmente, ho una collezione di classi che compongono un "Backend", questo contiene un DataInterface che parla con un database e restituisce le classi POCO, un ModelProvider che li avvolge nei modelli e un ViewModelProvider che crea viste, tutto dipendenti l'uno dall'altro.
Queste istanze vengono create all'avvio dell'applicazione e quindi racchiuse in una singola classe "back-end". C'è solo un'istanza di questo per l'applicazione. Sto scoprendo che molte, molte classi hanno bisogno di portare in giro questa istanza di Backend per funzionare.
Ho anche un AppController di classe che controlla la navigazione di alto livello e cose come mostrare dialoghi.
Di conseguenza, queste due classi vengono passate nei costruttori per quasi tutti i ViewModel che faranno qualsiasi cosa che sia stata completata.
Questo non mi sembra sensato, ma deve essere un problema molto comune avere un paio di classi a istanza singola a cui è necessario accedere in tutta l'applicazione.
Stavo pensando che una soluzione sarebbe quella di creare una singola classe statica (ad esempio la classe "backend" già esistente) che potrebbe tenere traccia di ciò, quindi tutto ciò che devo fare è:
StaticBackend.ViewModelProvider.GetSomeViewModelsForMe();
Questa è una buona pratica o esiste un modo più consolidato per farlo?
Iniezione di dipendenza:
Sto cercando di capire come si fa l'iniezione di dipendenza. Sembra che non sia lontano se inizio a creare interfacce per ModelProvider, ViewModelProvider ecc.
Sembra che mi troverei in un posto simile, tranne che le cose potrebbero essere formalmente più sensate, dovrei comunque "iniettare" le classi di IModelProvider e IViewModelProvider fino in fondo dal costruttore al costruttore.
Ecco come stanno le cose al momento (ma incapsulando parte del back-end in interfacce):
interface INavagationManager
{
void NavagateTo(Page page);
}
interface IViewModelProvider
{
void CreateSomeViewModelsToDisplay();
}
class HomePage : Page
{
INavagationManager NavagationManager;
IViewModelProvider ViewModelProvider;
//this contains no dependencies on the IViewModelProvider, but it does with INavagationManager
public HomePage(INavagationManager navagationManager, IViewModelProvider viewModelProvider) {
this.NavagationManager = navagationManager;
//this is "injected" but it's not really a dependency of HomePage, as it never wants to get ViewModels, but the pages it creates do
this.ViewModelProvider = viewModelProvider;
}
public void UserWantsToNavagateSomewhere()
{
//all ViewModelProvider exists for is to be passed on down the 'chain'
NavagationManager.NavagateTo(new SubPage(ViewModelProvider));
}
}
class SubPage : Page
{
IViewModelProvider ViewModelProvider;
List<MyViewModel> MyViewModels;
public SubPage(IViewModelProvider viewModelProvider)
{
ViewModelProvider = viewModelProvider;
//actually use this dependency for something
MyViewModels = ViewModelProvider.CreateSomeViewModelsToDisplay();
}
}
L'uso delle interfacce facilita l'esecuzione di UnitTesting in futuro, in quanto è possibile alimentarlo in INavagationManager ecc. per testare il comportamento. Ma sono ancora nella stessa posizione in cui ero prima, sono ancora un po 'confuso su come i contenitori IoC si adattano.
Sembra che creerei un container, che si occupa delle dipendenze di iniezione come IViewModelProvider e INavagationManager nell'esempio sopra, e preferirei passare il contenitore tra tutti gli oggetti? In questo modo:
interface INavagationManager
{
void NavagateTo(Page page);
}
interface IViewModelProvider
{
void CreateSomeViewModelsToDisplay();
}
class HomePage : Page
{
Container Container;
INavagationManager NavagationManager;
//this contains no IViewModelProvider, but in instance of Container
public HomePage(Container container, IViewModelProvider viewModelProvider) {
this.NavagationManager = navagationManager;
this.Container= container;
}
public void UserWantsToNavagateSomewhere()
{
//all ViewModelProvider exists for is to be passed on down the 'chain'
NavagationManager.NavagateTo(Container.GetInstance<SubPage>());
}
}
class SubPage : Page
{
IViewModelProvider ViewModelProvider;
List<MyViewModel> MyViewModels;
public SubPage(IViewModelProvider viewModelProvider)
{
ViewModelProvider = viewModelProvider;
//actually use this dependency for something
MyViewModels = ViewModelProvider.CreateSomeViewModelsToDisplay();
}
}