Devo utilizzare le classi statiche per i metodi che eseguiranno attività comuni e verranno richiamati tramite la mia applicazione?

6

Ho passato le ultime ore a leggere sull'uso delle classi static e ho cercato di capire se dovevo usarle o meno, ma non sono ancora arrivato a nessuna conclusione. Sembra che l'argomento potrebbe andare in entrambi i modi. Nella mia applicazione ho creato quelle che chiamo "classi helper" che contengono metodi che svolgeranno compiti molto comuni per me e verrebbero richiamati attraverso la mia applicazione ( ASP.Net MVC Web App usando C# ) e la semplice domanda è, dovrebbe sono davvero statici o no?

Ecco un esempio di uno dei miei aiutanti.

public static class ActiveDirectoryHelper
{
    public static PrincipalContext GetPrincipalContext(string ouName)
    {
        var fullOUName = string.Concat("OU=", ouName,",DC=");

        return new PrincipalContext(ContextType.Domain, "", fullOUName, ConfigurationManager.AppSettings["ServiceAccountUser"], ConfigurationManager.AppSettings["ServiceAccountPassword"]);
    }

    public static PrincipalSearcher GetAllUsersInOU(string ouName)
    {
        var principalContext = GetPrincipalContext(ouName);
        var userPrincipal = new UserPrincipal(principalContext);
        return new PrincipalSearcher(userPrincipal);
    }

    public static UserPrincipal GetUserPrincipal(string userName, string ouName)
    {
        var principalContext = GetPrincipalContext(ouName);
        return UserPrincipal.FindByIdentity(principalContext, userName);
    }
}
    
posta Matthew 01.06.2016 - 21:56
fonte

7 risposte

3

Penso che le classi statiche siano carine in molti casi. Potrei semplicemente dire "usali quando è utile" ma non è molto utile.

La mia regola generale è (come sempre): sto nascondendo eventuali dipendenze? Se ritieni che una "classe di supporto" sia utile (anche se fai attenzione alla bassa coesione), allora con tutti i mezzi, vai avanti. Assicurati solo che i tuoi metodi non accedano allo stato globale però. I metodi statici puri sono adorabili. I metodi statici che dipendono da alcuni globali o che aprono connessioni DB o letti dal disco / alcuni file di configurazione fanno tic tac delle bombe a orologeria.

Rendono davvero difficile testare l'applicazione (l'unico modo per farlo sarà eseguire manualmente l'intero sistema, o con i test fragili del sistema completo, non otterrai granularità). Inoltre, rendono impossibile lo scambio di implementazioni.

Ricorda solo il principio di inversione di dipendenza e il principio di apertura / chiusura! Assicurati che le tue lezioni siano inseribili. Assicurati che non tirino fuori la roba dal nulla. Se lo fai, allora vai avanti e realizza tutti i metodi statici che vuoi!

    
risposta data 02.06.2016 - 09:09
fonte
2

Sembra che tu stia nascondendo una dipendenza esterna ad Active Directory usando questa classe statica. Un problema qui è che se stai provando a testare la classe che chiama questi metodi, non puoi falsificare le chiamate statiche. Quindi inibisci immediatamente la testabilità del tuo codice. Lo rifatterei su un'interfaccia, qualcosa come IProvideActiveDirectoryInformation e la classe concreta, ActiveDirectoryInformationProvider. Quindi passare l'interfaccia nel costruttore del controller. Ciò ti consentirà di cablare la classe di calcestruzzo con un contenitore DI. Permetterà inoltre di falsificare ActiveDirectoryInformationProvider e restituire quello che vuoi per i metodi di interfaccia.

Cercherò anche di non passare indietro cose come l'oggetto PrincipalSearcher nell'interfaccia. Se il tuo metodo è GetAllUsersInOU () mi aspetterei un elenco di utenti o nomi utente.

    
risposta data 02.06.2016 - 19:27
fonte
1

Una classe dovrebbe essere statica se esiste solo come concetto astratto nella tua applicazione.

Ad esempio, supponi di creare un clone di Twitter. Potresti avere 2 tipi di tweet, tweet dell'utente e annunci. Entrambi condividono un comportamento comune ma sono diversi. Quindi, vuoi usare il polimorfismo e una fabbrica per crearne uno o l'altro.

Queste due classi di tweet dovrebbero essere classi concrete, in quanto entità reali. Il tuo dominio è definito da queste classi.

La fabbrica dovrebbe essere statica perché esiste solo a livello astratto per rendere l'applicazione progettata in modo migliore e per aiutarti a riutilizzare il codice che creerà un tipo di tweet. Il tuo dominio non è definito a nessun livello da questo stabilimento.

Quindi, se non pensi che una classe debba mai essere istanziata ma non ha bisogno di essere estesa per essere usata, probabilmente è un buon segno che dovrebbe essere statica.

    
risposta data 02.06.2016 - 08:54
fonte
1

Una delle cose suggerite in Programmazione orientata agli oggetti è errata (il titolo è quello di attirare la tua attenzione, e il contenuto è contestato ma divertente) è che le classi *Handler , *Manager e *Doer in generale sono un odore di codice che indica qualcuno che cerca di forzare l'orientamento dell'oggetto su un problema che è più adatto per un'implementazione procedurale. p>

In C # puoi usare le classi statiche come spazi dei nomi dei moduli per le procedure e preferibilmente chiamarle come tali. Penso che questo sia il modo di farlo, ma non nel tuo caso particolare.

Le applicazioni della tua particolare implementazione avranno dipendenze comportamentali dello stato globale (diciamo le autorizzazioni di un particolare utente), e come tali dovrebbero essere una dipendenza iniettata in modo che il codice che utilizza questo possa essere testato in isolamento.

    
risposta data 02.06.2016 - 09:53
fonte
0

Potrei mancare qualcosa, ma a mio avviso la risposta si riduce ai metodi e alle variabili dei membri.

Se questi sono tutti statici, la classe stessa può (e dovrebbe essere) resa statica. In caso contrario, non è una classe statica.

NB. non c'è nulla che impone alla classe di essere statico anche se i metodi e le variabili sono tutti statici.

    
risposta data 02.06.2016 - 11:56
fonte
0

Considera il linguaggio di programmazione che stai usando (C #) come un insieme di strumenti.

Non ci sono regole, no "dovrebbe" o "should not".

Guarda cosa sta facendo il lavoro e scegli lo strumento migliore per il lavoro.

Se hai bisogno di una raccolta di metodi globale disponibile, la stessa per tutti i thread, le classi statiche sono un buon strumento. Se si desidera memorizzare i dati all'interno della classe (diversi per ogni thread), probabilmente non lo sono.

    
risposta data 02.06.2016 - 14:18
fonte
0

Non c'è niente di sbagliato nella tua classe di Helper. Devo confessare che uso questo tipo di Util , Helpers o Titolari per rendere accessibili determinate risorse / logica da luoghi diversi.

Tuttavia un architetto della mia azienda mi dice ripetutamente che queste classi spesso raccolgono codice che non so dove collocare. Inoltre non gli piace perché potresti portare componenti da livelli in cui i livelli superiore / inferiore non dovrebbero avere accesso e svolgono compiti fuori dalle loro responsabilità. Porta anche alcuni problemi al momento del test.

Non mi dispiace. Io lo uso e lo uso abbastanza bene come penso che dovrebbe essere usato. E funziona bene. Quindi non ti preoccupare.

È vero che al momento dei test unitari ti sarà difficile prendersene in giro. Ma ci vorrà ancora un po 'di tempo per farlo. Ci sono librerie che attraversano questo problema.

Un altro approccio potrebbe impedirti di questo tipo di carenze (durante i test). Per esempio, il modello di Singleton. Iniezione dell'istanza come dipendenza del componente e conversione dei metodi in metodi di istanza.

Comunque, per ora vedo, le tue soluzioni mi stanno bene.

    
risposta data 03.06.2016 - 19:51
fonte

Leggi altre domande sui tag