2010-01-21 26 views
33

मैंने हाल ही में जावा कोडिंग का एक गुच्छा किया है और गहरे घोंसले के साथ, बहुत विशिष्ट पैकेज नामकरण सिस्टम के लिए उपयोग किया है। com.company.project.db। यह जावा, एएस 3/फ्लेक्स और सी # में ठीक काम करता है। मैंने सी ++ में भी वही प्रतिमान लागू किया है, लेकिन मैंने यह भी सुना है कि सी ++ नेमस्पेस को जावा पैकेजों के प्रत्यक्ष समकक्षों के रूप में देखना बुरा है।सी ++ नेमस्पेस, जावा पैकेज की तुलना

क्या यह सच है, और क्यों? नामस्थान/पैकेज समान और अलग कैसे हैं? यदि आप गहरे घोंसले वाले नामस्थानों का उपयोग करते हैं तो क्या समस्याएं देखी जा सकती हैं?

+0

क्या लाभ (रों) आप गहराई से नेस्टेड नामस्थान का उपयोग करने में देखते हैं? –

+0

जावा, एएस 3, सी # जैसी किसी भी अन्य भाषा में जैसा ही है ... मुझे आपके प्रश्न का बिंदु नहीं दिख रहा है। –

+1

मेरा मुद्दा यह है कि मैं कोई भी नहीं देख सकता, और यह जानना चाहूंगा कि एक स्पष्ट प्रशंसक उनके बारे में क्या उपयोगी पाता है। –

उत्तर

23

सी ++ नामस्थान में उपलब्ध नामों को विभाजित करने के बारे में हैं। जावा पैकेज मॉड्यूल के बारे में हैं। नामकरण पदानुक्रम इसका एक पहलू है।

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

सी ++ नामस्थानों के लिए अतिरिक्त नियम भी हैं जो अधिक उपयोग किए जाने पर आपको पकड़ सकते हैं - जैसे कि argument-dependent-lookup, और माता-पिता के स्तर को हल करने के नियम। बाद में डब्लूआरटी, ले लें:

namespace a{ namespace b{ int x; } } 
namespace b{ string x; } 
namespace a 
{ 
    b::x = 42; 
} 

क्या यह कानूनी है? क्या यह स्पष्ट है कि क्या हो रहा है? आपको उन सवालों के जवाब देने के लिए नेमस्पेस रिज़ॉल्यूशन की सटीकता जानने की आवश्यकता है।

+1

दिलचस्प। क्या आप "आश्रित-लुकअप" और "पैरेंट स्तर को हल करने" के बारे में कुछ लिंक जोड़ सकते हैं? कभी नहीं सुना। – sleske

+1

@sleske - वहां जाएं – philsquared

+4

@sleske: पूर्ण स्पष्टीकरण एक टिप्पणी में वास्तव में क्या लिख ​​सकता है उससे काफी लंबा है। बुनियादी विचार यह है कि जब संकलक को गैर-पूर्ण-योग्य पहचानकर्ता मिल जाता है तो यह वर्तमान नामस्थान से शुरू होने का मिलान करने का प्रयास करेगा, और यदि नहीं मिला तो यह संलग्न नामस्थान ... रूट के लिए सभी तरह से प्रयास करेगा। यह एडीएल (तर्क आश्रित लुकअप) द्वारा बढ़ाया जाता है, ताकि यदि आप तर्कों के एक सेट पर फ़ंक्शन को कॉल करते हैं, तो यह तर्क नामों में विधि पहचानकर्ता से मिलान करने का भी प्रयास करेगा। 'एफ (std :: string(), :: ns :: myclass())' 'st'' और' ns' नेमस्पेस में 'f' भी देखेंगे। –

17

जावा पैकेज घोंसला नहीं हैं, वे फ्लैट हैं। किसी भी स्पष्ट घोंसले नामकरण सम्मेलन से ज्यादा कुछ नहीं है।

उदाहरण के लिए, पैकेज com.company.project.dbcom.company.project या com.company.project.db.x पर कोई संबंध नहीं है। com.company.project.db में कोड a.b.c में कोड की तुलना में com.company.project.db.x में कोड तक पहुंच नहीं है।

+0

दिलचस्प, मैंने कभी इसके बारे में सोचा नहीं था लेकिन माना जाता है कि पैकेज-स्तरीय दायरा/दृश्यता सब-पैकेज पर लागू होगी। तो a.b.c में एक पैकेज स्तर वर्ग a.b.c.d के लिए अदृश्य है? –

+0

बीटीडब्ल्यू, जावा फ़ाइल संरचना में घोंसले को लागू करता है, है ना? आपका मतलब क्या नहीं था, लेकिन अभी भी महत्वपूर्ण है ... जावा पैकेज मनमाने ढंग से पाठ नहीं हैं जो आप टाइप कर सकते हैं (आईआईआरसी) –

+1

@ जॉन: आपके पहले बिंदु पर: सही।आपके दूसरे बिंदु पर, जावा उपकरण आम तौर पर एक निर्देशिका संरचना को लागू करते हैं जो पैकेज नामकरण की तरह दिखता है, हां, लेकिन फिर, यह एक मजबूत व्यक्ति के बावजूद एक सम्मेलन से अधिक कुछ नहीं है। – skaffman

0

आप सी ++ में नेस्टेड नेमस्पेस रख सकते हैं।

वे जावा में उतना ही काम नहीं करते हैं, हालांकि जाहिर है। जावा पैकेज वास्तव में बहुत बेहतर परिभाषित हैं और कोई असली स्थिर इनिट अजीबता नहीं है। सी ++ नेमस्पेस के साथ मददगार हैं लेकिन अभी भी इसमें काफी खतरे शामिल हैं।

+7

कृपया इस "खतरे" का उल्लेख करें जिसे आप उल्लेख करते हैं। –

0

सी ++ में, डिजाइन और कार्यान्वयन की मूल इकाई कक्षा है, नामस्थान नहीं। नामस्थानों को बड़े पुस्तकालयों में नाम संघर्षों को रोकने के साधनों के रूप में इरादा किया गया था, अवधारणाओं को व्यक्त करने के लिए नहीं।

क्लासेस नामस्थान से अधिक कई फायदे हैं:

  • वे निर्माणकर्ता और विनाशकर्ता हो सकता है
  • वे निजी सदस्यों
  • वे नहीं फिर से खोला जा सकता है

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

+1

मुझे लगता है कि आप गलत इकाइयों की तुलना कर रहे हैं। पैकेज कक्षाओं की तुलना में सी ++ में हेडर फ़ाइलों की तरह अधिक हैं। सी और सी ++ में मॉड्यूलरिटी की मूल इकाई हेडर फाइलें और संकलन इकाइयां हैं, कक्षाएं नहीं। –

+1

"उन्हें फिर से खोला नहीं जा सकता" - कुछ लोग एक नुकसान के रूप में देखेंगे ;-) – philsquared

+0

@ कोनराड - मैं मॉड्यूल के साथ हेडर फ़ाइलों की तुलना करने के बारे में सावधान रहूंगा। शीर्षलेख फ़ाइलें बहुत पहले प्रोसेसर चीज हैं। यदि कुछ भी निकटतम संबंधित इकाई है तो हमारे पास अभी अनुवाद इकाई (सीपीपी फ़ाइल) है - हालांकि प्रतीक * आमतौर पर हेडर फाइलों के माध्यम से निर्यात किए जाते हैं - लेकिन यह एक आवश्यकता नहीं है – philsquared

0

मैं कुछ चीजों में फेंक दूंगा जो मैंने सुना है लेकिन सच्चाई को नहीं जानते हैं, कृपया पुष्टि/उन्हें हटाने में मदद करें।

  1. सी ++ प्रदर्शन (किसी भी तरह) है लंबे समय तक पूरी तरह से निर्दिष्ट विधि के नाम जैसे से प्रभावित namespace1::namespace2::namespace3::classX::method123()

  2. आप संकलक/लिंकर

+3

1) नहीं - नामस्थान पूरी तरह से संकलित-समय की चीज हैं। 2) संभव - लेकिन अधिकांश सी ++ कंपाइलर्स बहुत लंबे नामों का समर्थन करते हैं - उन्हें करना है, या टेम्पलेट काम नहीं करेंगे। –

+0

मैं दोनों गिनती पर नील को वापस देखूंगा और जोड़ सकता हूं कि पूरे योग्य पदानुक्रम के लिए प्रतीक लंबाई सीमा * प्रति नामस्थान * होने की संभावना है। – philsquared

+0

यहां तक ​​कि जब आप मिश्रण में आरटीटीआई फेंकते हैं? –

0

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

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

1) बेस विजेट कक्षा संपादित करें? ठीक है, लेकिन सबसे अधिक संभावना है कि आपके पास इसका उपयोग नहीं है। हो सकता है कि एक लाइसेंसिंग समस्या है जो आपको अपना संशोधन करने से रोकती है। यहां तक ​​कि यदि आप ऐसा कर सकते हैं, भले ही यह कुछ ऐसा हो जो केवल आपके प्रोजेक्ट के लिए समझ में आता है, लेखकों को इसे अपनी भविष्य की रिलीज में शामिल नहीं किया जाएगा, और टूलकिट को अपग्रेड करना अधिक दर्दनाक होगा

2) एक इंटरफ़ेस क्लास/बहु विरासत? आपके मौजूदा कोड के आधार पर यह विजेट से संबंधित प्रत्येक वर्ग को अद्यतन करने के लिए दर्द का अधिक या कम होगा। ऐसा करें और आपके कोड को बनाए रखने के लिए और अधिक खर्च आएगा क्योंकि प्रत्येक व्यक्ति को एक नई कक्षा को परिभाषित करने के बारे में पता होना चाहिए कि वे आपके इंटरफ़ेस से प्राप्त होने का अनुमान लगाते हैं। अन्य लोगों के अनुशासन पर निर्भर होना वास्तव में जोखिम भरा है।

सी ++ नामस्थानों की अद्भुत बात यह है कि आपके पास पहले से मौजूद सिस्टम में सामग्री को समाहित करने का एक अतिरिक्त तरीका है। न केवल आप पहले से मौजूद मौजूदा पुस्तकालयों में encapsulate कर सकते हैं जिन्हें आप संपादित नहीं कर सकते हैं, आप समान अवधारणाओं को समाहित कर सकते हैं जिन्हें आप कक्षाओं/वस्तुओं के अपने पदानुक्रम में आसानी से सम्मिलित नहीं कर सकते हैं।

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

0

यहां कुछ कारण हैं कि क्यों और कैसे सी ++ नेमस्पेस जावा या सी # नामस्थान से अलग हैं।

बचना संघर्ष

जावा/सी # भाषाओं में, नामस्थान वर्ग पुस्तकालयों के विभिन्न भागों में नामों के बीच संघर्ष से बचने के लिए लक्षित हैं। आपके पास सी # में नेमस्पेस पदानुक्रम में 5 अलग-अलग स्थानों में "वॉचर" नामक कक्षा हो सकती है। सी ++ में, यदि आपके पुस्तकालय में होने वाले समान नाम वर्ग हैं तो आप नेमस्पेस बनाने के बजाय एक और कक्षा के अंदर डालते हैं। इस तरह के घोंसले वर्ग सभी ठीक और प्रोत्साहित होते हैं और वास्तव में सिंटैक्स भी इस तरह व्यवहार करता है जैसे कक्षा :: ऑपरेटर का उपयोग कर नामस्थान है।

कितने नेस्टेड नेमस्पेस होना चाहिए?

बूस्ट, ईजिन और निश्चित रूप से लोकप्रिय पुस्तकालयों, एसटीएल अच्छे उदाहरण प्रदान करता है। इन पुस्तकालयों में आम तौर पर std:: या boost:: या eigen:: जैसे नामस्थान में भरवां सब कुछ बहुत अधिक है। कुछ घटकों को अपना नामस्थान std::ios या boost:filesystem मिलता है। दूसरे स्तर का उपयोग करने के दौरान चारों ओर कोई निरंतर नियम नहीं है लेकिन ऐसा लगता है कि बड़े या अलग से विकसित/बनाए रखा या वैकल्पिक घटकों को आम तौर पर अपना नामस्थान मिलता है। तीसरा स्तर और भी दुर्लभ है।आम तौर पर मैं company::project संरचना का उपयोग करता हूं और company::project::component परियोजनाओं के बड़े स्वतंत्र रूप से उपयोग योग्य उपप्रणाली के लिए। बाहरी पुस्तकालयों

में

बचना संघर्ष अब बड़ा सवाल: क्या होगा यदि आप प्राप्त दो अलग अलग लोगों को जो ठीक उसी नामस्थान और वर्ग हैं से दो पुस्तकालयों? यह स्थिति काफी दुर्लभ है क्योंकि ज्यादातर लोग अपने पुस्तकालयों को कम से कम अपने प्रोजेक्ट के नाम में लपेटते हैं। यहां तक ​​कि अगर परियोजना के नाम समान हैं, तो यह भी दुर्लभ है कि आप दोनों से पुस्तकालयों का उपयोग करते हैं। हालांकि कभी-कभी परियोजना के नामों के लिए बुरे निर्णय किए जाते हैं (आह ... "मेट्रो", "अपोलो" ...) या यहां तक ​​कि नेमस्पेस का भी उपयोग नहीं किया जाता है। यदि ऐसा होता है, तो आप किसी नाम या दोनों पुस्तकालयों के लिए नामस्थान में शामिल नहीं करते हैं और संघर्ष हल हो जाता है! यह एक कारण है कि लोग विवादों के बारे में ज्यादा परेशान नहीं करते हैं क्योंकि उन्हें हल करना तुच्छ है। यदि आप company::project का उपयोग करने के अभ्यास का पालन करते हैं तो संघर्ष सुपर दुर्लभ हो जाते हैं। भाषाओं

हालांकि सी ++ जैसे सी # using namespace बयान प्रदान करता है में

अंतर, अपनी आम तौर पर माना जाता है एक बुरा व्यवहार अपने खुद के नाम स्थान में "आयात" सब कुछ करने के लिए। इसका कारण यह है कि एक शीर्षलेख में बहुत सारी "बुरी" चीजें हो सकती हैं जिनमें चीजों को फिर से परिभाषित करना शामिल है जो आपको पूरी तरह से आश्चर्यचकित कर सकता है। यह सी #/जावा के विपरीत है जहां आप केवल using namespace के बराबर करते हैं तो आपको केवल सार्वजनिक सार्वजनिक इंटरफ़ेस मिलता है। (साइड नोट: सी ++ में आप पिंपल पैटर्न का उपयोग कर एक ही चीज़ प्राप्त कर सकते हैं लेकिन आमतौर पर इसके अतिरिक्त नलसाजी और कुछ पुस्तकालय वास्तव में ऐसा करते हैं)। तो आप लगभग using namespace नहीं करना चाहते हैं। इसके बजाय आप typedefs (या using name =) जो वास्तव में उपयोग करना चाहते हैं उसके लिए करते हैं। यह फिर से उपयोग करने के लिए अव्यवहारिक गहराई से घोंसला नामस्थान बनाता है।

आयोजन कोड

जावा/सी # में, लोगों को एक बहुत फ़ोल्डर में कोड को व्यवस्थित करने के लिए जाते हैं। आम तौर पर फ़ोल्डर 20 से अधिक या यहां तक ​​कि 10 फाइलें बढ़ता है, लोग फ़ोल्डर के बारे में सोचना शुरू कर देंगे। सी ++ में, चीजें more diverse हैं लेकिन कई बड़ी परियोजनाओं के लिए चापलूसी निर्देशिका संरचनाओं को प्राथमिकता दी जाती है। उदाहरण के लिए, मानक लाइब्रेरी के std folder में 53 फाइलें हैं और फेसबुक की folly प्रोजेक्ट एक ही मार्ग पर प्रतीत होता है। मुझे लगता है कि इसके लिए एक कारण यह है कि जावा/सी # लोग दृश्य आईडीई का अधिक उपयोग करते हैं और कंसोल के विपरीत फ़ोल्डर नेविगेशन में माउस स्क्रॉल का उपयोग करते हैं जहां आप फ्लैट संरचना में फ़ाइल ढूंढने के लिए वाइल्ड कार्ड्स का उपयोग कर सकते हैं। इसके अलावा सी ++ प्रोग्रामर पूरी तरह से एकल कक्षा में एकाधिक वर्गों को डालने और सी # या जावा के विपरीत वर्ग नाम के बजाए लॉजिकल यूनिट के रूप में नामकरण फ़ाइल को दूर करने से दूर नहीं हैं। यह संकलन तेजी से बनाता है जो बड़ी परियोजनाओं के लिए बहुत महत्वपूर्ण है। हालांकि प्रत्येक फ़ोल्डर के लिए अपना नामस्थान रखने के लिए भाषा-स्तर की आवश्यकता नहीं है, कई सी ++ डेवलपर प्रत्येक फ़ोल्डर में अपना नामस्थान निर्दिष्ट करना पसंद करते हैं और फ़ोल्डर पदानुक्रम 2 या उससे कम स्तर को गहरा रखते हैं।

संभावित अपवाद

C++ में आप A::B::C::D का उल्लेख कर सकते के रूप में सिर्फ C::D आप पहले से ही A::B अंदर कर रहे हैं। इसलिए यदि आपके पास निजी कोड या कम इस्तेमाल किए जाने वाले वर्ग हैं जिन्हें आप आगे धक्का देना चाहते हैं तो आप अपनी खुद की सापेक्ष गहराई को 2 या उससे भी कम रखते हुए ऐसा कर सकते हैं। इस मामले में, आप प्रत्येक स्तर के लिए फ़ोल्डर भी बनाना चाहते हैं, इसलिए फ़ाइल स्थान अनुमानित हैं। आम तौर पर, इस क्षेत्र में कोई स्वर्ण मानक नहीं है लेकिन आप सी #/जावा की नकल करने वाले गहरे घोंसले वाले नामस्थानों के साथ ओवरबोर्ड नहीं जाना चाहते हैं।

संबंधित

संबंधित मुद्दे