Iniezione del metodo del costruttore, è questo uno schema?

0

Lavorando su WPF (programmazione dell'interfaccia utente) in C # ho iniziato a iniettare frequentemente metodi nel costruttore dei miei modelli di visualizzazione.

Ad esempio:

public class HtmlRegexListViewModel : ViewModel
{
   private readonly Action<HtmlRegex> onSelection;

   public List<HtmlRegex> HtmlRegexes { get; private set; }

   private HtmlRegex selected;
   public HtmlRegex Selected 
   {
      get { return selected; } 
      set 
      {
         selected = value;
         onSelection(value);  
      }
   }

   public HtmlRegexListViewModel(Action<HtmlRegex> onSelection, IDatabase database)
   {
      this.onSelection = onSelection;
      HtmlRegexes = database.LoadHtmlRegexesVerySlowly();
   }
}

Ora lo faccio principalmente sui modelli di visualizzazione perché non voglio passare allo sforzo di creare una coppia di classi derivate EventHandler ed EventArgs ogni volta che voglio dire all'oggetto padre che il mio stato è cambiato.

Comunque lo uso anche estensivamente altrove.

Sembra che sia uno stile di cui mi pentirò quando si tratta di mantenere il codice in futuro, ma al momento non riesco a pensare a molti aspetti negativi. Disaccoppia, preserva la separazione delle preoccupazioni ed è un buon modo per creare una classe che ha una sola responsabilità.

Quindi questo è un pattern (differito di doppia spedizione?), un anti-pattern o se non lo è, dovrebbe essere?

    
posta Underscore 15.10.2016 - 18:33
fonte

3 risposte

1

Le funzioni di iniezione del costruttore non sono un anti-modello in sé e per sé. E, al contrario, se vuoi essere dogmatico al riguardo, il tuo costruttore dovrebbe richiedere tutto ciò che un'istanza deve essere valida. (Però, di solito niente oltre ciò che è necessario per la validità.)

Detto questo, assicurati di considerare i dogmi prevalenti per quello che sono: linee guida per produrre più semplice, ESSERE -er, codice più gestibile. E poi pensa su come quelle regole dovrebbero essere manifestate o ignorate nel raggiungimento di quegli obiettivi finali nella tua applicazione.

Nel tuo caso, non sono sicuro che il tuo costruttore sia il posto giusto per l'iniezione di quella funzione. Se il tuo HtmlRegexListViewModel potrebbe essere valido senza l'evento / notifica, preferirei personalmente costruirlo in questo modo:

var o = new HtmlRegexListViewModel(database);
o.onSelection = () => { whatever(); };

O questo:

new HtmlRegexListViewModel(database) {
  onSelection = () => { whatever(); }
}

O qualsiasi altra cosa.

    
risposta data 15.10.2016 - 19:16
fonte
0

Non lo chiamerei "Iniezione del metodo del costruttore", perché non è un metodo, è un delegato e i delegati sono un po 'troppo tecnici e un po' troppo dipendenti dalla lingua: C # li supporta, molti altri linguaggi non. Potremmo entrare in una discussione sui meriti relativi dei delegati rispetto alle interfacce a metodo singolo, ma sarebbe un punto controverso; invece di concentrarmi sugli aspetti tecnici dell'argomento di questo costruttore, preferirei concentrarmi sul suo scopo, che è osservare gli eventi. Quindi, chiamerei "Iniezione dell'osservatore del costruttore".

Non ho mai sentito parlare di una cosa come uno schema, ma non penso che sia anche un anti-modello. Stai semplicemente creando un oggetto che offre un evento che può essere consegnato a un solo osservatore e impone che questo osservatore debba essere fornito al momento della costruzione.

Potresti leggermente pentirti se ti capita di dover istanziare un oggetto senza un osservatore, ma il danno è molto piccolo, perché puoi:

  • Passa null e fai controllare l'oggetto per null prima di richiamare l'osservatore, o

  • Basta passare un osservatore che non fa nulla; lambda lo rende molto facile.

Potresti pentirti ancora di più se ti capita di dover scrivere una classe che offre non uno ma 5 eventi, nel qual caso passare 5 osservatori come parametri di costruzione potrebbero iniziare a sembrare brutti.

Detto questo, perché dici che "non vuoi dedicarti alla creazione di una coppia di classi derivate EventHandler ed EventArgs"? Gli eventi non sono limitati a EventHandler s e EventArgs , puoi dichiarare un evento che opera su Action<HtmlRegex> in modo da poter avere zero o più osservatori invece di un solo osservatore.

    
risposta data 15.10.2016 - 18:51
fonte
0

In un'interpretazione OOP, Action<HtmlRegex> onSelection è un esempio del Modello di strategia . Hai parametrizzato la tua classe su un'operazione onSelection che viene inviata dinamicamente: qualsiasi azione fornita funzionerà finché sarà conforme all'interfaccia Action<HtmlRegex> . Sebbene Action sia un tipo predefinito, potresti anche definire la tua stessa interfaccia con lo stesso effetto, sebbene ciò sarebbe stato più ingombrante per gli utenti:

interface SelectionHandler
{
  void Handle(HtmlRegex r);
}

...

class HtmlRegexListViewModel
{
  ...
  public HtmlRegexListViewModel(SelectionHandler onSelection, IDatabase database)
  {
    ...
  }
}

L'iniezione di una dipendenza strategica attraverso il costruttore è il solito modo di farlo, ma è possibile qualsiasi tecnica di iniezione delle dipendenze.

In un'interpretazione di programmazione funzionale, questa è solo una richiamata. Non c'è niente di speciale qui, e sarebbe troppo comune avere un nome particolare.

    
risposta data 15.10.2016 - 21:16
fonte

Leggi altre domande sui tag