Immagina un esempio concreto di un codice che, dato il prezzo di un articolo, dovrebbe chiamare un metodo specificando se l'articolo è un rimborso (prezzo inferiore a zero), un prodotto pagato (prezzo superiore a zero) o un valore gratuito prodotto (prezzo uguale a zero).
Le tue due parti di codice diventano:
Soluzione 1:
if (price < 0)
{
this.DoSomething(PriceType.Rebate);
}
else if (price > 0)
{
this.DoSomething(PriceType.Product);
}
else // price == 0
{
this.DoSomething(PriceType.Free);
}
Soluzione 2:
priceType = PriceType.Free;
if (price < 0)
{
priceType = PriceType.Rebate;
}
else if (price > 0)
{
priceType = PriceType.Product;
}
this.DoSomething(priceType);
La seconda soluzione, così com'è, ha meno righe (10 contro 12), nonostante la tua affermazione che "occupa più righe di codice", ma la prima sembra più leggibile. D'altra parte, la seconda soluzione può essere rifattorizzata per diventare molto più leggibile:
Refactoring della soluzione 2:
private PriceType FindPriceType(price)
{
if (price < 0)
{
return PriceType.Rebate;
}
else if (price > 0)
{
return PriceType.Product;
}
return PriceType.Free;
}
...
this.DoSomething(this.FindPriceType(price));
Separando il metodo originale in due metodi, il codice diventa più leggibile attraverso l'introduzione di un nome esplicito del metodo.
Esistono anche due casi specifici in cui la seconda soluzione offre ulteriori vantaggi:
Casi specifici
Il primo caso è quello in cui le condizioni tutte hanno la forma: if (something == value)
. Ad esempio:
if (priceType == 1)
{
return PriceType.Rebate;
}
if (priceType == 2)
{
return PriceType.Product;
}
if (priceType == 3)
{
return PriceType.Free;
}
throw new NotImplementedException();
può essere trasformato in molto più breve:
var map = {
1: PriceType.Rebate,
2: PriceType.Product,
3: PriceType.Free
}[priceType];
Un secondo caso specifico è dove non ci sono tre rami, ma solo un if/else
. Esempio:
Soluzione 1:
if (price < 0)
{
this.DoSomething(PriceType.Rebate);
}
else
{
this.DoSomething(PriceType.Product);
}
Soluzione 2:
priceType = PriceType.Product;
if (price < 0)
{
return PriceType.Rebate;
}
this.DoSomething(priceType);
In questo caso, la seconda soluzione può (in molte lingue) essere trasformata in one-liner:
this.DoSomething(price < 0 ? PriceType.Rebate : PriceType.Product);