एकल जिम्मेदारी सिद्धांत अपने सबसे अच्छे दोस्त यहाँ है।
सबसे पहले, 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>();
कैश का परीक्षण करने की कोई आवश्यकता नहीं है।
अब प्रश्न यह हो जाता है: क्या मुझे उस कैश्ड प्रोडक्ट रिपोजिटरी का परीक्षण करना चाहिए? मैं सुझाव देता हूं कि नहीं। कैश बहुत अनिश्चित है। रूपरेखा इसके साथ चीजें करती हैं जो आपके नियंत्रण से बाहर हैं। जैसे, उदाहरण के लिए, बहुत अधिक हो जाने पर, उसमें से सामान निकालना। आप उन परीक्षणों को समाप्त करने जा रहे हैं जो एक नीले चंद्रमा में एक बार विफल हो जाते हैं और आप वास्तव में कभी नहीं समझ पाएंगे कि क्यों।
और, मैंने ऊपर जिन परिवर्तनों का सुझाव दिया है, वास्तव में वहाँ परीक्षण करने के लिए उतना तर्क नहीं है। वास्तव में महत्वपूर्ण परीक्षण, फ़िल्टरिंग विधि, गेटएल () के विवरण से पूरी तरह से अलग हो जाएगी। GetAll () बस ... सब मिलता है। कहीं से।