The Tunggal Tanggung Jawab Prinsip adalah teman terbaik Anda di sini.
Pertama-tama, pindahkan AllFromCache () ke kelas repositori dan beri nama GetAll (). Itu diambil dari cache adalah detail implementasi dari repositori dan tidak boleh diketahui oleh kode panggilan.
Ini membuat pengujian kelas penyaringan Anda menyenangkan dan mudah. Tidak lagi peduli dari mana Anda mendapatkannya.
Kedua, bungkus kelas yang mendapatkan data dari database (atau di mana pun) dalam pembungkus caching.
AOP adalah teknik yang bagus untuk ini. Ini salah satu dari beberapa hal yang sangat bagus.
Menggunakan alat-alat seperti PostSharp , Anda dapat mengaturnya sehingga metode apa pun yang ditandai dengan atribut yang dipilih akan di-cache. Namun, jika ini adalah satu-satunya hal yang Anda caching, Anda tidak perlu pergi sejauh memiliki kerangka kerja AOP. Hanya memiliki Repositori dan Pembungkus Caching yang menggunakan antarmuka yang sama dan menyuntikkan itu ke kelas panggilan.
misalnya.
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
}
}
Lihat bagaimana Anda telah menghapus pengetahuan implementasi repositori dari ProductManager? Lihat juga bagaimana Anda mematuhi Prinsip Tanggung Jawab Tunggal dengan memiliki kelas yang menangani ekstraksi data, kelas yang menangani pengambilan data, dan kelas yang menangani caching?
Anda sekarang dapat instantiate ProductManager dengan salah satu dari Repositori tersebut dan mendapatkan caching ... atau tidak. Ini sangat berguna nantinya ketika Anda mendapatkan bug yang membingungkan yang Anda duga adalah hasil dari cache.
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(Jika Anda menggunakan wadah IOC, bahkan lebih baik. Seharusnya jelas cara beradaptasi.)
Dan, dalam tes ProductManager Anda
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
Tidak perlu menguji cache sama sekali.
Sekarang pertanyaannya menjadi: Haruskah saya menguji CachedProductRepository itu? Saya sarankan tidak. Cache ini cukup tidak pasti. Kerangka kerja melakukan hal-hal dengan itu yang di luar kendali Anda. Seperti, hanya menghapus barang-barang dari itu ketika sudah terlalu penuh, misalnya. Anda akan berakhir dengan tes yang gagal sekali dalam bulan biru dan Anda tidak akan pernah mengerti mengapa.
Dan, setelah melakukan perubahan yang saya sarankan di atas, benar-benar tidak banyak logika untuk diuji di sana. Tes yang sangat penting, metode penyaringan, akan ada di sana dan sepenuhnya disarikan dari detail GetAll (). GetAll () baru saja ... mendapatkan semuanya. Dari suatu tempat.