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