2010-07-14 11 views
5

En los proyectos en los que trabajé me tienen clases que consultan la base de datos/actualización, como éste,¿Debo hacer esta clase estática?

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

y cuando siga creando más y más clases de este tipo, que dan cuenta de que tal vez debería hacer este tipo de clase estática. Al hacerlo, el beneficio obvio es evitar la necesidad de crear instancias de clase cada vez que necesite consultar la base de datos. Pero dado que para la clase estática, solo hay una copia de la clase, ¿dará como resultado que cientos de solicitudes contengan solo una copia de clase estática?

Gracias,

Respuesta

2

Depende. ¿Alguna vez necesitará hacer que su programa sea multiproceso? ¿Alguna vez necesitará conectarse a más de una base de datos? ¿Alguna vez necesitará almacenar estado en esta clase? ¿Necesita controlar la vida útil de sus conexiones? ¿Necesitarás almacenamiento en caché de datos en el futuro? Si respondes que sí a cualquiera de estos, una clase estática hará que las cosas sean incómodas.

Mi consejo personal sería convertirlo en una instancia ya que es más OO y le daría la flexibilidad que pueda necesitar en el futuro.

0

Si usted va para una clase estática que tendrá que diseñarlo de manera que su gran medida sin estado. La táctica habitual es crear una clase base con funciones de acceso a datos comunes y luego derivarlas en clases específicas para, por ejemplo, cargar Clientes.

Si la creación de objetos es en realidad la sobrecarga de toda la operación, también podría considerar la agrupación de objetos pre-creados. Sin embargo, dudo mucho que este sea el caso.

Es posible que muchos de sus códigos de acceso a datos comunes se puedan convertir en métodos estáticos, pero una clase estática para todos los datos de acceso parece que el diseño se pierde en alguna parte.

Las clases estáticas no tienen ningún problema con el acceso multiproceso per-se, pero obviamente los bloqueos y el estado estático o compartido es problemático.

1

Tienes que tener cuidado haciendo que esta clase sea estática. En una aplicación web, cada solicitud se maneja en su propio hilo. Las utilidades estáticas pueden ser inseguras si no tienes cuidado. Y si eso sucede, no serás feliz.

Recomiendo encarecidamente que siga el patrón DAO. Use una herramienta como Spring para que esto sea más fácil para usted. Todo lo que tiene que hacer es configurar un origen de datos y su acceso a DB y las transacciones serán simples.

12

No convertiría esa clase en estática, pero en cambio usaría la inyección de dependencia y pasaría los recursos necesarios a esa clase. De esta forma, puede crear un repositorio simulado (que implementa la interfaz IRepository) para probar. Si hace que la clase sea estática y no pase en su repositorio, entonces es muy difícil de probar ya que no puede controlar a qué se está conectando la clase estática.

Nota: El siguiente código es un ejemplo aproximado y solo pretende transmitir el punto, no necesariamente compilar y ejecutar.

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; 
    } 
} 

Para probar 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(); 

yo no quiero divagar sobre la inyección de dependencia. Misko Hevery's blog entra en gran detalle con un great post to get started.

+0

Gracias brainimus. Tengo algo muy similar a tu ejemplo. El código de muestra que di es una versión muy depurada de mi clase. Sí, también me gusta el patrón Repository. Además, uso CastleWindsor para mi DI Container. – sean717

0

Al hacer la clase estática, tendría una unidad de tiempo difícil probándola, ya que entonces probablemente tendría que gestionar internamente la lectura de la cadena de conexión de una manera no clara, ya sea leyéndola dentro de la clase desde un archivo de configuración o solicitándolo desde alguna clase que gestione estas constantes. Prefiero crear una instancia de una clase así de una manera tradicional

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

y después asignarlo a una variable estática/pública mundial, si eso tiene sentido para la clase, es decir

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

por lo que ahora no sacrificaría ninguna flexibilidad para las pruebas de su unidad, ya que todas las dependencias de la clase se pasan a través de su constructor

Cuestiones relacionadas