Pattern Decoratore: può risolvere problemi derivanti da modifiche al codice sottostante?

1

Comprendo che i decoratori risolvono il problema di dover combinare i comportamenti, ma è stato suggerito di utilizzare il pattern di decoratore per risolvere i problemi di fragilità che potrebbero verificarsi a causa delle modifiche nel codice di base sottostante.

In particolare, Microsoft fornisce un ActiveDirectoryMembershipProvider con metodi virtuali per la creazione e l'aggiornamento degli utenti. Il metodo di aggiornamento non aggiorna tutte le informazioni che vorremmo aggiornare quindi ho pensato che dovremmo creare una nuova classe che eredita da ActiveDirectoryMembershipProvider in modo da poter chiamare l'implementazione di base e quindi scrivere il codice per aggiornare le informazioni estese che il l'implementazione di base non copre.

Ma è stato suggerito che poiché ActiveDirectoryMembershipProvider è un codice di terze parti, potremmo incorrere in problemi che potrebbero essere risolti dal pattern di decoratore. Non mi sembra che eventuali problemi derivanti dai cambiamenti nel codice sottostante possano essere mitigati dal modello di decoratore. Mi manca qualcosa qui?

    
posta BVernon 15.10.2014 - 18:06
fonte

3 risposte

5

Ripeti dopo di me - I pattern non sono sempre la risposta

Uff. Ora che l'abbiamo tolto di mezzo, permettiamo di andare avanti. Prima di tutto, ogni volta che estendi codice di terze parti che non fornisce alcuna garanzia sulla durata della vita o sulle dichiarazioni di funzioni, stai chiedendo un incubo quando aggiorni quel codice di terze parti. Un metodo potrebbe cambiare i suoi parametri, o la classe può essere rimossa tutti insieme, lasciando il tuo codice ora vuoto e solo.

Il pattern di decoratore è ottimo per consentire di modificare in modo granulare piccoli pezzi del metodo sottostante, ma non è la soluzione completa che si può pensare che sia. Se hai bisogno di aggiungere un intero pattern e tutta la cerimonia che ne consegue per modificare una piccola variabile, perché non creare un metodo che faccia proprio questo. Non hai bisogno di essere iperestensibile o preoccuparti di quali siano le qualità del modello. Fai semplicemente ciò che devi fare senza tutto il sovraccarico.

    
risposta data 15.10.2014 - 18:18
fonte
3

Sono d'accordo con risposta di @ Ampt .

Vorrei aggiungere un altro argomento qui.

Nota che puoi sempre ereditare da una classe - voglio dire, nella maggior parte delle lingue popolari, che comprende C #. (E anche in quelli dove è possibile, come il C ++, si consiglia di usare questa possibilità con parsimonia).

Quindi, rendendo la tua classe estendere ActiveDirectoryMembershipProvider , la stai effettivamente impedendo di estendere qualsiasi altra classe, o di incorporarla in qualsiasi gerarchia di classi personalizzate che hai in atto.

La composizione (basata sulla delega) batte l'ereditarietà in termini di flessibilità, decoratore o meno.

Un altro fattore è la testabilità. Se crei un decoratore che avvolga ActiveDirectoryMembershipProvider , potrebbe essere più facile sostituirlo con un oggetto fittizio a scopo di test.

    
risposta data 15.10.2014 - 18:34
fonte
0

Aiuta a capire esattamente cosa Decorator Pattern ti permette di fare.

Concentriamoci su un decoratore che avvolge una singola funzione. (Per tutte le altre chiamate al metodo, il decoratore lo inoltrerà direttamente verso l'oggetto sottostante.)

Questo è ciò che il metodo del decoratore potrebbe fare:

  • Possibile fare alcuni dei suoi contenuti prima chiamando l'oggetto sottostante
  • Probabilmente chiama il metodo con lo stesso nome sull'oggetto sottostante
    • Oppure, forse no. La chiamata è stata mangiata dal mio cane.
    • Oppure, chiamalo ancora, ma con un diverso set di parametri.
  • Dopo essere ritornati dal metodo sull'oggetto sottostante, possibilmente fare qualche altra cosa a parte.
    • Pronuncia, sostituisci il valore restituito.
    • Oppure, getta una pizza.

Per pizza intendo eccezione.

Ciò che Decorator non potrebbe fare, è:

Un metodo decoratore non può dettare il flusso di controllo interno del metodo nell'oggetto sottostante, in modi che l'oggetto sottostante non espone.

Ciò che intendo è:

Se l'oggetto sottostante espone commutatori e interruttori che influenzano il flusso di controllo interno del suo metodo, bene. Il tuo metodo di decoratore può utilizzare questi commutatori e interruttori ed eventualmente ripristinarli dopo essere tornati dal metodo sottostante.

Se l'oggetto sottostante non ti consente di influenzare alcuni aspetti del suo flusso di controllo interno, sei bloccato.

In questo caso, se hai bisogno di implementare il tuo flusso di controllo alternativo per sostituire completamente il metodo sottostante, c'è un nome per questo. Il pattern Copia e incolla.

Tuttavia, non puoi farlo:

Esegui i successivi 253 byte di codice macchina dopo aver inserito il metodo sottostante. Salta i successivi 47 byte di codice macchina. Oh, a proposito, immetti un po 'di spazzatura nello stack del metodo sottostante e preparati a prendere il controllo dell'hypervisor della macchina con un exploit zero-day.

In realtà potresti farlo, ma questo è chiamato un Trojan, non un Decorator.

Quindi, tornando alla domanda principale. Devo usare un decoratore o una classe derivata?

Credo che lascerò quella domanda a persone che conoscono infinitamente meglio la tua base di codice.

    
risposta data 16.10.2014 - 08:47
fonte

Leggi altre domande sui tag