Sì, è fattibile e potrebbe essere una buona idea
Certamente questo è fattibile e può spesso generare una logica più chiara, a seconda di quali parametri stai usando. Speriamo che i parametri siano collegati in qualche modo a un concetto di business ben compreso.
Identifica il concetto di business nascosto
Nei casi in cui i due parametri sono mappati su un singolo concetto di business (nascosto), è necessario rendere esplicito tale concetto, utilizzando una funzione di mappatura che prende p
e q
e restituisce il caso.
Questo esempio corrisponde al tuo primo esempio:
z = map(p, q)
switch (z)
case z1:
a();
break;
case z2:
b();
break;
case z3:
c();
break;
case z4:
d();
break;
}
O per il tuo secondo esempio:
z = map(p, q)
switch (z)
case z1:
a();
break;
case z2:
a();
b();
break;
case z3:
c();
break;
case z4:
//No operation
break;
}
Qual è la funzione di mappatura?
La funzione di mappatura può essere semplice come combinare p
e q
in una maschera di bit (se sono booleani) o combinare stringhe (se si tratta, ad esempio, di codici prodotto e sottoprodotto). Questo potrebbe essere un allungamento in alcune circostanze, ma è una soluzione semplice e ovvia in altre circostanze. Ad esempio, prendi in considerazione queste domande che potrebbero apparire in una domanda di assicurazione sanitaria:
- sei sposato? Sì o no
- Hai figli? Sì o no
In questo caso, la tua azienda potrebbe offrire quattro prodotti (il concetto di business nascosto): single, sposato, single con figli e sposato con figli. In questo tipo di scenario è perfettamente giustificato combinare le risposte dell'utente in un prodotto virtuale (dato dalla funzione di mappatura) e scegliere un percorso logico basato sul prodotto anziché sulle singole bandiere. In effetti è un codice molto migliore, IMO.
Sbarazzarsi del caso interruttore
Switch / case è brutto. Un altro approccio continuerebbe a utilizzare il concetto di business nascosto ma in uno schema di codice più pulito:
IProduct z = ProductFactory.GetProduct(q, p);
z.Execute();
... dove la factory può restituire uno dei quattro prodotti, ognuno dei quali implementa IProduct
che contiene un metodo Execute
specifico del prodotto che eseguirà a()
, b()
, c()
e / o d()
se necessario.
La fabbrica non avrà lo stesso problema (originale)?
La factory potrebbe contenere dichiarazioni% co_de nidificate (che riportano indietro il problema originale) oppure potrebbe utilizzare una tabella di ricerca per l'istanziazione, come questa:
class ProductFactory
{
private static readonly Dictionary<bool, Dictionary<bool, Func<IProduct>>> _products
= new Dictionary<bool, Dictionary<bool, Func<IProduct>>>();
static ProductFactory()
{
_products.Add(false, new Dictionary<bool, Func<IProduct>> {
{ true, () => new ProductSingleWithChildren() },
{ false, () => new ProductSingle() }
});
_products.Add(true, new Dictionary<bool, Func<IProduct>> {
{ true, () => new ProductMarriedWithChildren() },
{ false, () => new ProductMarried() }
});
}
public IProduct GetProduct(bool isMarried, bool hasChildren)
{
return _products[isMarried][hasChildren]();
}
}
... dove if
è un elenco di elenchi, ogni elemento contenente un _products
che istanzia il tipo appropriato.
I dizionari con una chiave di Func<IProduct>
sembrano un po 'strani, quindi in un vero pezzo di codice potresti inclinarti a utilizzare bool
, oppure possibile a enum
contenente un codice. Suggerirei di utilizzare un identificatore allineato con il business / dominio; rendere facile per gli altri sviluppatori capire cosa sta succedendo.
Per completezza, ecco un'idea di come sarebbero le classi:
interface IProduct
{
void Execute();
}
class ProductSingle : IProduct
{
public void Execute()
{
a();
}
}
class ProductSingleWithChildren : IProduct
{
public void Execute()
{
a();
b();
}
}
class ProductMarried: IProduct
{
public void Execute()
{
c();
}
}
class ProductMarriedWithChildren : IProduct
{
public void Execute()
{
//No operation
}
}
Noterai che alla fine non ci siamo solo sbarazzati della condizione string
duplicata, ci sono infatti dichiarazioni di% ZERO% co_de nell'intera soluzione !!! :) Abbastanza pulito, e ti fornirà un punteggio di complessità ciclomatica basso e una buona pipeline pulita della CPU. Più codice molto più leggibile.
Poi di nuovo, abbiamo appena scritto un sacco di più righe di codice rispetto all'esempio originale. Quindi, a seconda del contesto, forse le dichiarazioni% co_de nidificate sarebbero migliori, in alcuni casi, ad es. la combinazione dei flag è arbitraria o non si associa ad un concetto logico all'interno del problema aziendale, o la leggibilità extra non è necessaria per un certo piccolo problema. Dipende da te, naturalmente.