2012-02-20 9 views
24

Sono uno sviluppatore Java che è a partire dal per cogliere tutta la potenza delle iniezioni di dipendenza, e improvvisamente mi sono reso conto che non c'è modo di iniettare un metodo statico. Quindi mi ha fatto pensare: sono metodi statici di anti-pattern?I metodi statici sono un anti-pattern DI?

Ancora più importante: se dovessi accettare l'iniezione di dipendenza, significa che devo interrompere la codifica dei metodi statici? Chiedo perché non c'è modo di deriderli e iniettare finte statiche durante i test unitari, il che è un enorme spunto per me.

Edit: So che un modo comune per "avvolgere" e iniettare un metodo statico esistente è come questo:

public class Foo { 
    public static void bar() { ... } 
} 

public interface FooWrapper { 
    public void bar(); 
} 

public class FooWrapperImpl implements FooWrapper { 
    public void bar() { 
     return Foo.bar(); 
    } 
} 

... ma io non sto chiedendo come iniettare un statica esistente metodo ... Sto chiedendo se dovrei smettere di scriverli tutti insieme, se tutto il mio codice (da questo punto in avanti) abbraccerà la nozione di DI.

Inoltre, vedo un sacco di domande simili a questo, ma non sono riuscito a trovare una corrispondenza esatta che ha posto la stessa domanda. Se vedi che è davvero un capriccio di un'altra domanda, ti prego di indicarmelo e chiuderò io stesso questa domanda (per favore non limitarti a chiuderla!).

risposta

38

I metodi statici sono appropriati per le cose che non hanno lo stato associato . Alcuni metodi di fabbrica, metodi "puramente funzionali" come e simili sono tutti metodi statici perfettamente accettabili. java.lang.Math e java.util.Collections hanno molti ottimi esempi di metodi statici perfettamente accettabili.

Fortunatamente, questi metodi non hanno bisogno di iniezioni di dipendenza o di interagire con tali cose; non sono insolitamente difficili da testare. Non hanno dipendenze che avrebbero bisogno di deridere o altro.

D'altra parte, lo stato statico, o metodi statici con stato statico associato, sono completamente malvagi. Che è un anti-modello.

Spesso aiuta a definire un metodo come non statico (e quindi un metodo statico legittimo) se, e solo se, restituisce sempre un output equivalente su input equivalenti. Ciò rende chiaro che ad es. le query sul database e l'I/O del filesystem rendono i metodi stateful, perché i loro output variano a seconda di cosa si trova nel filesystem o nel database.

+0

Quindi, se ho un metodo chiamato 'fizz()' e in esso faccio una chiamata statica a un metodo 'Widget.buzz()', che colpisce un database e apporta tutti i tipi di modifiche al mio file system locale, allora come faccio a testare 'fizz()' senza invocare tutte le enormi modifiche apportate chiamando 'Widget.buzz()'? Il mio punto è, penso che dovrei smettere di scrivere del tutto il metodo statico, in modo da poter poi iniettare quel corretto oggetto 'Widget' (normale vs mock), e quindi controllare quale" versione "di' buzz() 'si attiva in fase di runtime. Pensieri? – IAmYourFaja

+0

'Widget.buzz()' ha uno stato statico associato - il database, e implicitamente, l'intero filesystem. Questo è male. 'fizz' potrebbe prendere un argomento' Widget', e si dovrebbe prendere in giro un 'Widget' per testare' fizz'. –

+0

Ahhh, non ho mai pensato al database o al filesystem come stato. Che criteri usi per definire lo "stato"? Penso che sia la radice del mio fraintendimento. – IAmYourFaja

2

I metodi statici non banali sono non compatibili con l'iniezione delle dipendenze. Basta renderli esempi di metodi di singleton.

Problemi correlati