2010-07-14 13 views
5

Nei progetti cui ho lavorato mi hanno classi che query di database/aggiornamento, come questo,dovrei rendere statica questa classe?

public class CompanyInfoManager 
{ 
    public List<string> GetCompanyNames() 
    { 
     //Query database and return list of company names 
    } 
} 

come ho continuare a creare sempre più classi di questo tipo, mi rendo conto che forse avrei dovuto fare questo tipo di classe statico. Facendo così, l'ovvio beneficio è evitare la necessità di creare istanze di classe ogni volta che ho bisogno di interrogare il database. Ma dato che per la classe statica, c'è solo una copia della classe, questo si tradurrà in centinaia di richieste che contendono solo una copia della classe statica?

Grazie,

risposta

2

Dipende. Avrai mai bisogno di rendere il tuo programma multithreaded? Avrai mai bisogno di collegarti a più di un database? Avrai mai bisogno di memorizzare lo stato in questa classe? Hai bisogno di controllare la durata delle tue connessioni? Avrai bisogno di caching dei dati in futuro? Se rispondi sì a qualcuno di questi, una classe statica renderà le cose difficili.

Il mio consiglio personale sarebbe quello di renderlo un caso come questo è più OO e darebbe la flessibilità che potrebbe essere necessario in futuro.

0

Se si va per una classe statica si dovrà progettare tale che la sua gran parte apolidi. La solita tattica consiste nel creare una classe base con funzioni di accesso ai dati comuni e quindi ricavarle in classi specifiche, ad esempio per caricare i clienti.

Se la creazione di oggetti è in realtà la testa in tutta l'operazione, allora si potrebbe anche guardare mettere in comune gli oggetti creati in precedenza. Tuttavia, dubito fortemente che questo sia il caso.

potreste scoprire che un sacco di codice di accesso ai dati comune potrebbe essere trasformato in metodi statici, ma una classe statica per tutti l'accesso ai dati sembra che il design è persa da qualche parte.

classi statiche non hanno problemi con accesso multi-filettato per-sé, ma ovviamente serrature e stato statico o condiviso è problematico.

1

bisogna essere attenti rendere questa classe statica. In un'app Web, ogni richiesta viene gestita sul proprio thread. Le utilità statiche possono essere poco sicure se non si presta attenzione. E se ciò accade non sarai felice.

Mi raccomando di seguire il modello DAO. Usa uno strumento come Spring per renderlo più facile per te. Tutto quello che devi fare è configurare un'origine dati e l'accesso al DB e le transazioni saranno un gioco da ragazzi.

12

Non vorrei rendere quella classe statica, ma invece utilizzerei l'iniezione di dipendenza e passare le risorse necessarie a quella classe. In questo modo è possibile creare un repository fittizio (che implementa l'interfaccia IRepository) con cui testare. Se rendi la classe statica e non passi nel tuo repository, allora è molto difficile testare dato che non puoi controllare a cosa sta collegando la classe statica.

Nota: il codice riportato di seguito è un esempio approssimativo e serve esclusivamente a trasmettere il punto, non necessariamente compilare ed eseguire.

public interface IRepository 
{ 
    public DataSet ExecuteQuery(string aQuery); 
    //Other methods to interact with the DB (such as update or insert) are defined here. 
} 

public class CompanyInfoManager 
{ 
    private IRepository theRepository; 
    public CompanyInfoManager(IRepository aRepository) 
    { 
     //A repository is required so that we always know what 
     //we are talking to. 
     theRepository = aRepository; 
    } 

    public List<string> GetCompanyNames() 
    { 
     //Query database and return list of company names 
     string query = "SELECT * FROM COMPANIES"; 
     DataSet results = theRepository.ExecuteQuery(query); 
     //Process the results... 
     return listOfNames; 
    } 
} 

Per testare CompanyInfoManager:

//Class to test CompanyInfoManager 
public class MockRepository : IRepository 
{ 
    //This method will always return a known value. 
    public DataSet ExecuteQuery(string aQuery) 
    { 
     DataSet returnResults = new DataSet(); 
     //Fill the data set with known values... 
     return returnResults; 
    } 
} 

//This will always contain known values that you can test. 
IList<string> names = new CompanyInfoManager(new MockRepository()).GetCompanyNames(); 

non ho voglia di divagare su iniezione di dipendenza. Misko Hevery's blog entra nei dettagli con uno great post to get started.

+0

Grazie brainimus. Ho qualcosa di molto simile al tuo esempio. Il codice di esempio che ho dato è una versione super ridotta della mia classe. Sì, mi piace anche lo schema del repository. Inoltre, utilizzo CastleWindsor per il mio contenitore DI. – sean717

0

Rendendo statica la classe, si sarebbe in grado di testare l'unità in modo difficile, poiché in tal caso si dovrebbe probabilmente gestire internamente la lettura della stringa di connessione in modo non chiaro, sia leggendola all'interno della classe che la . da un file di configurazione o richiedendolo da una classe che gestisce queste costanti. Preferirei un'istanza di una classe in modo tradizionale

var manager = new CompanyInfoManager(string connectionString /*...and possible other dependencies too*/) 

e poi assegnarlo ad una variabile statica/pubblica globale, se questo ha un senso per la classe, vale a dire

//this can be accessed globally 
public static CompanyInfoManager = manager; 

così ora si non sacrificherebbe alcuna flessibilità per i vostri test unitari, dal momento che tutte le dipendenze della classe vengono passate attraverso il suo costruttore

Problemi correlati