Non usare "Statico" in C #?

104

Ho presentato un'applicazione che ho scritto ad altri architetti per la revisione del codice. Uno di questi mi ha quasi immediatamente scritto e ha detto "Non usare" statico. "Non puoi scrivere test automatici con classi e metodi statici." Statico "deve essere evitato."

Ho controllato e completamente 1/4 delle mie classi sono contrassegnate come "statiche". Uso static quando non creerò un'istanza di una classe perché la classe è una singola classe globale utilizzata in tutto il codice.

Ha proseguito menzionando qualcosa che implica tecniche di derisione, IOC / DI che non possono essere usate con il codice statico. Dice che è spiacevole quando le librerie di terze parti sono statiche a causa della loro non testabilità.

Questo altro architetto è corretto?

aggiornamento: ecco un esempio:

APIManager - questa classe mantiene i dizionari delle API di terze parti che sto chiamando insieme al prossimo tempo consentito. Mette in atto i limiti di utilizzo dell'API che molte terze parti hanno nei loro termini di servizio. Lo uso ovunque io chiami un servizio di terze parti chiamando Thread.Sleep (APIManager.GetWait ("ProviderXYZ")); prima di effettuare la chiamata. Tutto qui è thread-safe e funziona alla grande con TPL in C #.

    
posta Infin8Loop 13.08.2012 - 23:53
fonte

10 risposte

115

Dipende dal fatto che le classi statiche mantengano o meno lo stato. Personalmente, non ho alcun problema con le funzioni stateless messe insieme in una classe statica.

    
risposta data 13.08.2012 - 23:57
fonte
90

È troppo generico al riguardo. Ha ragione, ostacola i test. Tuttavia, le classi e i metodi static hanno la loro posizione e dipendono davvero dal contesto. Senza esempi di codice che non puoi davvero dire.

I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.

Questo può essere un strong odore di codice. Per cosa stai usando le classi? Per contenere i dati? Per accedere a un database? Quindi ha ragione. In questo caso dovresti cercare di inserire l'iniezione delle dipendenze, in quanto una classe statica è effettivamente un singleton implicito.

Se li stai utilizzando per i metodi di estensione o gli helper che non cambiano lo stato e funzionano solo sui parametri forniti, quelli di solito vanno bene.

    
risposta data 13.08.2012 - 23:56
fonte
27

I checked and fully 1/4 of my classes are marked "static". I use static when I am not going to create an instance of a class because the class is a single global class used throughout the code.

La cosa migliore da fare è provare e testare il codice unitamente. Prova a progettare test che siano ripetibili, indipendenti, semplici e testare un solo metodo alla volta. Prova a eseguire i test in ordine casuale diverso. Puoi ottenere una build "verde" stabile?

Se sì, è un punto valido per difendere il tuo codice. Se, tuttavia, hai difficoltà, forse dovresti usare i metodi basati sull'istanza.

    
risposta data 14.08.2012 - 00:20
fonte
10

Uno dei vantaggi che si ottiene da IoC / DI è che la maggior parte delle interazioni tra le classi sono negoziate tra le interfacce. Ciò semplifica i test di unità, poiché le interfacce possono essere prese in giro automaticamente o in modo semi-automatico e quindi ciascuna delle parti può essere testata per ingressi e uscite. Inoltre, oltre alla testabilità, mettere le interfacce tra tutto ti permette di avere il codice più modulare possibile - puoi facilmente sostituire un'implementazione senza troppa preoccupazione che stai rovinando le dipendenze.

Poiché C # non ha metaclassi, una classe non può implementare un'interfaccia usando le caratteristiche statiche, quindi le caratteristiche statiche delle classi terminano qualsiasi tentativo di implementare un modello di oggetti IoC / DI puro. Vale a dire, non è possibile creare una simulazione per metterli alla prova e creare dipendenze reali.

Se la tua azienda / progetto è investito molto nel fare IoC, questo è ovviamente un problema ragionevole, e il dolore che stai attraversando è per il guadagno di tutti. Da un punto di vista architettonico, tuttavia, personalmente non penso che nessun modello debba essere seguito alla tomba. Ci sono alcune cose che hanno senso implementare usando metodi statici - la strategia di progettazione singleton, per esempio. Sono meno incline alle classi statiche perché penso che tendano a perdere i vantaggi di OO, ma ci sono momenti in cui una classe di librerie è probabilmente un'espressione più naturale di qualcosa rispetto a un motore.

Il commentatore mi ricorda i metodi di estensione, che ovviamente devono essere in classi statiche in C #. Questo è legittimo ed è un esempio di come il puro IoC non funzioni molto bene in C #, almeno se stai cercando di sfruttare l'ampiezza della lingua.

    
risposta data 14.08.2012 - 00:06
fonte
10

Le risposte già pubblicate coprono molti punti davvero buoni, ma ce n'è una che sembra mancare:

I campi statici sono mai garbage collection.

Questo è molto importante se hai un'app con molti vincoli di memoria, e questo schema può essere molto comune quando le persone cercano di implementare una cache.

Le funzioni statiche non sono così male, ma tutti gli altri lo hanno già descritto abbastanza dettagliatamente.

    
risposta data 17.08.2012 - 05:13
fonte
5

Talvolta le classi statiche sono utilizzate in modo improprio e dovrebbero essere:

  • a singleton (dove la classe non statica ha un membro statico e una variabile di istanza statica pubblica per recuperarla / crearlo una sola volta.
  • un metodo in un'altra classe (dove lo stato è importante). Se hai un membro che non usa dati da quella classe, probabilmente non dovrebbe far parte di quella classe.

Potrebbe anche essere una cosiddetta funzione "utility" e parte di una classe di utilità. Le classi di utilità sono classi che contengono solo metodi statici e fungono da funzioni di supporto senza alcun contesto.

    
risposta data 14.08.2012 - 02:35
fonte
4

I metodi statici vanno bene e hanno un posto legittimo nella programmazione. Sembra che il tuo architetto abbia un framework di testing che non supporta completamente i metodi statici. Se il tuo codice fa parte di un progetto più grande, è importante soddisfare le linee guida degli architetti. Tuttavia, non lasciare che questo progetto ti impedisca di utilizzare metodi statici quando è opportuno farlo.

    
risposta data 02.05.2014 - 19:35
fonte
1

Ho usato le proprietà statiche per cose comuni a tutte le istanze di una classe. E ho usato metodi statici per ottenere gruppi di oggetti di classe. Non sono affatto un esperto ma questo ha funzionato per me finora.

Esempio PHP:

class vendorData {
  private static $data_table = 'vendor_data'; // static property
  private $id; // instance property
  private $name; // instance property

  public function __construct($vendor_id) {
    if(!self::validId($vendor_id) ) { // static method
      return false; // id doesn't exist
    }
    $this->id = $vendor_id; // id has been validated
    $this->getProperties(); // object method
  }

  private static function validId($vendor_id) {
    // send db query to find if the id exists
    // return true/false;
  }

  private function getProperties() { // object method
    $sql = "SELECT * FROM '{self::$data_table}' // using static property
        WHERE 'id' = {$this->id}"; // using object instance property
    // get resultset
    foreach($result as $property => $value) {
      $this->$property = $value; // object instance properties all set
    }
  }

  // and here
  public static function getBy($property,$value) { // static method to return object array
    $sql = "SELECT 'id' FROM '{self::$data_table}' // using static property
      WHERE '$property' = '$value'";
    // send query, get $ids array
    $obj_array = array();
    foreach($ids as $id) {
      // create array of current class objects using special static keyword
      // meaning of static here is different than in property/method declarations
      $obj_array[$id] = new static($id);
    }
    return $obj_array;
  }
}
    
risposta data 14.08.2012 - 05:24
fonte
1

Dirò che i principi che hanno sono ok ma l'affermazione (non usare la statistica) potrebbe essere sbagliata. Quanto costa il tuo codice? se il numero è alto e sei a tuo agio con il test dell'unità della tua app, allora stai bene. In caso contrario, suggerirei di rivedere il codice. Puoi trovare che le classi statiche sono la ragione o no, dipenderà da molte cose.

    
risposta data 14.08.2012 - 06:13
fonte
-3

Le classi con metodi statici abusano dei principi dell'OOP. Non è già un OOP, è una programmazione orientata alla classe COP.

Raramente hanno una "personalità" chiara (io uso il mio preferito metafora umana qui) o identità. Quindi non sanno chi sono. Questo punto è sufficiente per eliminare questo concetto in OOP, ma ce ne sono altri.

Il prossimo è una conseguenza del primo punto. Dal momento che tali classi non sanno chi sono, tendono a essere grandi o enormi.

Il terzo rende il tuo codice assolutamente non gestibile. L'uso dei metodi statici introduce dipendenze nascoste . Si aprono dappertutto, e non sai mai cosa succede nella tua classe. Non puoi esserne certo solo osservando la firma del costruttore.

Lentamente, ma inevitabilmente, il tuo codice sta diventando sempre meno coeso, dal momento che le dipendenze nascoste sono scarsamente controllate. Sembrano invisibili. Ed è così facile aggiungerne un altro! Non è necessario modificare la firma di alcun metodo. Tutto quello che devi fare è chiamare un metodo statico. E che brutto codice segue ...

Ok, probabilmente lo hai già indovinato. L'accoppiamento stretto è un frequente operatore di bassa coesione. Se ci sono molti clienti che usano una classe, l'accoppiamento diventa più stretto. E c'è una grande seduzione nell'usare una classe o un metodo già scritto che richiede solo una piccola correzione. Solo un parametro flag di metodo.

Che cosa usare al posto dei metodi statici? Bene, il mio suggerimento è OOP. Perché non provarlo?

    
risposta data 19.10.2017 - 14:16
fonte

Leggi altre domande sui tag