पिछले महीनों में मैंने यहां के लोगों के लिए एसई और अन्य साइटों पर मेरे कोड के बारे में कुछ रचनात्मक आलोचना की पेशकश की है। एक चीज है जो लगभग हर बार पॉपिंग करती है और मैं अभी भी उस सिफारिश से सहमत नहीं हूं; : P मैं यहाँ इसकी चर्चा करना चाहता हूँ और शायद चीजें मेरे लिए स्पष्ट हो जाएँगी।
यह एकल-जिम्मेदारी सिद्धांत (एसआरपी) के बारे में है। मूल रूप से, मेरे पास एक डेटा वर्ग है, Fontजो न केवल डेटा में हेरफेर करने के लिए, बल्कि इसे लोड करने के लिए भी कार्य करता है। मुझे बताया गया है कि दोनों को अलग होना चाहिए, लोडिंग फ़ंक्शंस को फ़ैक्टरी क्लास के अंदर रखा जाना चाहिए; मुझे लगता है कि यह एसआरपी की गलत व्याख्या है ...
मेरा फ़ॉन्ट कक्षा से एक टुकड़ा
class Font
{
public:
bool isLoaded() const;
void loadFromFile(const std::string& file);
void loadFromMemory(const void* buffer, std::size_t size);
void free();
void some();
void another();
};
सुझाया गया डिज़ाइन
class Font
{
public:
void some();
void another();
};
class FontFactory
{
public:
virtual std::unique_ptr<Font> createFromFile(...) = 0;
virtual std::unique_ptr<Font> createFromMemory(...) = 0;
};
सुझाया गया डिज़ाइन कथित रूप से SRP का अनुसरण करता है, लेकिन मैं असहमत हूं - मुझे लगता है कि यह बहुत दूर चला जाता है। Fontवर्ग लंबे समय तक आत्मनिर्भर (यह कारखाना के बिना बेकार है), और नहीं है FontFactoryकी जरूरत है संसाधन है, जो शायद दोस्ती या सार्वजनिक टिककर खेल के माध्यम से किया जाता है के कार्यान्वयन है, जो आगे के कार्यान्वयन का पर्दाफाश के बारे में विवरण जानने के लिए Font। मुझे लगता है कि यह खंडित जिम्मेदारी का मामला है ।
यहाँ मुझे लगता है कि मेरा दृष्टिकोण बेहतर है:
Fontआत्मनिर्भर है - आत्मनिर्भर होने के कारण, इसे समझना और बनाए रखना आसान है। इसके अलावा, आप किसी और चीज को शामिल किए बिना वर्ग का उपयोग कर सकते हैं। यदि, हालांकि, आपको लगता है कि आपको संसाधनों के एक अधिक जटिल प्रबंधन की आवश्यकता है (एक कारखाना) तो आप आसानी से ऐसा कर सकते हैं (बाद में मैं अपने कारखाने के बारे में बात करूँगाResourceManager<Font>)।मानक पुस्तकालय का अनुसरण करता है - मेरा मानना है कि उपयोगकर्ता-परिभाषित प्रकारों को उस संबंधित भाषा में मानक प्रकारों के व्यवहार को कॉपी करने के लिए यथासंभव प्रयास करना चाहिए।
std::fstreamआत्मनिर्भर है और यह की तरह कार्य प्रदान करताopenहै औरclose। मानक पुस्तकालय के बाद का मतलब है कि चीजों को करने का एक और तरीका सीखने के लिए प्रयास करने की आवश्यकता नहीं है। इसके अलावा, आम तौर पर बोलते हुए, C ++ मानक समिति शायद यहां किसी की तुलना में डिजाइन के बारे में अधिक जानती है, इसलिए यदि कभी संदेह हो, तो वे जो करते हैं उसे कॉपी करें।परीक्षणशीलता - कुछ गलत हो जाता है, समस्या कहां हो सकती है? - क्या यह तरीका
Fontअपना डेटा संभालता है या डेटाFontFactoryलोड करने का तरीका है ? तुम सच में नहीं जानते। कक्षाएं आत्मनिर्भर होने से यह समस्या कम हो जाती है: आपFontअलगाव में परीक्षण कर सकते हैं । यदि आपको कारखाने का परीक्षण करना है और आप जानते हैं किFontठीक काम करता है, तो आपको यह भी पता होगा कि जब भी कोई समस्या होती है तो उसे कारखाने के अंदर होना चाहिए।यह संदर्भ अज्ञेय है - (यह मेरी पहली बात के साथ थोड़ा प्रतिच्छेद
Fontकरता है ।) अपनी बात करता है और इस बारे में कोई धारणा नहीं बनाता है कि आप इसका उपयोग कैसे करेंगे: आप इसका उपयोग किसी भी तरह से कर सकते हैं। उपयोगकर्ता को किसी कारखाने का उपयोग करने के लिए मजबूर करना कक्षाओं के बीच युग्मन को बढ़ाता है।
मेरा भी एक कारखाना है
(क्योंकि डिजाइन Fontमुझे अनुमति देता है।)
या एक प्रबंधक के बजाय, केवल एक कारखाना नहीं है ... Fontआत्मनिर्भर है इसलिए प्रबंधक को यह जानने की आवश्यकता नहीं है कि किसी को कैसे बनाया जाए; इसके बजाय प्रबंधक सुनिश्चित करता है कि एक ही फाइल या बफर एक से अधिक बार मेमोरी में लोड न हो। आप कह सकते हैं कि एक फैक्ट्री भी ऐसा कर सकती है, लेकिन क्या इससे एसआरपी नहीं टूटेगा? कारखाने को न केवल वस्तुओं का निर्माण करना होगा, बल्कि उन्हें प्रबंधित भी करना होगा।
template<class T>
class ResourceManager
{
public:
ResourcePtr<T> acquire(const std::string& file);
ResourcePtr<T> acquire(const void* buffer, std::size_t size);
};
यहां बताया गया है कि प्रबंधक का उपयोग कैसे किया जा सकता है। ध्यान दें कि यह एक कारखाने के रूप में मूल रूप से उपयोग किया जाता है।
void test(ResourceManager<Font>* rm)
{
// The same file isn't loaded twice into memory.
// I can still have as many Fonts using that file as I want, though.
ResourcePtr<Font> font1 = rm->acquire("fonts/arial.ttf");
ResourcePtr<Font> font2 = rm->acquire("fonts/arial.ttf");
// Print something with the two fonts...
}
जमीनी स्तर...
(यह एक tl डालना चाहते हैं; यहाँ डॉ; लेकिन मैं एक के बारे में नहीं सोच सकता ।:))
ठीक है, वहाँ तुम्हारे पास है, मैं अपने मामले में सबसे अच्छा के रूप में मैं कर सकता था। कृपया आपके द्वारा किए गए किसी भी काउंटर-तर्क को पोस्ट करें और यह भी कि आपको लगता है कि सुझाए गए डिज़ाइन का मेरे खुद के डिज़ाइन से अधिक है। मूल रूप से, मुझे दिखाने की कोशिश करें कि मैं गलत हूं। :)