2010-07-14 2 views
5

이 클래스를 정적으로 설정해야합니까? 내가 근무 프로젝트에서

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

내가 이런 종류의 더 많은 클래스를 만드는 유지로

, 나는 어쩌면 내가 이런 종류의를해야 실현이처럼/업데이트 데이터베이스를 쿼리 클래스를 가지고 클래스 정적. 이렇게함으로써 명백한 이점은 데이터베이스 쿼리를 할 때마다 클래스 인스턴스를 만들지 않아도된다는 것입니다. 그러나 정적 클래스의 경우 하나의 클래스 복사본 만 있으므로 수백 개의 요청으로 정적 클래스의 복사본 하나만을 사용하게됩니까?

감사합니다,

답변

2

다릅니다. 프로그램을 멀티 스레드로 만들 필요가 있습니까? 둘 이상의 데이터베이스에 연결해야합니까? 이 수업에 주를 저장할 필요가 있습니까? 연결 수명을 제어해야합니까? 앞으로 데이터 캐싱이 필요합니까? 이들 중 하나에 예라고 답하면 정적 클래스는 일을 어색하게 만듭니다.

내 개인적인 조언은 더 많은 객체 지향 (OO)이되어 미래에 필요할 수도있는 유연성을 제공 할 수 있도록 인스턴스로 만드는 것입니다.

0

정적 클래스에 가면 당신이 그런는 주로 비 저장을하는 것이 설계해야합니다. 일반적인 전략은 일반적인 데이터 액세스 함수를 사용하여 기본 클래스를 만든 다음 고객을로드하는 등의 특정 클래스에서 파생 클래스를 파생시키는 것입니다.

개체 생성이 실제로 전체 작업의 오버 헤드 인 경우 미리 만든 개체를 풀링 할 수도 있습니다. 그러나, 나는 이것이 매우 의심 스럽다.

일반적인 데이터 액세스 코드를 정적 메서드로 만들 수 있지만 모든 데이터 액세스에 대한 정적 클래스는 디자인이 어딘가에 손실 된 것처럼 보일 수 있습니다.

정적 클래스는 멀티 스레드 액세스에 별다른 문제가 없지만 잠금은 물론 고정 또는 공유 상태에 문제가있는 것은 분명합니다.

1

이 클래스를 정적으로 만들 때주의해야합니다. 웹 응용 프로그램에서 각 요청은 자체 스레드에서 처리됩니다. 주의하지 않으면 정적 유틸리티는 스레드가 안전하지 않을 수 있습니다. 그런 일이 생기면 행복하지 않을 것입니다.

DAO 패턴을 따르는 것이 좋습니다. 이 도구를 사용하면 쉽게 사용할 수 있습니다. 데이터 소스를 구성하기 만하면 DB 액세스와 트랜잭션이 간편해집니다.

12

나는 그 클래스를 정적으로 만들지 않고 대신 의존성 주입을 사용하고 해당 클래스에 필요한 리소스를 넘겨 준다.. 이렇게하면 테스트 할 모의 저장소 (IRepository 인터페이스를 구현)를 만들 수 있습니다. 클래스를 정적으로 만들고 저장소에 전달하지 않으면 정적 클래스가 연결되는 대상을 제어 할 수 없으므로 테스트하기가 매우 어렵습니다.

참고 : 아래 코드는 개략적 인 예이며 반드시 전달해야하며 컴파일 및 실행하지 않아도됩니다.

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

는 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(); 

나는 의존성 주입에 대해에 산책하고 싶지 않았다. Misko Hevery's bloggreat post to get started과 함께 매우 상세하게 들어갑니다.

+0

감사합니다 brainimus. 나는 당신의 모범과 비슷한 것을 가지고 있습니다. 내가 준 샘플 코드는 내 수업의 슈퍼 스트립 버전입니다. 예, 저장소 패턴도 좋습니다. 또한, 저는 DI 컨테이너에 CastleWindsor를 사용합니다. – sean717

0

클래스를 정적으로 만들면 어려움을 겪을 수 있습니다. 은 아마도 클래스 내부에서 읽음으로써 명확하지 않은 방식으로 연결 문자열 읽기를 내부적으로 관리해야 할 것입니다 구성 파일에서 가져 오거나 이러한 상수를 관리하는 일부 클래스에서 요청할 수 있습니다. 즉 이제 즉, 클래스

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

을 의미가 있다면 차라리, 전통적인 방법

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

다음 글로벌/공공 정적 변수에 할당에서 이러한 클래스의 인스턴스 거라고 모든 클래스의 종속성이 생성자를 통해 전달되기 때문에 단위 테스트에 유연성을 희생하지 않습니다.

관련 문제