Uso di metodi statici per implementare la logica all'interno di una classe

2

Recentemente ho preso uno strano comportamento nella mia codifica: ad un certo punto nell'ultimo anno ho iniziato a creare metodi protected static per implementare la logica dei miei metodi public , assicurandoti che la versione protected static contenga tutti della logica, ma non è influenzato dallo stato.

per es.

class Demo
{
    string someAttribute;
    public Demo(string someAttribute)
    {
        this.someAttribute = someAttribute;
    }

    // public method only calls the static method, passing all 
    // parameters sent to the public function as well as any 
    // of the object's attributes required by the function.
    public string AppendSomeAttribute(string textToAppendTo) =>
        AppendSomeAttribute(textToAppendTo, someAttribute);

    // static method is not publicly exposed.  It contains all 
    // of the function's logic, but is not affected by state
    protected static string AppendSomeAttribute(string textToAppendTo, string someAttribute) =>
        string.Concat(textToAppendTo, someAttribute);

    /*
    // this is what a normal person would do:
    public string AppendSomeAttribute(string textToAppendTo) =>
        string.Concat(textToAppendTo, someAttribute);
    */
}

Non ricordo di aver letto nulla che avrebbe innescato questo cambiamento. La mia ipotesi migliore è che leggo qualcosa che lo consiglia e che è bloccato nel mio subconscio; ma potrebbe essere solo una cattiva abitudine che avevo inconsciamente raccolto.

Cercando di capire perché questo può essere consigliato ho trovato il seguente:

  • Tutta la logica viene gestita in un unico luogo; quindi, dove ci sono più metodi pubblici che adottano parametri diversi, questo aiuta a mantenere tutta la logica in una routine (ha sicuramente senso dove la versione di quella routine che fornisce tutti i parametri non dovrebbe essere esposta pubblicamente, altrimenti non ne vedo alcun beneficio).
  • Rimuovendo lo stato dell'oggetto dall'equazione, la logica di questi metodi è più facilmente testata / provata; sia per unit test, sia quando copia il codice di incollamento su LinqPad (o simile) per provarlo in una sandbox.

Tuttavia, queste non sono grandi giustificazioni per fare ciò come uno stile di codifica de facto (cioè dove non esiste uno scenario specifico per giustificare questo, come i molti sovraccarichi pubblici dello stesso metodo con nessuno che prende tutti i parametri esempio, come descritto sopra).

Domanda:

C'è un chiaro vantaggio nella scrittura del codice in questo modo?

    
posta JohnLBevan 19.04.2018 - 14:41
fonte

4 risposte

2

Questo sarebbe OK, purché tu abbia dei discendenti che condividono in modo significativo quella logica.

La cosa protetta è che invia un messaggio, aumenta le aspettative. E troppo spesso, dopo aver scavato, non trovo discendenti che usano quei membri protetti e sembra che fosse solo una questione di "nel caso in cui avrò bisogno di accedervi più tardi da un ipotetico futuro discendente" (che non ha mai visto la luce del giorno). Questo non va bene.

Qualsiasi utilizzo di protected dovrebbe adattarsi al modello di ereditarietà nel senso che rappresenta chiaramente una logica comune per tutte le classi di bambini. Quindi ha senso e aiuta il lettore a capire l'applicazione.

    
risposta data 19.04.2018 - 22:16
fonte
3
I metodi

protected static sono una cosa strana da creare. Sospetto che tu voglia creare metodi private static . Essendo protected , il tuo commento " static method is not publicly exposed " non è corretto al 100%. Si può accedere tramite classe figlio come mostrato di seguito:

using System;

public class Program
{
    static void Main()
    {
        var x = new Demo2();
        Console.WriteLine(x.AppendSomeAttribute("We hacked it. ")); 
        // Prints "We hacked it. lol" 
    }
}

class Demo
{
    private string _someAttribute;
    public Demo(string someAttribute) => _someAttribute = someAttribute;

    public string AppendSomeAttribute(string textToAppendTo) =>
        AppendSomeAttribute(textToAppendTo, _someAttribute);

    protected static string AppendSomeAttribute(string txtToAppendTo, string someAttrbute) =>
        string.Concat(txtToAppendTo, someAttrbute);
}

class Demo2 : Demo
{
    public Demo2() : base("lol") {}

    public static string LetsHack(string textToAppendTo, string someAttribute) =>
        AppendSomeAttribute(textToAppendTo, someAttribute);
}

Si può vedere in azione, qui .

I metodi di supporto privati sono uno schema comune. Anche contrassegnarli come statici quando non accedono allo stato dell'oggetto è un modello comune. protected static è semplicemente strano e sono sicuro che questa è la prima volta che vedo qualcuno che la usa.

    
risposta data 19.04.2018 - 17:04
fonte
1

Questa è una pratica comune quando si scrivono classi sicure multi-thread, anche se normalmente eviterei l'ereditarietà il più possibile in tale classe. Se il metodo statico è completamente puro (privo di effetti collaterali), può essere richiamato dall'esterno dei blocchi mutex protetti, il che è un grande vantaggio quando si tenta di evitare i blocchi annidati.

    
risposta data 20.04.2018 - 03:38
fonte
1

Il caso d'uso principale (secondo la tua spiegazione) è di evitare l'uso di valori di istanza. Ma non vedo alcun motivo per mantenere il metodo come statico dopo che è stato sviluppato.

  1. Sviluppa un metodo (non statico)
  2. Inseriscilo in static per vedere se nel corpo del metodo compaiono errori, il che indica che stai utilizzando i valori di istanza.
  3. Rimuovi static .

Sono tutto per i metodi intelligenti per il factcheck di qualcosa, ma non vedo alcun motivo per mantenere il tuo approccio intelligente ma insolito dopo aver confermato ciò che volevi.

Come argomento secondario, se già non riesci a tenere traccia dei valori usati in un metodo, probabilmente il metodo sta gestendo troppo per cominciare.

By removing the object's state from the equation the logic of these methods is more easily tested / proven; either by unit tests,

Non sto seguendo abbastanza qui. I metodi statici (da soli) sono notoriamente difficili da testare in quanto non è facile prendere in giro uno stato.

Una statica avvolta in una non-statica non è diversa da una configurazione non statica completa; in termini di test unitario.

All logic is handled in a single place; so where there are multiple public methods taking different parameters this helps keep all logic in one routine (definitely makes sense where the version of that routine which supplies all parameters is not supposed to be publicly exposed; otherwise I can't see a benefit).

Questo è un argomento per pubblico / protetto / privato, non statico / istanza. È possibile ottenere lo stesso identico obiettivo con metodi di istanze private / protette.

Semplicemente non vedo il punto del tuo codice. Nulla cambia se rimuovi la parola chiave static dal tuo esempio.

Nei tuoi commenti sul codice, dici che [protected] static method is not publicly exposed , che è un falso nome. non è esposto pubblicamente perché è protetto , indipendentemente dal fatto che sia statico o meno.

Se stai parlando di come un metodo static non è esposto su un'istanza; questo è parzialmente vero Ma questo è un argomento su evitare l'errore dello sviluppatore , non sulla correttezza logica.
Inoltre: una statica protetta è ancora disponibile pubblicamente all'interno della sua classe e tutte le classi che ne derivano. Non è disponibile come this.MyStaticMethod() , ma è ancora disponibile come MyStaticMethod() . Non stai completamente aggirando la sua disponibilità.

Ciò che dici non è sbagliato, ma non vedo argomenti che giustifichino questo ulteriore livello di astrazione.

    
risposta data 20.04.2018 - 13:12
fonte

Leggi altre domande sui tag