2011-01-12 14 views
16

मैं C++ का उपयोग कर प्रोग्राम के मुख्य कार्य में क्या जाता है, इसकी एक सर्वोत्तम अभ्यास युक्ति की तलाश में हूं। वर्तमान में मुझे लगता है कि दो दृष्टिकोण संभव हैं। (हालांकि उन दृष्टिकोणों के "मार्जिन" मनमाने ढंग से एक-दूसरे के करीब हो सकते हैं)मुख्य समारोह में क्या जाता है?

1: एक "मास्टर" -क्लास लिखें जो मुख्य कार्य में पारित पैरामीटर प्राप्त करता है और उस "मास्टर" में पूरा प्रोग्राम संभालता है - कक्षा (बेशक आप अन्य वर्गों का भी उपयोग करते हैं)। इसलिए मुख्य कार्य कम से कम लाइनों तक कम हो जाएगा।

#include "MasterClass.h" 
int main(int args, char* argv[]) 
{ 
MasterClass MC(args, argv); 
} 

2: मुख्य कार्य में "पूर्ण" प्रोग्राम लिखें, निश्चित रूप से उपयोगकर्ता परिभाषित वस्तुओं का उपयोग करना! हालांकि वैश्विक कार्य भी शामिल हैं और मुख्य कार्य कुछ हद तक बड़ा हो सकता है।

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

+0

आम तौर पर args के बजाय argc लिखा जाता है। Argc – Will

उत्तर

23

आपके पास एक मास्टर क्लास क्यों होगी? जिम्मेदारी का क्षेत्र एकल क्या है?

"मास्टर" या "एप्लिकेशन" कक्षाएं बड़े ब्लब्स बनती हैं जो कई अलग-अलग चीजें करते हैं। आखिरकार, बात क्या है? यह आपको क्या खरीदता है?

मुख्य फ़ंक्शन का उपयोग इस मुख्य कार्यक्षमता प्रदान करने के लिए क्यों नहीं करें? main में उच्च स्तरीय एप्लिकेशन लाइफसाइक्शंस को परिभाषित करें। इसमें कुछ कमांड लाइन तर्क होते हैं और उन्हें पार करते हैं (अधिमानतः इसे किसी अन्य फ़ंक्शन या क्लास में प्रस्तुत करके), और फिर यह कुछ सेटअप कार्यक्षमता को कॉल करता है, और फिर कुछ क्लीनअप करने से पहले यह किसी प्रकार का मुख्य पाश दर्ज कर सकता है। सब कुछ, यह आपको शायद 10-15 लाइनों का मुख्य कार्य दे सकता है, लेकिन शायद उससे अधिक नहीं। इसे जितना संभव हो सके अन्य वर्गों और कार्यों को सौंपना चाहिए। इसलिए main स्वयं को छोटा और प्यारा रखा जाता है, लेकिन अभी भी इसका उद्देश्य है।

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

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

+1

+1 केवल तर्क पार्सिंग के लिए। यदि कोई "मॉड्यूलर" कोड लिखना चाहता है, तो किसी को वास्तविक कोड से तर्क पार्सिंग (दूसरों के बीच एक इंटरफेस) को कम करना होगा, और उन सभी "सेटिंग्स" को इकट्ठा करने के लिए उपयुक्त संरचना का उपयोग करना होगा। ध्यान दें कि तर्क पार्सिंग में पर्यावरण चर के उपयोग को भी शामिल किया जा सकता है, क्योंकि अधिकांश बार डिफ़ॉल्ट रूप से सेटअप करने के लिए उपयोग किया जाता है। फिर यह छोटा/स्तरीय उच्च-स्तरीय दृश्य तक छोटा सेटअप/लूप होता है। –

+0

"आखिरकार, क्या बात है?" यद्यपि यहां प्रदर्शित नहीं किया गया है, यह निर्भरता इंजेक्शन प्रदान कर सकता है। 'Std :: cout' पर लिखने वाले कोड होने के बजाय, उदाहरण के लिए,' मास्टर' क्लास ** एक ** 'मानक आउटपुट 'स्ट्रीम, एक' std :: ostream' के साथ सहयोगी है। 'मुख्य()' फ़ंक्शन उस एसोसिएशन के लिए 'std :: cout' के साथ 'मास्टर' ऑब्जेक्ट बनाता है, लेकिन इकाई परीक्षण' std :: ostringstream' का उपयोग कर सकते हैं। यह इकाई परीक्षण व्यवहार आवश्यकताओं के लिए आसान हो जाता है जैसे कि "यदि कमांड लाइन दोषपूर्ण है, तो प्रोग्राम को अपने मानक एरर आउटपुट स्ट्रीम में एक त्रुटि संदेश लिखना होगा"। – Raedwald

+0

@ रेडवाल्ड: इसके लिए आपको मास्टर क्लास की आवश्यकता क्यों है? 'मुख्य' क्यों उचित 'std :: ostream' नहीं बना सकता है और फिर इसे सभी वर्गों और कार्यों को सौंपता है जो इसे प्रस्तुत करता है? इसके लिए मास्टर क्लास की आवश्यकता नहीं है। – jalf

2

आपका पहला दृष्टिकोण बहुत आम है, हालांकि कक्षा को 'एप्लिकेशन' नाम दिया जाता है (या कम से कम शब्द 'एप्लिकेशन' होता है) तो ऐसा करें।

3

मैं मुख्य दिनचर्या में प्रक्रिया के तर्कों का विश्लेषण करता हूं, फिर argc और argv की तुलना में अधिक पठनीय पैरामीटर पास करके कक्षा उदाहरण बना सकता हूं।

6

आप दो "चरम" दृष्टिकोणों का वर्णन कर रहे हैं, जिनमें से कोई भी मेरे लिए सही नहीं लगता है। न तो एक God Class, न ही एक भी भगवान समारोह होने के लिए वास्तविक उपयोग के लिए किसी भी गैर-कार्यक्रम कार्यक्रम को लागू करने का सही तरीका है।

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

आपका दूसरा दृष्टिकोण इकाई परीक्षण के लिए फिर से समस्याग्रस्त हो सकता है, इसलिए आपको ठीक से अनाज वाले यूनिट परीक्षण संभव बनाने के लिए extract methods (और फिर अधिमानतः move them into a separate class) पर प्रयास करना चाहिए।

मीठा स्थान जहां आप बनना चाहते हैं, इस प्रकार दो चरम सीमाओं के बीच कहीं है, जो आपके कोड को टेस्ट करने योग्य बनाने की आवश्यकता से बाधित है।

main() के संदर्भ में, सामान्य रूप से अपने कार्यक्रमों को कैसे व्यवस्थित करना है, इस बारे में सोचने योग्य है। मूल विचार "हिस्सा" (वर्गों और विधि) जो

  • , इतने छोटे, समझा जा सकता है परीक्षण किया है और आसानी से बनाए रखा है,
  • तार्किक जोड़नेवाला में विभाजन है।
+1

तर्कों की संख्या की गिनती है मैं असहमत हूं। एक प्रवेश बिंदु होना चाहिए- चाहे वह एक ईश्वरीय कार्य या ईश्वर वर्ग है, कम से कम एक होना चाहिए। – Puppy

+2

@DeadMG, ज़ाहिर है। लेकिन ओपी को उद्धृत करते हुए: * "पहले दृष्टिकोण के लिए कुछ यूनिट परीक्षण लिखना [...] थोड़ा मुश्किल है क्योंकि अधिकांश विधियां निजी हैं।" *। यह मैं समझता हूं कि उसकी 'मास्टर' कक्षा एक ईश्वर वर्ग है, कहीं भी कुछ भी नहीं दे रही है। –

+0

ओह, मैं देखता हूं कि आपका क्या मतलब है। हाँ, मैं पूरी तरह से सहमत हूं। – Puppy

0

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

2

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

2

आमतौर पर मैं एक मुख्य कार्य (समान हस्ताक्षर whith) अपने आवेदन के नाम स्थान में फोन:

namespace current_application { 
    int main(int argc, char **argv) { 
     // ... 
    } 
} 
int main(int argc, char **argv) { 
    return current_application::main(argc, argv); 
} 

और फिर मैं आमतौर पर अपने वास्तविक मुख्य (नाम स्थान में एक) का उपयोग आवेदन बुद्धिमान बातें प्रारंभ करने में :

मानक इनपुट/आउटपुट/त्रुटि पर
  • सेट स्थानों)

  • पार्स आवेदन tion मापदंडों अपने मुख्य वर्ग की वस्तु पर

  • इन्स्तांत, अगर वर्तमान

  • कॉल मुख्य समारोह (QApplication की तरह कुछ के समकक्ष), अगर वर्तमान (QApplication::run की तरह कुछ के बराबर)

और आमतौर पर दुर्घटना के मामले में अधिक डीबगिंग जानकारी मुद्रित करने के लिए trycatch ब्लॉक को जोड़ना पसंद करते हैं।


यह सब लेकिन बहुत ही व्यक्तिपरक है; यह आपकी कोडिंग शैली का हिस्सा है।

+0

मैं नहीं देखता कि यह आपको क्या प्राप्त करता है। भ्रमित रखरखाव प्रोग्रामर को छोड़कर। :) –

+0

@ जॉन डिबलिंग: क्यों? – peoro

+1

क्योंकि आप सी ++ में जावा-आश कुछ करने की कोशिश कर रहे हैं। इस प्रकार का आर्किटेक्चर, जहां आप नामस्थान के भीतर एक मुफ्त फ़ंक्शन में 'मुख्य()' को आसानी से डेलगेट करते हैं, आपको * कुछ भी नहीं मिलता है, और अप्रत्याशित है। नामित 'मुख्य' आपके लिए क्या करता है कि गैर-नामित व्यक्ति नहीं करता है? –

0

आपके द्वारा दिया गया उदाहरण केवल मुख्य कार्य को नामस्थान के अंदर ले जाता है। मुझे यहां लाभ नहीं दिख रहा है। मास्टर क्लास मॉडल की ओर थोड़ा सा प्रवृत्ति के साथ सड़क दृष्टिकोण का एक माध्यम मेरे लिए काम करता है। मास्टर क्लास ऑब्जेक्ट आमतौर पर ढेर पर विशाल और सर्वोत्तम बनाया जाएगा। मेरे पास मुख्य कार्य ऑब्जेक्ट बनाता है और यहां होने वाली किसी भी त्रुटि को संभालता है।

class MasterClass { 
public: 
static MasterClass* CreateInstance(int argc, char **argv); 
    // ... 
} 

int main(int argc, char** argv) 
{ 
    try 
    { 
     MasterClass mc = MC::CreateInstance(argc, argv); 
    } 
    catch(...) 
    { 
     // ... 
    } 
} 

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

STATUS LNPUBLIC AddInMain(HMODULE hModule, int argc, char far *argv[]) 
{ 
    MasterClass mc = MC::CreateInstance(argc, argv); 
    while(/* wait for scheduler to give control */) 
    { 
      STATUS s = mc->RunForTimeSlice(); 
      if (s != SUCCESS) 
       break; 
    } 
    // clean up 
} 

अनुसूचक के साथ बातचीत के लिए सभी तर्क मुख्य में इस प्रकार है और इस कार्यक्रम के बाकी इसके किसी भी संभाल करने के लिए नहीं है।

0

यदि किसी अपवाद में हैंडलर नहीं है, तो यह निर्दिष्ट नहीं है कि स्थानीय वस्तुओं के विनाशकों को std::terminate से पहले बुलाया जाता है या नहीं।

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

आमतौर पर है कि सभी है कि मैं main में डाल दिया, जो अन्यथा सिर्फ एक cppMain कॉल है ... ;-)

चीयर्स & hth।,

+1

वैश्विक स्कोप पर ऑब्जेक्ट्स रखने की बजाय एक और चाल है, तो आप वैश्विक दायरे पर पॉइंटर्स रख सकते हैं, और फिर मुख्य अंदर वस्तुओं (और इस प्रकार निर्माण आदेश को नियंत्रित करें) का निर्माण करें और पॉइंटर्स को उन स्थानीय लोगों पर इंगित करें, और फिर "वास्तविक" मुख्य कार्य को कॉल करें। इस प्रकार निर्धारक निर्माण और विनाश और इसके आदेश :) –

0

मैं एक आईओसी (नियंत्रण के उलट) पसंद करते हैं के लिए दृष्टिकोण मेरी कार्यक्रम।

इसलिए मेरा "मुख्य" प्रोग्राम के "विकल्प" और "कॉन्फ़िगरेशन" को निर्धारित करने के लिए कमांड तर्कों का उपयोग करता है। विकल्पों के अनुसार मेरा मतलब कमांड लाइन में पारित कुछ झंडे को समझना और कॉन्फ़िगरेशन से मेरा मतलब है कॉन्फ़िगरेशन फ़ाइलों को लोड करना।

वह ऑब्जेक्ट जो कॉन्फ़िगरेशन फ़ाइलों को लोड करने के लिए उपयोग करता है उसके बाद "रन" करने का आदेश होता है लेकिन क्या चल रहा है (यदि कुछ भी हो) कमांड लाइन तर्कों पर भी निर्भर करता है।

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