Tek Sorumluluk Prensibi burada iyi arkadaşı.
Her şeyden önce, AllFromCache () 'i bir havuz sınıfına taşıyın ve GetAll () olarak adlandırın. Önbellekten alması deponun bir uygulama detayıdır ve çağıran kod tarafından bilinmemelidir.
Bu, filtreleme sınıfınızı test etmeyi kolay ve kolay hale getirir. Artık nereden aldığınız umurunda değil.
İkinci olarak, verileri veritabanından (veya her yerde) bir önbellek sarmalayıcısına alan sınıfı sarın.
AOP bunun için iyi bir tekniktir. Çok iyi olduğu birkaç şeyden biri.
PostSharp gibi araçları kullanarak , seçilen bir özellik ile işaretlenmiş herhangi bir yöntemin önbelleğe alınmasını sağlayacak şekilde ayarlayabilirsiniz. Ancak, önbelleğe aldığınız tek şey buysa, bir AOP çerçevesine sahip olmak kadar ileri gitmenize gerek yoktur. Aynı arabirimi kullanan ve bunu çağıran sınıfa enjekte eden bir Havuz ve Önbellek Sarıcıya sahip olmanız yeterlidir.
Örneğin.
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
}
}
Havuz uygulama bilgilerini ProductManager'dan nasıl kaldırdığınızı gördünüz mü? Ayrıca, veri çıkarmayı işleyen bir sınıfa, veri almayı işleyen bir sınıfa ve önbelleğe almayı işleyen bir sınıfa sahip olarak Tek Sorumluluk İlkesi'ne nasıl uyduğunuzu görün.
Artık ProductManager'ı bu Depolardan herhangi biriyle başlatabilir ve önbelleğe alabilirsiniz ... ya da edemezsiniz. Bu, daha sonra önbelleğin bir sonucu olduğundan şüphelendiğiniz kafa karıştırıcı bir hata aldığınızda inanılmaz derecede yararlıdır.
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(Bir IOC kabı kullanıyorsanız, daha da iyi. Nasıl adapte olacağınız açık olmalıdır.)
Ve ProductManager testlerinizde
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
Önbelleği test etmeye gerek yok.
Şimdi soru şu: Bu CachedProductRepository'yi test etmeli miyim? Önermiyorum. Önbellek oldukça belirsiz. Çerçeve onunla sizin kontrolünüz dışında olan şeyleri yapar. Mesela, çok fazla dolduğunda bir şeyleri çıkarmak gibi. Bir mavi ayda bir kez başarısız olan testlerle sonuçlanacaksınız ve nedenini asla gerçekten anlamayacaksınız.
Ve yukarıda önerdiğim değişiklikleri yaptıktan sonra, orada test edilecek çok fazla mantık yok. Gerçekten önemli bir test olan filtreleme yöntemi orada olacak ve GetAll () 'ın ayrıntılarından tamamen soyutlanacaktır. GetAll () sadece ... hepsini alır. Bir yerlerden.