सार # के रूप में सार वर्ग का उपयोग करें


21

C ++ डेवलपर के रूप में मैं C ++ हेडर फ़ाइलों के लिए काफी अभ्यस्त हूं, और कोड के अंदर किसी प्रकार के जबरन "दस्तावेज़ीकरण" के लिए यह फायदेमंद है। मेरे पास आमतौर पर एक बुरा समय होता है जब मुझे उसकी वजह से कुछ C # कोड पढ़ना पड़ता है: मेरे पास उस तरह का मानसिक नक्शा नहीं है जिस तरह का मैं उसके साथ हूं।

चलो मान लेते हैं कि एक सॉफ्टवेयर इंजीनियर के रूप में मैं एक कार्यक्रम की रूपरेखा तैयार कर रहा हूं। क्या हर वर्ग को एक अमूर्त असम्बद्ध वर्ग के रूप में परिभाषित करना पागलपन होगा, इसी तरह हम C ++ हेडर के साथ क्या करेंगे, और डेवलपर्स इसे लागू करने देंगे?

मैं अनुमान लगा रहा हूं कि कुछ कारण हो सकते हैं कि कोई व्यक्ति इसे एक भयानक समाधान क्यों समझ सकता है लेकिन मुझे यकीन नहीं है कि क्यों। इस तरह के समाधान के लिए किसी को क्या विचार करना होगा?


13
C # C ++ की तुलना में पूरी तरह से अलग प्रोग्रामिंग भाषा है। कुछ वाक्यविन्यास समान दिखते हैं, लेकिन आपको इसमें अच्छा काम करने के लिए C # समझने की आवश्यकता है। और आपको हेडर फ़ाइलों पर निर्भर रहने के साथ बुरी आदत के बारे में कुछ करना चाहिए। मैंने C ++ के साथ दशकों तक काम किया है, मैंने कभी भी हेडर फ़ाइलों को नहीं पढ़ा है, केवल उन्हें लिखा है।
बेंट

17
C # और Java की सबसे अच्छी चीजों में से एक है हेडर फाइलों से मुक्ति! बस एक अच्छी IDE का उपयोग करें।
Erik Eidt

9
C ++ हेडर फ़ाइलों में घोषणाएँ उत्पन्न बाइनरी का हिस्सा नहीं हैं। वे संकलक और लिंकर के लिए वहां हैं। ये C # अमूर्त वर्ग उत्पन्न कोड का हिस्सा होंगे, किसी भी तरह से कोई लाभ नहीं होगा।
मार्क बेनिंगफील्ड

16
C # में समतुल्य निर्माण एक इंटरफ़ेस है, न कि एक अमूर्त वर्ग।
रॉबर्ट हार्वे

6
@DaniBarcaCasafont "मैं हेडर को एक तेज और विश्वसनीय तरीके के रूप में देखता हूं कि यह देखने के लिए कि क्लास के तरीके और विशेषताएँ क्या हैं, यह किस प्रकार के पैरामीटर की अपेक्षा करता है और यह क्या रिटर्न देता है"। विजुअल स्टूडियो का उपयोग करते समय मेरा विकल्प उस पर Ctrl-MO शॉर्टकट है।
wha7ever -

जवाबों:


44

सी ++ में ऐसा करने का कारण कंपाइलरों को तेजी से लागू करना और लागू करना आसान था। यह प्रोग्रामिंग को आसान बनाने के लिए एक डिज़ाइन नहीं था ।

हेडर फ़ाइलों का उद्देश्य संकलक को सभी त्वरित फ़ंक्शन नामों को जानने के लिए सुपर क्विक फर्स्ट पास करने में सक्षम बनाना और उनके लिए मेमोरी लोकेशन आवंटित करना था ताकि cp फ़ाइलों में कॉल किए जाने पर उन्हें संदर्भित किया जा सके, भले ही वर्ग उन्हें परिभाषित कर रहा हो अभी तक पार्स नहीं किया गया है।

आधुनिक विकास परिवेश में पुरानी हार्डवेयर सीमाओं के परिणाम को दोहराने की कोशिश करना अनुशंसित नहीं है!

हर वर्ग के लिए एक इंटरफ़ेस या अमूर्त वर्ग को परिभाषित करना आपकी उत्पादकता को कम करेगा; उस समय आप और क्या कर सकते थे ? साथ ही, अन्य डेवलपर्स इस सम्मेलन का पालन नहीं करेंगे।

वास्तव में, अन्य डेवलपर्स आपके अमूर्त वर्गों को हटा सकते हैं। अगर मुझे इन दोनों मानदंडों को पूरा करने वाला कोड मिलता है, तो मैं इसे हटा देता हूं और इसे कोड से बाहर निकाल देता हूं :1. Does not conform to the interface segregation principle 2. Only has one class that inherits from it

दूसरी बात यह है कि, विजुअल स्टूडियो के साथ शामिल उपकरण हैं जो आपके द्वारा स्वचालित रूप से पूरा करने का लक्ष्य रखते हैं:

  1. Class View
  2. Object Browser
  3. में Solution Explorerआप कक्षाओं में खर्च करने के लिए अपने काम करता है, मानकों और बदले प्रकार देखने के लिए त्रिकोण पर क्लिक कर सकते हैं।
  4. फ़ाइल टैब के नीचे तीन छोटे ड्रॉप डाउन मेनू हैं, जिनमें से सबसे दाएं वर्तमान वर्ग के सभी सदस्यों को सूचीबद्ध करता है।

C # में C ++ हेडर फ़ाइलों की प्रतिकृति बनाने के लिए समय समर्पित करने से पहले एक कोशिश करें।


इसके अलावा, ऐसा करने के लिए तकनीकी कारण नहीं हैं ... यह आपके अंतिम बाइनरी को जितना हो सके उतना बड़ा बना देगा। मैं मार्क बेनिंगफील्ड की इस टिप्पणी को दोहराऊंगा:

C ++ हेडर फ़ाइलों में घोषणाएँ उत्पन्न बाइनरी का हिस्सा नहीं हैं। वे संकलक और लिंकर के लिए वहां हैं। ये C # अमूर्त वर्ग उत्पन्न कोड का हिस्सा होंगे, किसी भी तरह से कोई लाभ नहीं होगा।


इसके अलावा, रॉबर्ट हार्वे द्वारा तकनीकी रूप से उल्लेख किया गया है, C # में हेडर के सबसे करीब बराबर एक इंटरफ़ेस होगा, न कि एक अमूर्त वर्ग।


2
आप अनावश्यक आभासी प्रेषण कॉल के बहुत से समाप्त करेंगे (यदि आपका कोड प्रदर्शन-संवेदनशील है तो अच्छा नहीं है)।
लुकास ट्रेजेन्यूस्की

5
यहाँ इंटरफ़ेस अलगाव सिद्धांत को संदर्भित किया गया है।
एनएच।

2
एक पक्षी की आंखों को देखने के लिए बस पूरी कक्षा को सम्‍मिलित कर सकता है (दायाँ क्लिक -> रूपरेखा -> परिभाषाओं के लिए संक्षिप्त करें)।
jpmc26

"उस समय आप और क्या कर सकते थे" -> उम्म, कॉपी और पेस्ट और वास्तव में मामूली पोस्टवर्क? मुझे लगभग 3 सेकंड लेता है, अगर बिल्कुल भी। बेशक, मैं उस समय का उपयोग सिगरेट पीने की तैयारी के लिए एक फिल्टर टिप को बाहर निकालने के लिए कर सकता था। वास्तव में एक प्रासंगिक बिंदु नहीं है। [डिस्क्लेमर: मुझे दोनों से प्यार है, मुहावरेदार सी #, साथ ही मुहावरेदार सी ++, और कुछ और भाषाएँ]
१०

1
@phresnel: मैं आपको एक कक्षा की परिभाषाएँ देखने और दोहराने की कोशिश करूँगा और मूल वर्ग को 3 एस में 3 से हटा दूंगा, बिना किसी त्रुटि के, किसी भी वर्ग के लिए, जो कि एक आसान पक्षी की दृष्टि से बड़ा नहीं है, के लिए पर्याप्त है। यह (जैसा कि ओपी के प्रस्तावित उपयोग का मामला है: माना जाता है कि जटिल वर्ग अन्यथा जटिल हैं)। लगभग स्वाभाविक रूप से, मूल वर्ग की जटिल प्रकृति का अर्थ है कि आप केवल दिल से सार वर्ग की परिभाषा नहीं लिख सकते (क्योंकि इसका मतलब होगा कि आप पहले से ही इसे दिल से जानते हैं) और फिर पूरे कोडबेस के लिए ऐसा करने के लिए आवश्यक समय पर विचार करें ।
फ्लेटर

14

सबसे पहले, यह समझें कि विशुद्ध रूप से अमूर्त वर्ग वास्तव में सिर्फ एक इंटरफ़ेस है जो कई उत्तराधिकार नहीं कर सकता है।

क्लास लिखें, एक्सट्रैक्ट इंटरफेस, एक ब्रेन डेड एक्टिविटी है। इतना कि हम इसके लिए एक refactoring है। जो एक दया है। इसके बाद "हर वर्ग को एक इंटरफ़ेस मिलता है" पैटर्न न केवल अव्यवस्था पैदा करता है यह पूरी तरह से बिंदु को याद करता है।

एक इंटरफ़ेस के बारे में नहीं सोचा जाना चाहिए कि जो कुछ भी वर्ग कर सकता है वह केवल एक औपचारिक प्रतिबंध है। एक इंटरफ़ेस को क्लाइंट कोड का उपयोग करके एक अनुबंध के रूप में सोचा जाना चाहिए, जो इसकी आवश्यकता है।

मुझे इंटरफ़ेस लिखने में कोई परेशानी नहीं है कि वर्तमान में केवल एक वर्ग इसे लागू कर रहा है। मैं वास्तव में परवाह नहीं है अगर कोई भी वर्ग अभी तक इसे लागू नहीं करता है। क्योंकि मैं सोच रहा हूं कि मेरे उपयोग करने वाले कोड की क्या जरूरत है। इंटरफ़ेस व्यक्त करता है कि उपयोग कोड क्या मांगता है। बाद में जो भी साथ आता है वह वही कर सकता है जो उसे तब तक पसंद है जब तक वह इन अपेक्षाओं को पूरा नहीं करता है।

अब मैं हर बार ऐसा नहीं करता कि एक वस्तु दूसरे का उपयोग करे। मैं एक सीमा पार करते समय ऐसा करता हूं। मैं ऐसा तब करता हूं जब मैं नहीं चाहता कि एक वस्तु को वास्तव में पता चले कि वह किस अन्य वस्तु से बात कर रहा है। यह एकमात्र तरीका है जिसमें बहुरूपता काम करेगी। मैं इसे तब करता हूं जब मुझे उम्मीद है कि मेरा क्लाइंट कोड बदलने की संभावना है। मैं निश्चित रूप से ऐसा नहीं करता जब मैं उपयोग कर रहा हूँ स्ट्रिंग वर्ग है। स्ट्रिंग क्लास अच्छी और स्थिर है और मुझे लगता है कि मेरे खिलाफ इसे बदलने के लिए कोई ज़रूरत नहीं है।

जब आप सीधे एक ठोस कार्यान्वयन के साथ बातचीत करने का निर्णय लेते हैं, तो एक अमूर्तता के माध्यम से आप यह अनुमान लगा रहे हैं कि कार्यान्वयन स्थिर है, जो विश्वास नहीं बदलने के लिए पर्याप्त है।

ठीक उसी तरह जिस तरह से मैं डिपेंडेंसी इन्वर्सेशन प्रिंसिपल को गुस्सा दिलाता हूं । आपको आंखें मूंदकर यह सब कुछ लागू नहीं करना चाहिए। जब आप एक अमूर्त जोड़ते हैं, तो आप वास्तव में कह रहे हैं कि आप परियोजना के जीवन पर स्थिर होने के लिए वर्ग को लागू करने के विकल्प पर भरोसा नहीं करते हैं।

यह सब मान लेते हैं कि आप ओपन बंद सिद्धांत का पालन करने की कोशिश कर रहे हैं । यह सिद्धांत तभी महत्वपूर्ण है जब स्थापित कोड में सीधे परिवर्तन करने से जुड़ी लागत महत्वपूर्ण हो। मुख्य कारणों में से एक यह है कि लोग इस बात पर असहमत हैं कि वस्तुओं को अलग करना कितना महत्वपूर्ण है क्योंकि प्रत्यक्ष परिवर्तन करते समय सभी को समान लागतों का अनुभव नहीं होता है। यदि आपके संपूर्ण कोड आधार को रिटायर करना, पुन: जमा करना और पुनर्वितरित करना आपके लिए तुच्छ है, तो प्रत्यक्ष संशोधन के साथ परिवर्तन की आवश्यकता को हल करना इस समस्या का एक बहुत ही सरल सरलीकरण है।

बस इस सवाल का कोई ब्रेन डेड जवाब नहीं है। एक इंटरफ़ेस या अमूर्त वर्ग कुछ ऐसा नहीं है जिसे आपको हर वर्ग के साथ जोड़ना चाहिए और आप केवल लागू करने वाली कक्षाओं की संख्या की गणना नहीं कर सकते हैं और यह तय कर सकते हैं कि इसकी आवश्यकता नहीं है। यह बदलाव से निपटने के बारे में है। जिसका मतलब है कि आप भविष्य का अनुमान लगा रहे हैं। अगर आपको यह गलत लगे तो हैरान मत होइए। इसे सरल रखें क्योंकि आप खुद को एक कोने में रखे बिना कर सकते हैं।

तो कृपया, हमें कोड पढ़ने में मदद करने के लिए केवल सार न लिखें। हमारे पास इसके लिए उपकरण हैं। क्या decoupling की जरूरत है यह समझने के लिए अमूर्त का उपयोग करें।


5

हां, यह भयानक होगा क्योंकि (1) यह अनावश्यक कोड का परिचय देता है (2) यह पाठक को भ्रमित करेगा।

यदि आप C # में प्रोग्राम करना चाहते हैं तो आपको C # पढ़ने की आदत डालनी चाहिए। अन्य लोगों द्वारा लिखे गए कोड इस पैटर्न का वैसे भी पालन नहीं करेंगे।


1

इकाई परीक्षण

मैं दृढ़ता से सुझाव दूंगा कि आप इंटरफेस या अमूर्त कक्षाओं (जहां अन्य कारणों से वारंटेड को छोड़कर) के साथ कोड को अव्यवस्थित करने के बजाय यूनिट परीक्षण लिखते हैं।

एक अच्छी तरह से लिखित इकाई परीक्षण न केवल आपकी कक्षा के इंटरफ़ेस का वर्णन करता है (जैसे हेडर फ़ाइल, अमूर्त वर्ग या इंटरफ़ेस करेगा), लेकिन यह भी वर्णन करता है, उदाहरण के लिए, वांछित कार्यक्षमता।

उदाहरण: जहां आपने एक हेडर फ़ाइल myclass.h लिखी हो सकती है:

class MyClass
{
public:
  void foo();
};

इसके बजाय, c # में इस तरह एक परीक्षा लिखें:

[TestClass]
public class MyClassTests
{
    [TestMethod]
    public void MyClass_should_have_method_Foo()
    {
        //Arrange
        var myClass = new MyClass();
        //Act
        myClass.Foo();
        //Verify
        Assert.Inconclusive("TODO: Write a more detailed test");
    }
}

यह बहुत ही सरल परीक्षण हेडर फ़ाइल के रूप में एक ही जानकारी देता है। (हमारे पास पैरामीटर रहित फ़ंक्शन "फू" के साथ "MyClass" नाम का एक वर्ग होना चाहिए) जबकि एक हेडर फ़ाइल अधिक कॉम्पैक्ट है, परीक्षण में अधिक जानकारी शामिल है।

एक चेतावनी: टीडीडी जैसी कार्यप्रणाली के साथ झड़पों को हल करने के लिए अन्य डेवलपर्स के लिए एक वरिष्ठ सॉफ्टवेयर इंजीनियर आपूर्ति (असफल) परीक्षण होने की ऐसी प्रक्रिया, लेकिन आपके मामले में यह एक बड़ा सुधार होगा।


आप यूनिट टेस्टिंग (पृथक परीक्षण) कैसे करते हैं? वास्तविक कार्यान्वयन से मॉकिंग क्या रूपरेखा का समर्थन करता है, सबसे अधिक मैंने देखा है कि मॉक कार्यान्वयन के साथ कार्यान्वयन को स्वैप करने के लिए एक इंटरफ़ेस का उपयोग किया जाता है।
बुलन

मुझे नहीं लगता कि ओपी: एस के उद्देश्यों के लिए नकली की आवश्यकता होती है। याद रखें, यह टीडीडी के लिए उपकरण के रूप में इकाई परीक्षण नहीं है, लेकिन शीर्षक फ़ाइलों के प्रतिस्थापन के रूप में इकाई परीक्षण। (वे निश्चित रूप से "सामान्य" इकाई परीक्षणों में मोक्स आदि के साथ विकसित हो सकते हैं)
गुरन

ठीक है, अगर मैं केवल इसके पक्ष में विचार करता हूं, तो मैं बेहतर समझता हूं। अपने उत्तर को अधिक सामान्य आवेदन के उत्तर के रूप में पढ़ें। स्पष्ट करने के लिए Thx!
Bulan

@ बुलान को व्यापक मजाक की आवश्यकता अक्सर एक बुरे डिजाइन का संकेत देती है
TheCatWhisperer

@ TheCatWhisperer हाँ, मैं अच्छी तरह से वाकिफ हूँ, इसलिए कोई तर्क नहीं है, मैं यह नहीं देख सकता कि मैंने कहीं भी यह बयान दिया है: DI सामान्य रूप से परीक्षण के बारे में बात कर रहा था, कि मैंने जो मॉक-फ्रेमवर्क का उपयोग किया है, वह स्वैप करने के लिए इंटरफेसेस का उपयोग करता है वास्तविक कार्यान्वयन से बाहर है, और अगर आप इंटरफेस के बारे में नहीं है, तो आप कैसे नकली के बारे में कुछ अन्य तकनीक थी।
Bulan
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.