क्या कुछ मूल्यों को तार के रूप में संग्रहित करना बुरा है?


19

यह बहुत ही अस्पष्ट शीर्षक है लेकिन मैं इसे बेहतर तरीके से सोच भी नहीं सकता। लेकिन, सिर्फ एक उदाहरण के रूप में, उस दिशा के बारे में सोचें जो किसी खेल में एक चरित्र की ओर बढ़ रहा है। यह सिर्फ एक स्ट्रिंग का उपयोग करने और फिर चीजों को करने में गलत लगता है if(character.direction == "left")। यह मुझे लगता है कि यह मूर्खतापूर्ण त्रुटियों के लिए बहुत अधिक जगह छोड़ देता है, जैसे गलती Leftसे lया इसके बजाय जो भी हो left। क्या मेरा शक सही है? यदि हां, तो ऐसा कुछ हासिल करने का पसंदीदा तरीका क्या है?


10
यदि आपकी भाषा उन लोगों का समर्थन करती है, तो इसके अलावा आपका मतलब क्या है?
हॉफमैल



कुछ भाषाएं स्ट्रिंग्स के अलावा अन्य मूल्यों को स्टोर करने में सक्षम नहीं हैं, उदाहरण के लिए bash
मौविसील

पता नहीं क्यों लेकिन मुझे सी में "परिभाषित" याद आया। आप इस तरह की बातें कर सकते हैं: # झूठे सच
linuxunil

जवाबों:


28

यदि आप जिस भाषा का उपयोग कर रहे हैं, वह enums के उपयोग का समर्थन करती है, तो मैं उनका उपयोग करूँगा। यह आपको दिए गए प्रकार के लिए उपलब्ध विकल्पों की संख्या को सीमित करने की अनुमति देता है। जावा में जैसे:

public enum Direction {
    LEFT,
    RIGHT,
    UP,
    DOWN
}

2
यह जवाब ओपी समस्या को समझने में योगदान नहीं करता है; मैं यहाँ कोई तर्क नहीं देखता हूँ, केवल एक राय जो कि भाषाओं की श्रेणी में सीमित है enumजैसे जावा। कई भाषाओं (जैसे वीबीए) के पास है enum, लेकिन यह सबसे अच्छा विकल्प नहीं हो सकता है क्योंकि इसमें भविष्य में समान-प्रमाण का अभाव है। enumअकेले कुछ अधूरा, अक्सर भंगुर और भाषा-विशिष्ट समाधान क्यों है, इसकी चर्चा के लिए मेरा जवाब देखें ।
6

12

कोड में शाब्दिक तार (या जादुई संख्या) का उपयोग करना भयानक अभ्यास है।

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

const string LEFT = "left"
if (someThing == LEFT) { doStuff(); }

इस सरल स्विच के इतने सारे फायदे हैं कि मुझे यह भी पता नहीं होगा कि उन्हें कहाँ से समझाना है (कम से कम बिना कुछ अधिक कॉफी के)। मैजिक नंबरों पर पढ़ें, यह एक ही सटीक अवधारणा है, केवल एक स्ट्रिंग मान के बजाय एक संख्या मान पर लागू होता है।

यहां एक त्वरित रेफरी है, मुझे यकीन है कि सैकड़ों और भी हैं: /programming/47882/what-is-a-magic-number-and-why-is-it-bad


1
इस दृष्टिकोण के साथ मुझे जो समस्या है वह यह है कि आपको टाइपो-बग मिलते हैं - जैसे कि स्ट्रिंग LEFT = "लेटफ" - जबकि अगर आप ऐसे एनम के साथ काम करते हैं जो संकलन के समय पकड़े जाते हैं।
पीटर बी

@PieterB - मुझे लगा कि OPs प्रश्न काफी व्यापक था, और "बाएं" के लिए उदाहरण सिर्फ एक मनमाना उदाहरण है - जहां सभी मामले एक एनम से मेल नहीं खाते। मैं मानता हूं कि विशेष रूप से निर्देशों के एक सेट के लिए, एक एनम सबसे अच्छा विकल्प है, लेकिन मेरा जवाब उस में और अधिक सामान्य होना था "अगर आप इसे शाब्दिक रूप में रखते हैं, तो कम से कम इसे एक स्थिर बनाएं" (enums, ज़ाहिर है,) एक प्रकार का स्थिर होना)
jleach

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

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

4

संक्षिप्त उत्तर: हां, तार किसी भी कार्य के लिए आदर्श नहीं होते हैं, इसके अलावा पाठ पात्रों के एक क्रम को संग्रहीत करना और पहुंचना, और यहां तक ​​कि अगर एक अमूर्त के अंतर्निहित टुकड़े तार होते हैं, तो उन्हें चर या स्थिरांक के रूप में संदर्भित करने के लाभ हैं

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

left = "left";

या इसके समतुल्य, इसके स्ट्रिंग के उपयोग के फायदे हैं जब आप इसे अपने कोड में संदर्भित करते हैं। उदाहरण के लिए,

if (player.direction == Left)

एक संकलन-समय त्रुटि (सबसे अच्छा मामला, जावा और इस तरह) का पता लगाया जाएगा या किसी भी आईडीई द्वारा उसके बिट्स को गलत (सबसे खराब मामला, बुनियादी और इस तरह) के रूप में चिह्नित किया जाएगा।

इसके अलावा, leftएक रेफरेंसेबल इकाई के रूप में धारणा होने से आपको उस दिशा के प्रकार के साथ जाने के लिए जो भी दिशा तय करने में मदद मिलेगी। का उपयोग करके "left", दिशा एक होने के लिए प्रतिबद्ध है String। यदि आप पाते हैं या प्रकार के लिए एक बेहतर अमूर्तता बनाते हैं, तो आपको अपने पूरे कोड बॉडी के माध्यम से हर उदाहरण को बदलते हुए शिकार पर जाने की आवश्यकता है "left"। यदि किसी प्रकार को विस्तृत किया जाता है, तो एक स्थिर या चर को किसी भी बदलाव की आवश्यकता नहीं होगी।

वह प्रकार जो आप वास्तव में चाहते हैं, विशेष रूप से आपके डोमेन के लिए है। आपका कोड आपके साथ क्या करने की योजना बना रहा है left? शायद आप एक बनावट के एक्स अक्ष को दर्पण करना चाहेंगे या बाईं ओर का सामना करना पड़ रहा है या आगे बढ़ना चाहते हैं; यदि ऐसा है, तो आप leftएक संपत्ति या विधि के साथ एक वस्तु बनाना चाह सकते हैं जो उस व्यवहार को दर्शाती है, जिसमें आपकी rightवस्तु विपरीत गैर-प्रतिबिंबित परिणाम है। आप उस तर्क को उस वस्तु में कर सकते हैं जो स्प्राइट्स या बनावट का प्रतिनिधित्व करता है, जिस स्थिति में आप ऊपर बताए गए कारणों के "left"बजाय उपयोग करने के leftलिए फिर से पीड़ित होंगे ।

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


2

आपने अपनी भाषा निर्दिष्ट नहीं की, लेकिन एक सामान्य उत्तर देने के लिए, आपको स्ट्रिंग का उपयोग करना चाहिए जब आपको वास्तव में पाठ की आवश्यकता होती है, न कि किसी चीज़ का प्रतिनिधित्व करने के लिए। उदाहरण के लिए आपने जो उदाहरण दिया है वह उत्पादन सॉफ्टवेयर में स्वीकार्य नहीं होगा।

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

जैसा कि यह सुझाव दिया गया है, यदि आपकी भाषा अनुमति देती है तो गणना का उपयोग करें। आपके विशिष्ट उदाहरण में, यह स्पष्ट रूप से बेहतर विकल्प है।


गति और मेमोरी के मायने नहीं हैं। उस ने कहा, enums या स्थिरांक पसंद करते हैं। स्ट्रिंग अधिक समझ में आता है अगर डेटा एक पाठ प्रारूप से आ रहा है, जैसे XML, लेकिन फिर भी सभी कैप, या सभी अनसैप्स के अनुरूप होना चाहिए। या, हमेशा कन्वर्ट , ई जी। if (uppercase(foo) == "LEFT")
user949300

2
@ user949300 सभी अपरकेस या सभी लोअरकेस में तार बदलना विश्वसनीय भी नहीं है। ऐसी संभावना है कि कोई व्यक्ति तुर्की की तरह किसी अन्य लोकल (या वहां व्यापार का विस्तार) का दौरा करने का फैसला कर सकता है , और भोली ऊपरी आवरण (या कम आवरण) स्ट्रिंग तुलनाओं को तोड़ सकता है।
8bittree

गति और स्मृति की देखभाल हमेशा अच्छा अभ्यास है, वे अनंत संसाधन नहीं हैं। हालाँकि यह पठनीयता या कुछ अन्य व्यापार-बंद के लिए जानबूझकर बलिदान करने के लिए ठीक है, जो यहाँ नहीं है। लेकिन उनके बारे में परवाह नहीं करना आसानी से सुस्त या बेकार अनुप्रयोगों को जन्म दे सकता है।
नागदेव

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

1

बस डेटा प्रकार का उपयोग करें जो आपकी स्थिति में समझ में आता है।

stringएक अंतर्निहित अंतर / इंट्रा-एप्लिकेशन संचार के रूप में प्रकार का उपयोग स्वाभाविक रूप से एक समस्या नहीं है। वास्तव में, कभी-कभी स्ट्रिंग्स का उपयोग करना बेहतर होता है: यदि आपके पास एक सार्वजनिक एपीआई है, तो यह मानव-पठनीय होने के लिए एपीआई के अंदर और बाहर जाने वाले मूल्यों के लिए वांछनीय हो सकता है। यह सीखने और डीबग करने के लिए आपके API का उपयोग करने वाले लोगों के लिए आसान बनाता है।

आपके कोड के साथ असली समस्या मूल्य को दोहराने में है।

ऐसा न करें:

if (direction == 'left') {
  goLeft();
}

यदि आपने इन शर्तों में से किसी एक में एक टाइपो या "वाम" के अन्य उपयोग किए हैं, तो आप इसके लिए कोडबेस-वाइड खोज को प्रभावी ढंग से करने में असमर्थ हो सकते हैं, क्योंकि आपने इसे गलत माना है!

इसके बजाय, एक एन्यूमरेशन या एक स्थिरांक के विरुद्ध कोड - जिसके आधार पर आप जिस भाषा (भाषाओं) का उपयोग कर रहे हैं, उस डेटा प्रकार का समर्थन करता है।

इसका मतलब आपके आवेदन में एक बार और केवल एक बारLEFT सौंपा जाना चाहिए । और, आपके बाकी कोड को उन एनमों या स्थिरांक का लाभ उठाना चाहिए:

const string LEFT = "left";

if (direction == LEFT) {
  goLeft();
}

यदि आप ऐसा चुनते हैं तो यह आपको बाद में अपनी दिशाओं के लिए आपके द्वारा उपयोग किए जाने वाले डेटा प्रकार को और अधिक आसानी से बदलने की अनुमति देता है।


1

क्या यह बुरा अभ्यास है?

शायद हाँ, लेकिन यह ठीक उसी पर निर्भर करता है जो आप कर रहे हैं, और उस प्रोग्रामिंग भाषा पर भी जिसका आप उपयोग कर रहे हैं।

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

  • एक enumप्रकार बेहतर होगा, यदि आपकी प्रोग्रामिंग भाषा इस बात का समर्थन करती है।
  • अन्यथा, नामित पूर्णांक स्थिरांक जाने का मार्ग है, स्थिरांक के लिए एकल परिभाषा के साथ।

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

इस तरह के परिदृश्य में एक और समाधान की आवश्यकता हो सकती है, और स्ट्रिंग्स का उपयोग करना एक विकल्प है। (और आप स्ट्रिंग शाब्दिक और नामांकित स्थिरांक को जोड़ सकते हैं ... यदि परिदृश्य डायनेमिक एक्सटेंशन के साथ एक निश्चित कोर को जोड़ता है।)


यदि आप जावा में लागू कर रहे हैं, character.direction == "left"तो किसी अन्य कारण से खराब अभ्यास है। आपको ==स्ट्रिंग्स की तुलना करने के लिए उपयोग नहीं करना चाहिए , क्योंकि यह स्ट्रिंग समानता के बजाय ऑब्जेक्ट आइडेंटिटी का परीक्षण कर रहा है। (यह काम करेगा अगर आप गारंटी दे सकते हैं कि "left"स्ट्रिंग के सभी उदाहरणों को नजरबंद कर दिया गया है, लेकिन इसके लिए संपूर्ण-एप्लिकेशन विश्लेषण की आवश्यकता है।)


1
ऐसा लगता है कि हमेशा के लिए तय हो गया है जो अक्सर तय नहीं होता है। उदाहरण के लिए चार दिशाएं आठ हो सकती हैं।
जिमी टी।

@JimmyT। - यह संदर्भ पर निर्भर करता है। उदाहरण के लिए, एक खेल में, एक वर्ण को 4 से 8 तक ले जाने वाली दिशाओं की संख्या को बदलने से खेल नियमों का एक पूरा ओवरहाल हो जाएगा, और नियमों को लागू करने वाला कोड। Stringदिशाओं का प्रतिनिधित्व करने के लिए उपयोग करने से परिवर्तनों को शामिल करने के लिए काम की मात्रा के करीब शून्य अंतर होगा। एक और अधिक समझदार दृष्टिकोण मानते हैं कि निर्देशों की संख्या में परिवर्तन नहीं होगा, और स्वीकार करते हैं कि आप क्या करना बहुत काम होता है किसी भी तरह से करता है, तो खेल के नियम तो मौलिक रूप से बदल दिया है।
स्टीफन सी

@JimmyT - पूरी तरह से सहमत Ive को कई बार ऐसा होता देखा गया है, आप भी डेवलपर्स को स्ट्रिंग को पुनर्परिभाषित करने के लिए शॉर्ट कट लेते हैं, उदाहरण के लिए, उत्पाद = "विकल्प" उत्पाद बन जाता है = "Option_or_Future" पूरी तरह से कोड के अर्थ को नष्ट कर देता है।
क्रिस मिलबर्न

-3

जैसा कि सुझाव दिया गया है, आपको एनम का उपयोग करना चाहिए। हालाँकि, केवल Enign का उपयोग Strigns के प्रतिस्थापन के रूप में पर्याप्त IMHO नहीं है। आपके कण उदाहरण में, खिलाड़ी का वेग वास्तव में भौतिकी के माध्यम से एक वेक्टर होना चाहिए:

class Vector {
  final double x;
  final double y;
}

इस वेक्टर का उपयोग तब प्रत्येक टिक को प्लेयर की स्थिति को अपडेट करने के लिए किया जाना चाहिए।

फिर आप इसे उच्च पठनीयता के लिए एक एनुम के साथ जोड़ सकते हैं:

enum Direction {
  UP(new Vector(0, 1)),
  RIGHT(new Vector(1, 0)),
  DOWN(new Vector(0, -1)),
  LEFT(new Vector(-1, 0));

  private Vector direction;

  Direction(Vector v) {
    this.direction = v;
  }

  public Vector getVector() { return this.direction; }
}

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