क्या एनामस भंगुर इंटरफेस बनाते हैं?


17

नीचे दिए गए उदाहरण पर विचार करें। ColorChoice enum में कोई भी परिवर्तन सभी IWindowColor उपवर्गों को प्रभावित करता है।

क्या ईर्ष्या भंगुर इंटरफेस का कारण बनती है? क्या अधिक बहुरूपी लचीलेपन की अनुमति देने के लिए किसी एनम से बेहतर कुछ है?

enum class ColorChoice
{
    Blue = 0,
    Red = 1
};

class IWindowColor
{
public:
    ColorChoice getColor() const=0;
    void setColor( const ColorChoice value )=0;
};

संपादित करें: मेरे उदाहरण के रूप में रंग का उपयोग करने के लिए खेद है, कि सवाल क्या है के बारे में नहीं है। यहां एक अलग उदाहरण है जो लाल हेरिंग से बचा जाता है और लचीलेपन से मेरा क्या मतलब है, इसके बारे में अधिक जानकारी प्रदान करता है।

enum class CharacterType
{
    orc = 0,
    elf = 1
};

class ISomethingThatNeedsToKnowWhatTypeOfCharacter
{
public:
    CharacterType getCharacterType() const;
    void setCharacterType( const CharacterType value );
};

इसके अलावा, कल्पना करें कि उपयुक्त ISomethingThatNeedsToKnowWhatTypeOfCharacter उपवर्ग को संभालती है एक कारखाने के डिजाइन पैटर्न द्वारा सौंपे गए हैं। अब मेरे पास एक एपीआई है जिसे भविष्य में एक अलग आवेदन के लिए विस्तारित नहीं किया जा सकता है जहां स्वीकार्य चरित्र प्रकार {मानव, बौना} हैं।

संपादित करें: मैं जो काम कर रहा हूं, उसके बारे में अधिक ठोस होना। मैं इस ( MusicXML ) विनिर्देश के एक मजबूत बंधन को डिजाइन कर रहा हूं और मैं विनिर्देशन में उन प्रकारों का प्रतिनिधित्व करने के लिए एनम वर्गों का उपयोग कर रहा हूं जो एक्स: एन्यूमरेशन के साथ घोषित किए गए हैं। मैं सोचने की कोशिश कर रहा हूं कि जब अगला संस्करण (4.0) सामने आता है तो क्या होता है। क्या मेरी क्लास लाइब्रेरी 3.0 मोड में और 4.0 मोड में काम कर सकती है? यदि अगला संस्करण 100% पिछड़ा संगत है, तो हो सकता है। लेकिन अगर गणना मूल्यों को विनिर्देश से हटा दिया गया है तो मैं पानी में मर चुका हूं।


2
जब आप "बहुरूपी लचीलापन" कहते हैं, तो आपके दिमाग में वास्तव में क्या क्षमताएं हैं?
Ixrec


3
रंगों के लिए एक एनम का उपयोग करना भंगुर इंटरफेस बनाता है, न कि केवल "एनम का उपयोग करना"।
डॉक ब्राउन

3
उस एनम का उपयोग करके एक नया एनम वेरिएंट ब्रेक कोड जोड़ना । एक एनुम में एक नया ऑपरेशन जोड़ना दूसरी ओर काफी आत्म-निहित है, क्योंकि जिन मामलों को संभालने की आवश्यकता है वे सभी वहीं हैं (इसके विपरीत इंटरफेस और सुपरक्लेसेस, जहां गैर-डिफ़ॉल्ट विधि जोड़ना एक गंभीर ब्रेकिंग परिवर्तन है)। यह उस प्रकार के परिवर्तनों पर निर्भर करता है जो वास्तव में आवश्यक हैं।

1
पुन: MusicXML: अगर XML फ़ाइलों से यह बताने का कोई आसान तरीका नहीं है कि स्कीमा का कौन सा संस्करण उपयोग कर रहा है, तो यह मुझे विनिर्देश में महत्वपूर्ण डिजाइन दोष के रूप में प्रभावित करता है। यदि आपको इसे किसी तरह से हल करना है, तो शायद हमारे लिए कोई रास्ता नहीं है जब तक कि हम यह नहीं जान पाएंगे कि वे 4.0 में ब्रेक का चयन क्या करेंगे और आप इसके कारण होने वाली एक विशिष्ट समस्या के बारे में पूछ सकते हैं।
Ixrec

जवाबों:


25

जब ठीक से उपयोग किया जाता है, तो एनमेस "जादुई संख्या" की तुलना में कहीं अधिक पठनीय और मजबूत होते हैं जो वे प्रतिस्थापित करते हैं। मैं आमतौर पर उन्हें कोड को अधिक भंगुर बनाते हुए नहीं देखता। उदाहरण के लिए:

  • setColor () के लिए समय की जाँच बर्बाद नहीं है अगर value वैध रंग मान है या नहीं, यह नहीं करना है। कंपाइलर पहले ही ऐसा कर चुका है।
  • आप सेटकोलर (0) के बजाय सेट कलर (रंग :: लाल) लिख सकते हैं। मुझे विश्वास हैenum class आधुनिक C ++ में सुविधा यहां तक ​​कि आपको लोगों को बाद के बजाय हमेशा पूर्व लिखने के लिए मजबूर करती है।
  • आमतौर पर महत्वपूर्ण नहीं है, लेकिन अधिकांश एनमों को किसी भी आकार के अभिन्न प्रकार के साथ लागू किया जा सकता है, इसलिए कंपाइलर चुन सकता है कि ऐसी चीजों के बारे में सोचने के लिए मजबूर किए बिना जो भी आकार सबसे सुविधाजनक है।

तथापि, रंग के लिए एक एनुम का उपयोग करना संदिग्ध है क्योंकि कई (अधिकांश?) स्थितियों में उपयोगकर्ता को रंगों के इतने छोटे सेट तक सीमित करने का कोई कारण नहीं है; आप उन्हें किसी भी आरजीबी मूल्यों में पास होने दे सकते हैं। जिन परियोजनाओं पर मैं काम करता हूं, उन पर रंगों की एक छोटी सूची केवल "थीम" या "शैलियों" के सेट के हिस्से के रूप में आएगी, जो कि कंक्रीट रंगों पर एक पतली अमूर्तता के रूप में कार्य करने वाली है।

मुझे यकीन नहीं है कि आपका "बहुरूपी लचीलापन" प्रश्न क्या हो रहा है। Enums का कोई निष्पादन योग्य कोड नहीं है, इसलिए बहुरूपी बनाने के लिए कुछ भी नहीं है। शायद आप ढूंढ रहे हैं कमांड पैटर्न की ?

संपादित करें: पोस्ट-एडिट, मैं अभी भी स्पष्ट नहीं हूं कि आप किस तरह की विस्तारशीलता की तलाश कर रहे हैं, लेकिन मुझे अभी भी लगता है कि कमांड पैटर्न निकटतम चीज है जो आपको "पॉलीमॉर्फिक एनम" मिलेगा।


मैं 0 को एनम के रूप में पारित करने की अनुमति नहीं देने के बारे में अधिक जानकारी कहां से प्राप्त कर सकता हूं?
टैंकरस्मैश

5
@TankorSmash C ++ 11 ने "एनम क्लास" की शुरुआत की, जिसे "स्कोप्ड एनम" भी कहा जाता है, जिसे उनके अंतर्निहित संख्यात्मक प्रकार में परिवर्तित नहीं किया जा सकता है। वे नाम स्थान को प्रदूषित करने से भी बचते हैं क्योंकि पुरानी सी-शैली "एनम" प्रकार की थी।
मैथ्यू जेम्स ब्रिग्स

2
एनम आमतौर पर पूर्णांकों द्वारा समर्थित हैं। बहुत सारी अजीब चीजें हैं जो क्रमांकन / डिसेरिएलाइज़ेशन या पूर्णांक और एनम के बीच कास्टिंग में हो सकती हैं। यह मान लेना हमेशा सुरक्षित नहीं है कि एक एनुम का हमेशा एक मान्य मूल्य होगा।
एरिक

1
आप सही एरिक हैं (और यह एक ऐसा मुद्दा है जिसका मैंने कई बार सामना किया है)। हालाँकि, आपको केवल डीरियलाइज़ेशन चरण में संभवतः अमान्य मान के बारे में चिंता करनी होगी। अन्य सभी बार जब आप एनम का उपयोग करते हैं, तो आप मान सकते हैं कि मान वैध है (कम से कम स्कैला जैसी भाषाओं में एनम के लिए - कुछ भाषाओं में एनम के लिए बहुत मजबूत प्रकार की जाँच नहीं होती है)।
कैट

1
@Ixrec "क्योंकि कई (अधिकांश?) स्थितियों में उपयोगकर्ता को रंगों के इतने छोटे समूह तक सीमित करने का कोई कारण नहीं है" वैध मामले हैं। नेट कंसोल पुरानी शैली खिड़कियों सांत्वना है, जो केवल 16 रंगों (सीजीए मानक के 16 रंग) में से एक में पाठ रख सकता हूँ emulates msdn.microsoft.com/en-us/library/...
Pharap

15

ColorChoice enum में कोई भी परिवर्तन सभी IWindowColor उपवर्गों को प्रभावित करता है।

नहीं, यह नहीं है। दो मामले हैं: कार्यान्वयनकर्ता या तो होंगे

  • स्टोर करें, वापस लौटें और आगे के एनम वैल्यूज़ को कभी भी उन पर काम न करें, जिस स्थिति में वे एनम में बदलाव से अप्रभावित रहते हैं, या

  • व्यक्तिगत एनम वैल्यू पर काम करते हैं, इस मामले में एनम में कोई भी बदलाव, स्वाभाविक रूप से, अनिवार्य रूप से, आवश्यक रूप से, कार्यान्वयनकर्ता के तर्क में एक समान परिवर्तन के लिए जिम्मेदार होना चाहिए।

यदि आप "आकृति", "आयत", और "पिरामिड" को "आकार" में डालते हैं, और कुछ drawSolid()फ़ंक्शन के लिए ऐसी एनम पास करते हैं, जो आपने संबंधित ठोस को आकर्षित करने के लिए लिखा है, और फिर एक सुबह आप "जोड़ने" का फैसला करते हैं इकोसाइटेट्रैड्रॉन "एनम के लिए मूल्य, आप drawSolid()फ़ंक्शन को अप्रभावित रहने की उम्मीद नहीं कर सकते हैं; यदि आप यह उम्मीद करते हैं कि यह किसी भी तरह से आप के बिना icositetrahedrons आकर्षित करने के लिए पहली बार icositetrahedrons आकर्षित करने के लिए वास्तविक कोड लिखने के लिए है, तो यह आपकी गलती है, एनम की गलती नहीं है। इसलिए:

क्या ईर्ष्या भंगुर इंटरफेस का कारण बनती है?

नहीं, वे नहीं। जिन कारणों से भंगुर इंटरफेस होता है, वे प्रोग्रामर खुद को निन्जा समझते हैं, पर्याप्त चेतावनी के बिना अपने कोड को संकलित करने की कोशिश कर रहे हैं। फिर, संकलक ने उन्हें चेतावनी नहीं दी है कि उनके drawSolid()कार्य में एक switchबयान शामिल है जो caseनए जोड़े गए "Ikositetrahedron" एनम मूल्य के लिए एक खंड याद कर रहा है ।

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


अब, सच कहा जाए, तो एनम एक वस्तु-उन्मुख निर्माण नहीं हैं। वे वस्तु-उन्मुख प्रतिमान और संरचित प्रोग्रामिंग प्रतिमान के बीच एक व्यावहारिक समझौता के अधिक हैं।

चीजों को करने का शुद्ध ऑब्जेक्ट-ओरिएंटेड तरीका बिल्कुल नहीं है, और इसके बजाय सभी तरह की वस्तुएं हैं।

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

इस तरह, जब आप "Ikositetrahedron" उपवर्ग का परिचय देते हैं, तो आपको बस इसके लिए एक draw()फ़ंक्शन प्रदान करना होगा, और संकलक आपको यह याद दिलाने के लिए करेगा कि, आपको "Icositetrahedron" को तुरंत न दें।


उन स्विच के लिए एक संकलन समय चेतावनी फेंकने पर कोई सुझाव? मैं आमतौर पर सिर्फ रनटाइम अपवादों को फेंक देता हूं; लेकिन संकलन समय महान हो सकता है! नहीं के रूप में महान .. लेकिन इकाई परीक्षण दिमाग में आते हैं।
वॉन हिल्ट्स

1
जब से मैंने अंतिम बार C ++ का उपयोग किया है, तब से यह निश्चित है, इसलिए मुझे यकीन नहीं है, लेकिन मुझे उम्मीद है कि कंपाइलर को -Wall पैरामीटर की आपूर्ति करना और default:क्लॉज को छोड़ देना चाहिए। विषय पर एक त्वरित खोज ने कोई और अधिक निश्चित परिणाम नहीं दिया, इसलिए यह एक अन्य programmers SEप्रश्न के विषय के रूप में उपयुक्त हो सकता है ।
माइक नाकिस

C ++ में यदि आप इसे सक्षम करते हैं तो एक संकलन समय की जांच हो सकती है। C # में किसी भी चेक को रन टाइम पर होना चाहिए। जब भी मैं एक गैर-ध्वज एनुम को एक पैरामीटर के रूप में लेता हूं, तो मैं इसे Enum.IsDefined के साथ मान्य करना सुनिश्चित करता हूं, लेकिन इसका मतलब यह है कि जब आप एक नया मान जोड़ते हैं, तो आपको Enum के सभी उपयोगों को मैन्युअल रूप से अपडेट करना होगा। देखें: stackoverflow.com/questions/12531132/…
माइक

1
मुझे उम्मीद है कि एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामर कभी भी अपने डेटा ट्रांसफर ऑब्जेक्ट को नहीं बनाएगा, जैसे कि Pyramidवास्तव में draw()एक पिरामिड को कैसे पता है । सबसे अच्छा यह Solidएक GetTriangles()विधि से प्राप्त हो सकता है और आप इसे एक SolidDrawerसेवा में पारित कर सकते हैं । मुझे लगा कि हम OOP में वस्तुओं के उदाहरण के रूप में भौतिक वस्तुओं के उदाहरणों से दूर हो रहे हैं।
स्कॉट व्हिटलॉक

1
यह ठीक है, बस किसी को अच्छी पुरानी वस्तु उन्मुख प्रोग्रामिंग को कोसना पसंद नहीं आया। :) खासकर जब से हम में से अधिकांश कार्यात्मक प्रोग्रामिंग और ओओपी को कड़ाई से कहीं अधिक ओओपी से जोड़ते हैं।
स्कॉट व्हिटलॉक

14

Enums भंगुर इंटरफेस नहीं बनाते हैं। गलत इस्तेमाल का करता है।

एनम किस लिए हैं?

Enums को सार्थक रूप से नामित स्थिरांक के सेट के रूप में उपयोग करने के लिए डिज़ाइन किया गया है। उनका उपयोग तब किया जाना चाहिए जब:

  • आप जानते हैं कि कोई भी मूल्य नहीं निकाला जाएगा।
  • (और) आप जानते हैं कि यह बहुत कम संभावना है कि एक नए मूल्य की आवश्यकता होगी।
  • (या) आप स्वीकार करते हैं कि एक नए मूल्य की आवश्यकता होगी, लेकिन इसके कारण टूटने वाले सभी कोड को ठीक करने के लिए वारंट के लिए पर्याप्त रूप से पर्याप्त है।

एनम का अच्छा उपयोग:

  • सप्ताह के दिन: (.Net के अनुसार)System.DayOfWeek ) जब तक आप कुछ अविश्वसनीय अस्पष्ट कैलेंडर के साथ काम नहीं कर रहे हैं, तब तक सप्ताह के केवल 7 दिन होंगे।
  • गैर-एक्स्टेंसिबल रंग: (.Net के अनुसार System.ConsoleColor) कुछ इससे असहमत हो सकते हैं, लेकिन .Net ने इसे एक कारण के लिए चुना। .Net के कंसोल सिस्टम में, कंसोल द्वारा उपयोग के लिए केवल 16 रंग उपलब्ध हैं। ये 16 रंग सीजीए या 'कलर ग्राफिक्स एडेप्टर' के रूप में जानी जाने वाली विरासत रंग पैलेट के अनुरूप हैं । कोई नया मान कभी नहीं जोड़ा जाएगा, जिसका अर्थ है कि यह वास्तव में एक एनम का एक उचित अनुप्रयोग है।
  • निश्चित राज्यों का प्रतिनिधित्व करने वाले गणना: (जावा के अनुसार Thread.State) जावा के डिजाइनरों ने फैसला किया कि जावा थ्रेडिंग मॉडल में केवल कभी-कभी राज्यों का एक निश्चित सेट होगा जो किसी Threadभी मामले में हो सकता है, और इसलिए मामलों को सरल बनाने के लिए, इन अलग-अलग राज्यों का प्रतिनिधित्व किया जाता है। । इसका मतलब यह है कि कई राज्य-आधारित चेक सरल आईएफ और स्विच हैं जो अभ्यास में पूर्णांक मूल्यों पर काम करते हैं, प्रोग्रामर के बिना इस बात की चिंता किए बिना कि मूल्य वास्तव में क्या हैं।
  • गैर-पारस्परिक रूप से अनन्य विकल्पों का प्रतिनिधित्व करने वाले बिटफ्लैग: (.Net के अनुसार System.Text.RegularExpressions.RegexOptions) बिटफ्लैग एनम का बहुत ही सामान्य उपयोग है। तो वास्तव में, आम है कि। नेट में सभी एनमों HasFlag(Enum flag)में निर्मित एक विधि होती है। वे बिटवाइज ऑपरेटरों का भी समर्थन करते हैं और FlagsAttributeबिटमैप के एक सेट के रूप में उपयोग किए जाने के उद्देश्य से एक एनम को चिह्नित करना है। झंडे के सेट के रूप में एक एनम का उपयोग करके, आप एकल मूल्य में बूलियन मानों के एक समूह का प्रतिनिधित्व कर सकते हैं, साथ ही साथ झंडे को सुविधा के लिए स्पष्ट रूप से नामित किया जा सकता है। यह किसी एमुलेटर में किसी स्टेटस रजिस्टर के झंडे का प्रतिनिधित्व करने के लिए या किसी फाइल (रीड, राइट, एग्जीक्यूट) की अनुमतियों का प्रतिनिधित्व करने के लिए या किसी भी स्थिति के बारे में बेहद फायदेमंद होगा जहां संबंधित विकल्पों का एक सेट परस्पर अनन्य नहीं है।

एनम के बुरे उपयोग:

  • एक खेल में चरित्र वर्ग / प्रकार: जब तक कि खेल एक-शॉट डेमो नहीं है जिसे आप फिर से उपयोग करने की संभावना नहीं रखते हैं, तो चरित्र वर्ग के लिए enums का उपयोग नहीं किया जाना चाहिए क्योंकि संभावना है कि आप बहुत अधिक कक्षाएं जोड़ना चाहते हैं। चरित्र का प्रतिनिधित्व करने वाले एकल वर्ग का होना बेहतर है और एक खेल चरित्र 'प्रकार' का प्रतिनिधित्व किया जाता है। इसे संभालने का एक तरीका टाइपऑब्जेक्ट पैटर्न है, अन्य समाधानों में एक शब्दकोश / टाइप रजिस्ट्री के साथ चरित्र प्रकारों को पंजीकृत करना, या दोनों का मिश्रण शामिल है।
  • एक्स्टेंसिबल कलर्स: यदि आप रंगों के लिए एनम का उपयोग कर रहे हैं, जो बाद में इसमें जोड़ा जा सकता है, तो एनम के रूप में इसका प्रतिनिधित्व करना एक अच्छा विचार नहीं है, अन्यथा आपको रंगों को जोड़ने के लिए हमेशा के लिए छोड़ दिया जाएगा। यह ऊपर दिए गए मुद्दे के समान है, इस प्रकार एक समान समाधान का उपयोग किया जाना चाहिए (यानी टाइपऑब्जेक्ट का एक रूपांतर)।
  • एक्स्टेंसिबल स्टेट: यदि आपको एक स्टेट मशीन मिल गई है, जो कई और राज्यों को शुरू कर सकती है, तो इन राज्यों को एन्यूमरेशन के जरिए प्रस्तुत करना अच्छा नहीं है। पसंदीदा विधि मशीन की स्थिति के लिए एक इंटरफ़ेस को परिभाषित करने के लिए है, एक कार्यान्वयन या वर्ग प्रदान करता है जो इंटरफ़ेस को लपेटता है और अपनी विधि कॉल ( रणनीति पैटर्न के समान ) को दर्शाता है, और फिर बदलकर अपनी स्थिति बदल देता है जो कि कार्यान्वयन वर्तमान में सक्रिय है।
  • पारस्परिक रूप से अनन्य विकल्पों का प्रतिनिधित्व करने वाले बिटफ्लैग्स: यदि आप झंडे का प्रतिनिधित्व करने के लिए एनम का उपयोग कर रहे हैं और उन दो झंडों को कभी एक साथ नहीं होना चाहिए तो आपने पैर में खुद को गोली मार ली है। झंडे में से किसी एक पर प्रतिक्रिया करने के लिए जो कुछ भी प्रोग्राम किया जाता है, वह अचानक झंडे पर प्रतिक्रिया करेगा जो भी पहले या प्रतिक्रिया करने के लिए प्रोग्राम किया गया है - यह दोनों के लिए प्रतिक्रिया हो सकती है। इस तरह की स्थिति सिर्फ परेशानी के लिए पूछ रही है। यदि संभव हो तो ध्वज की अनुपस्थिति को वैकल्पिक स्थिति के रूप में माना जाता है (अर्थात Trueध्वज की अनुपस्थिति का अर्थ है False)। विशिष्ट कार्यों (यानी IsTrue(flags)और IsFalse(flags)) के उपयोग के माध्यम से इस व्यवहार को और समर्थन दिया जा सकता है ।

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

1
.NET का RegexOptions msdn.microsoft.com/en-us/library/…
BLSully

@BLSully उत्कृष्ट उदाहरण। कह नहीं सकता कि मैंने कभी उनका उपयोग किया है, लेकिन वे एक कारण से मौजूद हैं।
फराप

4

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

समस्या तब है जब आपके पास enum से जुड़ी महत्वपूर्ण कार्यक्षमता हो। अर्थात्, आपके पास इस तरह का कोड पड़ा हुआ है:

switch (my_enum) {
case orc: growl(); break;
case elf: sing(); break;
...
}

इनमें से एक या दो ठीक है, लेकिन जैसे ही आपके पास इस तरह की सार्थक switchदुश्मनी होती है , ये कथन कबीलों की तरह गुणा करने लगते हैं। अब हर बार जब आप एनम का विस्तार करते हैं, तो आपको switchयह सुनिश्चित करने के लिए सभी संबद्ध es का शिकार करने की आवश्यकता होती है कि आपने सब कुछ कवर किया है। यह भंगुर है। क्लीन कोड जैसे स्रोत यह सुझाव देंगे कि आपके पास switchप्रति वर्ष एक, अधिकतम होना चाहिए ।

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


1

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

  1. मानों को कभी हटाएं या न निकालें। यदि आप किसी बिंदु पर अपनी सूची में कोई मान रखते हैं, तो उस मूल्य को सभी अनंत काल के लिए उस नाम के साथ जोड़ा जाना चाहिए। यदि आप चाहते हैं, तो आप कुछ बिंदुओं का नाम बदल सकते हैं deprecated_orcया जो भी हो, लेकिन उन्हें नहीं हटाकर आप पुराने कोडों के खिलाफ संकलित पुराने कोड के साथ अधिक आसानी से संगतता बनाए रख सकते हैं। यदि कुछ नए कोड पुराने एनम स्थिरांक के साथ सौदा नहीं कर सकते हैं, तो या तो वहां एक उपयुक्त त्रुटि उत्पन्न करें या सुनिश्चित करें कि ऐसा कोई मूल्य कोड के उस टुकड़े तक नहीं पहुंचता है।

  2. उन पर अंकगणित मत करो। विशेष रूप से, तुलना का आदेश न दें। क्यों? क्योंकि तब आप एक ऐसी स्थिति का सामना कर सकते हैं जहाँ आप मौजूदा मूल्यों को बनाए नहीं रख सकते हैं और एक ही समय में एक आदेश को संरक्षित कर सकते हैं। उदाहरण के लिए कम्पास दिशाओं के लिए एक एनम लें: एन = 0, एनई = 1, ई = 2, एसई = 3,… अब अगर कुछ अपडेट के बाद आप एनएनई को शामिल करते हैं और मौजूदा दिशाओं के बीच में, आप या तो उन्हें अंत तक जोड़ सकते हैं। सूची में और इस प्रकार आदेश को तोड़ते हैं, या आप उन्हें मौजूदा कुंजियों के साथ इंटरलेव करते हैं और इस प्रकार विरासत कोड में उपयोग किए गए स्थापित मैपिंग को तोड़ते हैं। या आप सभी पुरानी कुंजियों को चित्रित करते हैं, और कुछ संगतता कोड के साथ-साथ पूरी तरह से नए कुंजी सेट करते हैं, जो विरासत कोड के लिए पुरानी और नई कुंजी के बीच अनुवाद करता है।

  3. पर्याप्त आकार चुनें। डिफ़ॉल्ट रूप से कंपाइलर सबसे छोटे पूर्णांक का उपयोग करेगा जिसमें सभी एनम मान हो सकते हैं। जिसका अर्थ है कि यदि, किसी अद्यतन में, आपके संभावित एनम का सेट 254 से 259 तक फैलता है, तो आपको अचानक एक के बजाय प्रत्येक एन्यूम मान के लिए 2 बाइट्स की आवश्यकता होती है। यह सभी जगह संरचना और वर्ग लेआउट को तोड़ सकता है, इसलिए पहले डिज़ाइन में पर्याप्त आकार का उपयोग करके इससे बचने की कोशिश करें। सी ++ 11 आपको यहां बहुत नियंत्रण देता है, लेकिन अन्यथा एक प्रविष्टि LAST_SPECIES_VALUE=65535को निर्दिष्ट करने में भी मदद करनी चाहिए।

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.