Questo smell l’ho creato io questa mattina.
Nel senso che ho trovato del codice che non mi piaceva e ho voluto trovare una soluzione.
Problema:
Il client crea dei tipi con valori di default se le condizioni sono vere o altrimenti con i valori passati.Motivazione:
L’esponenziale presenza di if mi irrita l’epidermide e, nel codice che andremo a vedere, di if non ce ne sono poche.Tentendo questa logica, avremo un proliferare di condizioni inutili lungo tutto il nostro progetto.
Un esempio di logica errata:
Ecco un esempio, tratto da una Web Application, di controlli di valori nel quale ci potremmo imbattere:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string value1;
try
{
value1 = Page.Request.QueryString["value1"].ToString();
}
catch (System.Exception em)
{
value1 = "";
}
string value2;
if (Page.Request.QueryString["value2"] != null)
value2 = Page.Request.QueryString["value1"].ToString();
else
value2 = "";
}
}
Soluzione:
Tenendo presente la regola: far lavorare il client tramite interfacce e non tramite oggetti.
(Si, lo scriverò in ogni post, magari lo capiremo :D).
Per la soluzione ho tenuto presente 3 bisogni:
- Far tornare un valore di default se il valore nella QueryString è null o vuoto (Null Object).
- Far tornare un valore diverso da quello di default se specificato (Creation Methods).
- Mantenere la costruzione degli oggetti in un unico punto (Abstract Factory).
Questa è una possibile soluzione, la mia soluzione:
class Programm
{
static void Main(string[] args)
{
List<FactoryNullableObject> lst = new List<FactoryNullableObject>();
lst.Add(FactoryNullableObject.CreateMyObjectNoDefault(null));
lst.Add(FactoryNullableObject.CreateMyObjectWidthDefault("Giovanni", "Giuseppe"));
lst.Add(FactoryNullableObject.CreateMyObjectWidthDefault(null, "Salvo"));
foreach (FactoryNullableObject item in lst)
Console.WriteLine(item.Value);
Console.ReadLine();
}
}
abstract class FactoryNullableObject
{
private static FactoryNullableObject FactoryMethod(string key, string defaultValue)
{
if (key == null)
return new NullableQueryStringObject(defaultValue);
return new QueryStringNullable(key);
}
public static FactoryNullableObject CreateMyObjectNoDefault(string key)
{
return FactoryMethod(key, "");
}
public static FactoryNullableObject CreateMyObjectWidthDefault(string key, string defaultValue)
{
return FactoryMethod(key, defaultValue);
}
public abstract string Value { get; }
}
class QueryStringNullable : FactoryNullableObject
{
public QueryStringNullable(string key)
{
_value = key;
}
public string _value = "";
public override string Value
{
get
{
return _value;
}
}
}
class NullableQueryStringObject : FactoryNullableObject
{
public NullableQueryStringObject(string defaultValue)
{
_value = defaultValue;
}
public string _value = "";
public override string Value
{
get { return _value; }
}
}
Benefici e non + Semplifica e chiarifica la creazione degli oggetti. + Allegerisce la conoscenza da parte del client delle classi e della loro implementazione. + Mantiene viva la regola sull’utilizzo delle interfacce. - Potrebbe richiedere il passaggio di parametri ulteriori ai Factory Method. - E’ un metodo non standard per istanziare gli oggetti. Così potreste trovarvi alcune classi con costruttori classici e altre no. - Potrebbe esserci un proliferare di metodi CreateMyObject |
Se fosse realmente così non esisterebbe il Refactoring :)
No comments:
Post a Comment