단일 책임 원칙은 여기에 당신의 가장 친한 친구입니다.
우선 AllFromCache ()를 리포지토리 클래스로 이동하고 GetAll ()이라고합니다. 캐시에서 검색한다는 것은 리포지토리의 구현 세부 사항이며 호출 코드로 알 수 없습니다.
이를 통해 필터링 클래스를 쉽고 편리하게 테스트 할 수 있습니다. 더 이상 어디에서 왔는지 신경 쓰지 않습니다.
둘째, 데이터베이스에서 데이터를 가져 오는 클래스를 캐싱 래퍼로 래핑합니다.
AOP 는이를위한 좋은 기술입니다. 그것은 아주 잘하는 몇 가지 중 하나입니다.
PostSharp 와 같은 도구를 사용하면 선택한 속성으로 표시된 메소드가 캐시되도록 설정할 수 있습니다. 그러나 이것이 캐싱하는 유일한 방법 인 경우 AOP 프레임 워크를 가질 필요가 없습니다. 동일한 인터페이스를 사용하는 리포지토리와 캐싱 래퍼 만 있으면이를 호출 클래스에 주입 할 수 있습니다.
예.
public class ProductManager
{
private IProductRepository ProductRepository { get; set; }
public ProductManager
{
ProductRepository = productRepository;
}
Product FetchById(guid id) { ... }
IList<Product> FilterByPropertry(int property) { ... }
}
public interface IProductRepository
{
IList<Product> GetAll();
}
public class SqlProductRepository : IProductRepository
{
public IList<Product> GetAll()
{
// DB Connection, fetch
}
}
public class CachedProductRepository : IProductRepository
{
private IProductRepository ProductRepository { get; set; }
public CachedProductRepository (IProductRepository productRepository)
{
ProductRepository = productRepository;
}
public IList<Product> GetAll()
{
// Check cache, if exists then return,
// if not then call GetAll() on inner repository
}
}
ProductManager에서 리포지토리 구현 지식을 어떻게 제거 했습니까? 데이터 추출을 처리하는 클래스, 데이터 검색을 처리하는 클래스 및 캐싱을 처리하는 클래스를 통해 단일 책임 원칙을 준수한 방법도 참조하십시오.
이제 이러한 리포지토리 중 하나를 사용하여 ProductManager를 인스턴스화하고 캐싱을 수행 할 수 있습니다. 이것은 나중에 캐시의 결과라고 생각되는 혼란스러운 버그가 발생할 때 매우 유용합니다.
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(IOC 컨테이너를 사용하는 경우 더 좋습니다. 적응 방법이 분명해야합니다.)
그리고 ProductManager 테스트에서
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
캐시를 전혀 테스트 할 필요가 없습니다.
이제 질문은 다음과 같습니다. CachedProductRepository를 테스트해야합니까? 나는 제안하지 않는다. 캐시는 꽤 불확실하다. 프레임 워크는 통제 할 수없는 작업을 수행합니다. 예를 들어 너무 가득 차면 물건을 제거하는 것과 같습니다. 당신은 푸른 달에 한번 실패한 테스트로 끝날 것이고, 왜 그런지 결코 이해하지 못할 것입니다.
그리고 위에서 제안한 변경 사항을 적용하면 실제로 테스트 할 논리가 많지 않습니다. 정말 중요한 테스트 인 필터링 방법이 있으며 GetAll ()의 세부 사항에서 완전히 추상화됩니다. GetAll () 그냥 ... 모두 가져옵니다. 어딘가에서.