La mia domanda è simile a (ma non esattamente uguale a) questa domanda . Questa domanda è stata anche utile, ma è meno simile alla mia domanda attuale rispetto alla domanda precedente a cui mi sono collegato.
Ho un framework che esegue test automatici. Fondamentalmente, uno "script" XML ha dati su quali metodi chiamare contro la nostra API; il nostro motore esegue i metodi specificati con la riflessione.
A causa di come vengono generati i log, a volte vogliamo sostituire alcune chiamate di metodo con un'altra. (Non c'è davvero alcun modo per aggirare questo). Una fabbrica "sa" quali metodi sono basati su un file XML che contiene la "mappatura".
// Originally we called this a "Command" pattern but it may be more accurate to call it a Strategy
// See if we're supposed to replace this method call with something else
bool wereAnyCommandsRun = await ExecuteCommandsIfThereAreAny(interfaceName, methodName);
// If we're NOT supposed to replace this method call, go ahead and execute it
if (!wereAnyCommandsRun)
{
// Do the method call
// ...
}
Facciamo il mapping XML in questo modo:
<map method="CaptureDomain" interface="IFrameworkInterface" command="ApplyXsltCommand"/>
In questo momento i "comandi" (probabilmente con maggiore precisione "Strategie") sono completamente standard - implementano un'interfaccia con un metodo Execute ().
Ora ho bisogno di aggiungere parametri a questo. Non so in anticipo quali parametri avranno bisogno, quindi sto cercando di trovare qualcosa che non sia completamente odioso e fragile. I miei requisiti principali sono che non voglio che il design diventi eccessivamente complicato; inoltre, il punto principale di questo è rendere il mio motore il più possibile "a prova di futuro", quindi voglio assicurarmi che non richieda modifiche se aggiungo o rifattore un metodo o una nuova richiesta (nel senso che il Comando e il suo chiamante devono essere accoppiati liberamente).
Alcune idee che ho avuto e respinto:
- Accettare un array params e utilizzare reflection per decidere se il chiamante ha trasmesso valori del tipo corretto. Non mi piace però perché aumenta drasticamente l'accoppiamento tra il comando e l'intero punto del meccanismo è quello di ridurre l'accoppiamento.
- Crea parametro "oggetti" per ogni tipo possibile. Anche questo creerebbe un sacco di "accoppiamenti".
- Fabbriche parametrizzate
Alcune idee che sto prendendo seriamente in considerazione:
- Avere un oggetto Contesto come una delle risposte nella domanda che ho collegato a suggerito. Se sto leggendo la domanda che ho collegato correttamente, i vantaggi qui sarebbero che il chiamante non dovrebbe "sapere" nulla sul comando in anticipo. Ci potrebbe essere un calo di prestazioni se finisco per catturare troppe informazioni sul chiamante, ma le prestazioni non sono una considerazione importante qui.
- Ho un oggetto MethodInfo e informazioni sui parametri per il metodo che sto sostituendo - magari aggiungilo come un terzo "elemento" nella mappatura di Factory. Il primo problema che vedo qui è simile allo svantaggio della soluzione precedente: il fatto che un parametro sia necessario per il metodo chiamato non implica che sia anche necessario per il comando. Inoltre, i miei comandi possono essere chiamati con diversi metodi, quindi è importante che non vi sia alcun accoppiamento tra di essi (quindi è più complicato di un semplice "se si visualizza questo elenco di parametri, utilizzare quel comando"). Questo potrebbe portare ad un eccessivo accoppiamento?
- Cerca di implementare una sorta di modello di visitatore al posto del modello di strategia. Tuttavia, sono un po 'confuso su come funzionerebbe effettivamente per dire la verità. Sarebbe solo aggiungere complessità inutile o sarebbe davvero una soluzione legittima qui?
Spero che questo non sia troppo ampio o basato sull'opinione pubblica (per favore fammi sapere se è così e io modificherò - Sono decisamente non che provo a chiedere un "gimme teh" codez "tipo question), ma qualcuno vede un problema con queste soluzioni?