Su twitter ho proposto scherzosamente di abolire la parola chiave static
dei linguaggi garbage collected.
All'inizio era appunto uno scherzo, poi mi sono detto:
posso effettivamente fare a meno di static?Innanzitutto, perché fare a meno di static? Perché può dare un sacco di problemi.
Factory
Prendiamo una classe e un'innocente metodo static per costruirla:
public class DumbClass {
private String foo;
public String getFoo() { return foo; }
public void setFoo(String foo) { this.foo = foo; }
private String initializedStuff;
public String getInitializedStuff() { return initializedStuff; }
private DumbClass(String foo, String initializedStuff) {
this.initializedStuff = initializedStuff;
this.foo = foo;
}
public static DumbClass create(Context c) {
return new DumbClass( c.doSomethingToGetFoo(), c.doSomethingToGetStuff() );
}
}
Inevitabilmente, come dice Alan Shalloway, le specifiche cambiano e uno dei vostri clienti vuole che, solo per lui, foo sia in CamelCase piuttosto che tutto MAIUSCOLO. E voi:
Facile: mettiamo in una libreria (che diamo solo a lui) una classe che estend.. Ops: non si può estendere, è un metodo statico! E se invece avessi fatto un'abstract factory?
public class DumbClass {
private String foo;
public String getFoo() { return foo; }
public void setFoo(String foo) { this.foo = foo; }
private String initializedStuff;
public String getInitializedStuff() { return initializedStuff; }
DumbClass(String foo, String initializedStuff) {
this.initializedStuff = initializedStuff;
this.foo = foo;
}
}
public interface IDumbClassFactory {
DumbClass create(Context c);
}
public class DefaultDumbClassFactory {
public DumbClass create(Context c) {
return new DumbClass( c.doSomethingToGetFoo(), c.doSomethingToGetStuff() );
}
}
Allora basterebbe wrappare DefaultDumbClassFactory o fare un'altra implementazione di IDumbClassFactory e avrei fatto! Morale: non usare metodi statici, meno che mai pubblici!
Campi privati
A volte capita di voler tenersi un contatore di istanze di una certa classe per sapere quante ce ne sono in giro. E si fa con un bel campo static:
public class Foo {
private static int howMany;
public Foo(Something s) {
howMany++;
}
...
}
Risultato? Scoprite che in realtà quel contatore non lo legge mai nessuno, anzi, se usate la libreria su un web server che gira per 2 anni di fila, alla fine vi va in overflow e causa un eccezione che ovviamente non gestite perché non ci avevate pensato. Oppure vorrete che non tenga traccia delle classi figlie, oppure per qualcuna sì e qualcuna no, e allora? Scoprite che vi serviva un'abstract factory.
Morale: quando sto per scrivere static ci penso due volte e quasi sempre alla fine scrivo: interface
1 commento:
...eppure credo che metodi di utilità sia corretto definirli statici, la clausola static infatti ne definisce l'indipendenza con qualsiasi istanza e questo è corretto dal momento che sono di utilità a qualsiasi istanza.
Posta un commento