क्या हेडर फाइलें वास्तव में अच्छी हैं? [बन्द है]


20

मुझे सी ++ स्रोत फ़ाइलों को ब्राउज़ करते समय हेडर फाइलें उपयोगी लगती हैं, क्योंकि वे एक कक्षा में सभी फ़ंक्शन और डेटा सदस्यों का "सारांश" देते हैं। अन्य कई भाषाओं (जैसे रूबी, पायथन, जावा, आदि) में इस तरह की सुविधा क्यों नहीं है? क्या यह ऐसा क्षेत्र है जहाँ C ++ की वाचालता काम आती है?


मैं C और C ++ में उपकरणों से परिचित नहीं हूं, लेकिन अधिकांश आईडीई / कोड संपादकों को मैंने "संरचना" या "रूपरेखा" दृश्य के रूप में काम किया है।
माइकल के

1
हेडर फाइलें अच्छी नहीं हैं - वे आवश्यक हैं! - एसओ पर यह जवाब भी देखें: stackoverflow.com/a/1319570/158483
पीट

जवाबों:


31

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

C ++ हेडर फ़ाइलों को रखने के लिए आवश्यक सी के साथ पीछे की ओर संगत है, लेकिन उनमें से बहुत से जोड़े गए, जिसके परिणामस्वरूप काफी समस्याग्रस्त डिजाइन हुआ। एफक्यूए में अधिक ।

मॉड्यूलरिटी के लिए, मॉड्यूल में कोड के बारे में मेटाडेटा के रूप में हेडर फ़ाइलों की आवश्यकता थी। उदाहरण के लिए। क्या तरीके (और सी ++ कक्षाओं में) किस पुस्तकालय में उपलब्ध हैं। डेवलपर का यह लिखना स्पष्ट था, क्योंकि संकलन का समय महंगा था। आजकल, यह संकलक कोड से ही मेटाडेटा उत्पन्न करने के लिए कोई समस्या नहीं है। जावा और .NET भाषाएँ सामान्य रूप से ऐसा करती हैं।

तो नहीं। हैडर फाइलें अच्छी नहीं हैं। वे तब थे जब हमें अलग-अलग फ्लॉपी पर कंपाइलर और लिंकर रखना पड़ा और संकलन में 30 मिनट लगे। आजकल, वे केवल रास्ते में आते हैं और खराब डिजाइन के संकेत हैं।


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

3
@ होंक यही मेरे सवाल के साथ मिल रहा था। लेकिन मुझे लगता है कि आधुनिक IDEs (जैसा कि एल्युसुबोव ने सुझाव दिया है) इस तरह की उपेक्षा करते हैं।
मैट फिकमैन

5
आप जोड़ सकते हैं कि C ++ समिति मॉड्यूल पर काम कर रही है जो C और C ++ को बिना किसी हेडर या अधिक कुशल तरीके से उपयोग किए हेडर के साथ काम करने में सक्षम बनाएगा। इससे यह उत्तर और अधिक उचित होगा।
प्रात: काल

2
@ मट्टफिचमैन: कुछ हेडर फाइल बनाना एक बात है (जो कि ज्यादातर प्रोग्रामर के संपादक / आईडीई अपने आप किसी तरह से कर सकते हैं), लेकिन एक सार्वजनिक एपीआई के बारे में यह बात है कि इसे प्रभावी ढंग से परिभाषित करने और वास्तविक मानव द्वारा डिजाइन करने की आवश्यकता है।
बेंजामिन बैनियर

2
@ हाँक। लेकिन इसके अलग-अलग फाइलों में परिभाषित होने का कोई कारण नहीं है। यह कार्यान्वयन के समान कोड में हो सकता है। जैसे C # कर रहा है।
वृहस्पति

17

यद्यपि वे आपके लिए दस्तावेज़ के रूप में उपयोगी हो सकते हैं, हेडर फ़ाइलों के आसपास की प्रणाली असाधारण रूप से अक्षम है।

सी को डिज़ाइन किया गया था ताकि प्रत्येक संकलन पास एक एकल मॉड्यूल का निर्माण करे; प्रत्येक स्रोत फ़ाइल संकलक के एक अलग रन में संकलित की जाती है। दूसरी ओर हैडर फाइलें, प्रत्येक संकलित फ़ाइल के लिए उस संकलन चरण में इंजेक्ट की जाती हैं जो उन्हें संदर्भित करता है।

इसका मतलब है कि यदि आपकी हेडर फ़ाइल 300 स्रोत फ़ाइलों में शामिल है, तो यह आपके प्रोग्राम के निर्माण के दौरान 300 से अधिक बार पार्स और संकलित हो जाती है। ठीक उसी परिणाम के साथ एक ही बात, बार-बार। यह समय की एक बड़ी बर्बादी है, और C और C ++ प्रोग्राम बनाने में प्राथमिक कारणों में से एक है।

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

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

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


5
कड़ाई से सच नहीं है - अधिकांश, यदि सभी नहीं, हेडर को पूर्व-संकलित करते हैं क्योंकि वे उन्हें देखते हैं तो उन्हें अगले संकलन इकाई में शामिल करना पूर्व संकलित कोड के ब्लॉक को खोजने से भी बदतर नहीं है। इसका कोई अलग से कहना, .NET कोड बार-बार 'बिल्डिंग' system.data.types जो आपके द्वारा संकलित प्रत्येक C # फ़ाइल के लिए है। C / C ++ प्रोग्राम को इतना लंबा होने का कारण यह है क्योंकि वे वास्तव में संकलित (और अनुकूलित) हैं। सभी .NET प्रोग्राम जरूरतों को IL में पार्स किया जाना है, रनटाइम JIT के माध्यम से वास्तविक संकलन करता है। उस ने कहा, सी # कोड में 300 स्रोत फ़ाइलों को भी संकलन करने में काफी समय लगता है।
gbjbaanb

7

यह स्पष्ट नहीं है कि फ़ंक्शन और डेटा सदस्यों के लिए फ़ाइल ब्राउज़ करने से आपका क्या मतलब है। हालाँकि, अधिकांश IDE वर्ग को ब्राउज़ करने और वर्ग डेटा सदस्यों को देखने के लिए उपकरण प्रदान करते हैं।

उदाहरण के लिए: विजुअल स्टूडियो के पास Class Viewऔर Object browserवह अच्छी तरह से आपकी अनुरोधित कार्यक्षमता प्रदान करता है। निम्न स्क्रीन-शॉट्स की तरह।

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें


4

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

कि, C की मैक्रो प्रणाली (C ++ द्वारा विरासत में मिली) के साथ मिलकर, कई नुकसान और भ्रामक स्थितियों की ओर जाता है।

वर्णन करने के लिए, यदि एक हेडर ने अपने उपयोग के लिए मैक्रोज़ का उपयोग करते हुए कुछ प्रतीक को परिभाषित किया, और किसी अन्य हेडर ने प्रतीक को किसी अन्य फैशन में उपयोग किया जैसे कि एक फ़ंक्शन के लिए एक नाम, तो समावेशन का क्रम अंतिम परिणाम को बहुत प्रभावित करेगा। ऐसे कई उदाहरण हैं।


2

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

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

इसलिए C / C ++ हेडर फाइलों में एक इंटरफेस के एक समतुल्य (प्रकार) को एक अच्छी बात है।

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


विभिन्न फाइलों में इंटरफ़ेस और कार्यान्वयन? यदि आपको डिज़ाइन की आवश्यकता है, तो यह अभी भी एक फ़ाइल में जावा / सी # जैसी भाषाओं में इंटरफ़ेस (या अमूर्त वर्ग) को परिभाषित करने और अन्य फाइलों में कार्यान्वयन (एस) को छिपाने के लिए बहुत आम है। इसके लिए पुरानी और मुश्किल हेडर फ़ाइलों की आवश्यकता नहीं है।
पीटर नॉर्डलैंडर

एह? ऐसा नहीं है कि मैंने क्या कहा - आप इंटरफ़ेस और क्लास कार्यान्वयन को 2 फाइलों में परिभाषित करते हैं।
gbjbaanb

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

@Petter मुझे लगता है कि आप गलत समझ रहे हैं, वैचारिक रूप से वे अलग नहीं हैं - सी भाषा में एक इंटरफ़ेस प्रदान करने के लिए एक हेडर मौजूद है, और यद्यपि आप सही हैं - आप 2 को जोड़ सकते हैं (जैसा कि कई हेडर-ओनली सी कोड के साथ करते हैं) इसका कोई नहीं है सर्वोत्तम अभ्यास जो मैंने कई स्थानों पर देखा है। सभी C # देवों को मैंने इंटरफ़ेस को क्लास से अलग करते हुए देखा है, उदाहरण के लिए। इसका एक अच्छा अभ्यास यह है कि तब आप बिना प्रदूषण के कई अन्य फाइलों में इंटरफ़ेस फ़ाइल को शामिल कर सकते हैं। अब, अगर आपको लगता है कि यह विभाजन एक सर्वोत्तम अभ्यास है (यह है) तो सी में इसे प्राप्त करने का तरीका हेडर फ़ाइलों का उपयोग करके है।
gbjbaanb

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

1

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

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

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

अन्य भाषाओं में समान सुविधा क्यों लागू नहीं होती है? खैर, क्योंकि अन्य भाषाएं अन्य लोगों से आती हैं, और उन डिजाइनरों / रचनाकारों की एक अलग दृष्टि है कि चीजों को कैसे काम करना चाहिए।

सबसे अच्छा जवाब यह है कि आप जिस काम को करने की जरूरत है उससे चिपके रहते हैं और आपको खुश करते हैं।


0

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

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

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