Domande sulle funzioni statiche

5

Oggi mi è venuto in mente qualcosa. Ho fatto molto del seguente

new Object().doSomething();

Creo un oggetto e invoco le sue funzioni, quindi dimentico dell'oggetto. Non ho bisogno di superare questa istanza. Questo segnala uno stile di codifica errato. È meglio convertire questi metodi in una funzione statica, quindi non è necessario creare ogni volta un nuovo oggetto?

    
posta AngryBird 07.10.2011 - 00:00
fonte

5 risposte

9

Creare un oggetto solo per chiamare un metodo su di esso e poi scartare dopo che la chiamata è generalmente una cattiva idea. Quindi, una possibile soluzione è convertire quel metodo di istanza in un metodo statico. Puoi anche lasciarlo come metodo di istanza, ma usare solo un'istanza di quella classe per tutto il codice. Quest'ultimo può essere applicato utilizzando il Pattern Singleton, come suggerisce @AJC.

Ma la tua domanda nasconde un problema più profondo. Supponiamo che il metodo doSomething() sia utilizzato nel contesto della logica aziendale. In tal caso, se crei l'oggetto in quel contesto, o chiami un metodo statico, o ottieni un riferimento all'oggetto tramite Singleton, stai rendendo il tuo codice molto difficile da testare. In questi tre scenari, la chiamata al metodo non può essere derisa da un test di unità perché il test non può controllare come viene istanziato l'oggetto. Quindi, sei bloccato con quella "versione" del metodo, che, a sua volta, può chiamare altri metodi statici o Singletons, che possono creare un'istanza delle loro dipendenze e così via e così via. Pertanto, anche se provi a scrivere un test unitario per quel metodo, finirai per testare un gruppo di classi della tua applicazione contemporaneamente. Inoltre, stai mescolando la logica di business con la creazione di oggetti, violando il principio di singola responsabilità e rendendo più difficile il tuo codice mantenere.

Il tuo codice dovrebbe raramente "prendere" le dipendenze di cui ha bisogno. Invece, dovrebbe solo dichiarare ciò di cui ha bisogno e lasciare la responsabilità di creare tali dipendenze in un'altra classe (in genere chiamate fabbriche ). Questa tecnica di progettazione viene spesso definita dipendenza da iniezione .

    
risposta data 07.10.2011 - 00:40
fonte
5

Questo dipende da cosa esattamente stai facendo in quella funzione e se puoi chiamarlo statico o meno. (variabili statiche all'interno, ecc ...)

Ma dal modo in cui sembra utilizzarlo, la risposta è sì. Dichiarare una classe statica o utilizzare il Singleton Pattern . Ma non continuare a fare quello che stai facendo. Stai semplicemente avendo il sovraccarico di istanziare un nuovo oggetto ogni volta.

Se per qualsiasi motivo devi utilizzare una nuova istanza di un oggetto, assicurati di eliminarlo quando hai finito.

    
risposta data 07.10.2011 - 00:08
fonte
4

Concettualmente, stai già chiamando una funzione statica, quindi la risposta facile è semplicemente andare avanti e codificarli in quel modo. Una risposta più difficile è che probabilmente hai un difetto di progettazione di base, tale che questo oggetto è o un "misc" che hai gettato un po 'di codice di sinistra in, o lo stai passando molto stato su ciascuna di quelle chiamate.

Mentre sono tutti in quell'oggetto, sono accoppiati e tu hai meno flessibilità nel refactoring del design. Se lo suddividete in sole funzioni, poi guardate insieme, quale stato stanno usando, ecc., Potete spostare quella funzionalità nel punto in cui appartiene, in uno o più oggetti con stato discreto, negli oggetti che sono chiamandoli (perché deve "prendere in prestito" il loro stato) o come oggetto singleton che aggrega lo stato.

A volte le funzioni sono semplicemente statiche, non hanno uno stato oltre alla parametrizzazione, quindi non hanno bisogno di essere parte di un oggetto. È ancora meglio lasciarli come funzioni piuttosto che essere legati insieme in un oggetto, perché man mano che il codice si evolve, sarà più facile migrarli.

    
risposta data 07.10.2011 - 06:34
fonte
2

Oltre a ciò che @AGC ha detto, se il doSomething () appartiene per dire, una classe cliente, allora non vuoi renderlo statico. In altre parole, le classi di business vengono raramente trasformate in classi statiche poiché i loro dati dovrebbero cambiare nell'ambito di una singola transazione e non si vuole tenerli in giro per tutto il tempo. Le classi di tipi statici sono utili per i dati di lunga durata e i metodi di utilità / aiuto. Se si utilizzano strumenti di test automatici, la statica può causare problemi: RIF1

    
risposta data 07.10.2011 - 00:30
fonte
1

Se sei davvero, davvero sicuro che DoSomething non avrà mai bisogno di implementazioni diverse a seconda del contesto (ad es. per il test), rendilo static , che ti dà una classe di utilità come java.lang.Math .

L'uso di un singleton è considerato sempre più una cattiva idea: se è possibile che tu abbia bisogno di diverse implementazioni in seguito, dovresti usare meglio schema di fabbrica : la fabbrica restituisce un'implementazione per un'interfaccia che definisce doSomething .

La soluzione migliore a mio parere è l'utilizzo di un quadro per l'integrazione delle dipendenze , che fa un passo avanti rispetto a una fabbrica eseguendo tutte le inizializzazioni in background. Per esempio. utilizzando Google Guice puoi scrivere qualcosa di simile

public interface DoIt {
   void doSomething(Blubb blubb);
}

class User {

  @Inject DoIt doit;  //injected by the DI framework

  public void process() {
     Blubb blubb = new Blubb();
     doit.doSomething(blubb);
  } 
}

Ovviamente devi avere un'implementazione di DoIt , e devi configurare i tuoi "binding" in background, ma il punto importante è che User non sa quale DoIt è stato usato o se è un singleton o no. È completamente disaccoppiato da tali dettagli di configurazione, che possono essere modificati senza toccare nulla in User .

    
risposta data 07.10.2011 - 11:07
fonte

Leggi altre domande sui tag