क्या आधुनिक सी लिखने के बारे में कोई आम तौर पर स्वीकृत दिशानिर्देश हैं?


13

मेरे पास एक मजबूत जावा / ग्रूवी पृष्ठभूमि है और मुझे एक टीम सौंपी गई है जो एक प्रशासनिक सॉफ्टवेयर के लिए काफी बड़ा सी कोड बेस बनाए रखती है।

कुछ दर्द बिंदु, जैसे डेटाबेस में ब्लॉब से निपटने या पीडीएफ और एक्सेल में रिपोर्ट उत्पन्न करने के लिए जावा वेब सेवा के लिए बाह्यीकृत किया गया है।

हालाँकि, एक जावा देव के रूप में, मैं कोड के कुछ पहलुओं से थोड़ा भ्रमित हूँ:

  • यह क्रिया है (विशेषकर जब 'अपवाद' से निपटने के लिए)
  • बहुत सारी विशाल विधियाँ हैं (कई 2000+ लाइनें विधि)
  • कोई उन्नत डेटा संरचना नहीं है (मुझे सूची, सेट और मानचित्र बहुत याद आते हैं)
  • चिंता की कोई जुदाई नहीं (SQL खुशी से कोड के चारों ओर मिश्रित है)

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

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

मैं सीखना चाहता हूं कि आमतौर पर स्वीकृत आधुनिक सिद्धांतों के अनुसार सी कोड कैसे लिखा जाए। क्या आधुनिक सी को कैसे लिखा और संरचित किया जाना चाहिए, इसके बारे में कोई सामान्य रूप से स्वीकृत सिद्धांत हैं?

कुछ-कुछ 'इफेक्टिव जावा' पुस्तक के समतुल्य की तरह, लेकिन सी के लिए।

उत्तरों और टिप्पणियों के प्रकाश में संपादित करें:

  • मैं अपनी मानसिकता को C कोड में ढालने की कोशिश करूंगा और इसे OOP पर मिरर करने की कोशिश नहीं करूंगा।
  • मैंने टिप्पणी से अनुशंसित कोडिंग शैली गाइड को स्कैन करना शुरू कर दिया है (जीएनयू कोडिंग मानक और लिनक्स कर्नेल कोडिंग स्टाइल)।
  • फिर मैं अपने सहकर्मियों को इस कोड शैली का प्रस्ताव देने की कोशिश करूंगा। सबसे कठिन हिस्सा सह-कर्मियों को यह समझाने के लिए हो सकता है कि विशाल विधि को छोटे भागों में विभाजित किया जा सकता है और यह दोहराने के लिए कि त्रुटि हैंडलिंग कोड की समान 4 पंक्तियों को एक विधि की मदद से टाला जा सकता है।

5
क्या एप्लिकेशन को वास्तव में आधुनिकीकरण की आवश्यकता है, या क्या आपको लगता है कि यह सिर्फ इसलिए करता है क्योंकि जिस तरह से लिखा गया वह अपरिचित है?
ब्लरफ्ल


1
@Brfl, मुझे लगता है कि आवेदन पुराने मानक के साथ लिखा गया है। मैं सिर्फ यह जानना चाहता हूं कि (प्रशासनिक) सी। के लिए आज (2016) मानक क्या है। मैं वर्तमान ऐप को रीफ़ैक्टर या फिर से नया नहीं करना चाहता, मुझे इस बात का अंदाज़ा है कि मुझे कोड का अगला भाग कैसे लिखना चाहिए।
Guillaume


3
@antleroft: एक 2,000 लाइन फ़ंक्शन जो सरल चीजों की एक लंबी सूची करता है, एक के बाद एक, बिल्कुल कोई समस्या नहीं है और इसे एक बहाने की आवश्यकता नहीं है। कृपया "आप 2,000 लाइन फ़ंक्शन नहीं लिखना चाहिए क्योंकि आप 2,000 लाइन फ़ंक्शन नहीं लिखना चाहिए" जैसे परिपत्र तर्कों के साथ जवाब न दें।
gnasher729 22

जवाबों:


14

मैं आपके प्रश्न से पढ़ सकता हूं कि समस्या यह नहीं है कि कोड पुराना C है, लेकिन सिर्फ खराब प्रोग्रामिंग है। वर्बोसिटी, विशाल 2000+ लाइन फ़ंक्शंस, या चिंताओं को अलग नहीं करने जैसी अधिकांश समस्याएं, जो किसी भी भाषा, C या जावा में समान रूप से लागू होती हैं।

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

यदि कॉल श्रृंखला में त्रुटि को पारित करने में समस्या लगती है, तो अपने आप से पूछें: क्या वास्तव में कुछ छोटे आदमी को यह जानने की ज़रूरत है कि यहाँ कोई समस्या है? एक भाषा में निर्मित अपवाद तंत्र ऐसा करना आसान बनाते हैं, लेकिन सामान्य तौर पर अपवादों को जल्दी (किसी भी भाषा में) संभालना बेहतर होता है ताकि त्रुटि स्थिति उच्च-स्तरीय कोड के तर्क को प्रदूषित न करे। और वहाँ ऊपर समारोह यदि वास्तव में पता करने की जरूरत है, वहाँ के तरीके हैं अनुकरण अपवाद के साथ setjmpऔर longjmp

मुझे लगता है कि केवल सी-संबंधित समस्या का उल्लेख मानक कंटेनरों की कमी है। जबकि Setसामान्य रूप Mapसे जोड़े के एक सरणी के साथ और (सबसे अधिक भाग के लिए) एक सॉर्ट किए गए सरणी के साथ बदला जा सकता है या struct(यदि आप हाथ से पहले कुंजी सेट जानते हैं, तो map[key] = valueबदल जाता है s.key = value), लेकिन यह तथ्य है कि मानक में कोई गतिशील सरणी कंटेनर नहीं है पुस्तकालय। C99 में आप कम से कम स्टैक पर एक वैरिएबल लेंथ ऐरे को घोषित कर सकते हैं ( int array[len]लेकिन आपको lenपहले से गणना करने की आवश्यकता है (आमतौर पर कठिन नहीं) और निश्चित रूप से आप इसे स्टैक-एलोकेटेड ऑब्जेक्ट के रूप में वापस नहीं कर सकते। अधिकांश प्रोजेक्ट अपने स्वयं के डायनामिक ऐरे कंटेनर को लिखने या एक ओपन-सोर्स को अपनाने के साथ समाप्त होते हैं।

एक समापन नोट पर, मैं इंगित करना चाहता हूं कि मैं वहां गया हूं। मैं जावा प्रोग्रामर रहा हूँ जो C ++ और शुद्ध C. में चला गया था। मैं सलाह देना चाहता हूँ कि "किताब X को अच्छी C सीखने के लिए पढ़ें", लेकिन कोई भी ऐसा नहीं है जैसे जावा के लिए कोई नहीं है। आगे बढ़ने का तरीका भाषा और मानक पुस्तकालय की सभी जटिलताओं को भिगोना है; Google बहुत कुछ, बहुत कुछ पढ़ता है, और जब तक आप सी में सोचना शुरू नहीं करते हैं, तब तक बहुत कुछ कोड करें । जावा में सी में चीजें लिखने की कोशिश करना उतना ही निराशाजनक है जितना कि एक विदेशी भाषा में एक वाक्य लिखने की कोशिश करना जो सीधे शब्दों में आपकी मां से अनुवादित है। जुबान; आप और पाठक दोनों ही परेशान होंगे। अच्छी खबर यह है कि अच्छी प्रोग्रामिंग सीखना धीमी है लेकिन दूसरी भाषा सीखना तेज़ है। इसलिए यदि आप जावा में सभ्य कोड लिखते हैं,


1
सब सब में, यह एक बहुत अच्छा जवाब है। मैं सिर्फ एक वैध उपकरण के रूप में देखने पर setjmp()/ आपत्ति longjmp()जताऊंगा: यह कोई सफाई करने की कोशिश भी नहीं करता है। कोई भी आवंटन लीक हो जाएगा, किसी भी आयोजित लॉक को जारी नहीं किया जाएगा, किसी भी खुली हुई फ़ाइल को बंद नहीं किया जाएगा, और कोई भी क्षणिक डेटा असंगतता स्थायी हो जाएगी। IMHO, यह फ़ंक्शन जोड़ी मूल रूप से अब तक का आविष्कार किया गया सबसे खराब हैक है, एकमात्र औचित्य के साथ कि इसे लागू करना संभव था। अंत में, सी: स्पष्ट त्रुटि कोड में त्रुटि से निपटने के लिए वास्तव में केवल एक ही वैध तरीका है।
cmaster - मोनिका

@ cmaster yea। व्यक्तिगत रूप से, setjmp/longjmpC में पानी से एक मछली लगती है और मैंने कभी भी उनका उपयोग नहीं किया। मैंने केवल अपवादों की नकल के लिए इंटरनेट पर कई ट्यूटोरियल / पुस्तकालयों के कारण उन्हें शामिल करने के लिए मजबूर महसूस किया, इसलिए मैंने सोचा कि ऐसे लोग हैं जो वास्तव में इसका उपयोग करते हैं।
एक उल्लू

7

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

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

यदि आप अभी भी उस मार्ग से नीचे जाना चाहते हैं तो मैं निम्नलिखित सुझाव दूंगा:

  • सॉफ़्टवेयर / कोड का एक राज्य आरेख बनाएं (या जनरेट करें)
  • कोड में गोता लगाएँ और क्रमशः कोड के सबसे जटिल या महत्वपूर्ण भागों की एक सूची बनाएँ
  • किसी ऐसे व्यक्ति का पता लगाएं, जो उस कोड आधार के बारे में जानकार हो और उनसे पूछें कि इसे इस तरह क्यों बनाया गया है और समस्या का कारण क्या है
  • आपने जो भी सीखा है उससे प्रलेखन लिखें

इस बिंदु पर, आप यह तय करेंगे कि यह खोज के लायक है या नहीं। यदि आपकी कंपनी की संस्कृति विफलता को पुरस्कृत नहीं करती है तो उच्चतर या प्रबंधक से हरी बत्ती प्राप्त करें।

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

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


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

1

यदि आप उच्च स्तर की भाषा पसंद करते हैं, तो C ++ या ऑब्जेक्टिव-सी जैसी कुछ भाषाएँ हैं जिन्हें C कोड के साथ आसानी से मिलाया जा सकता है।

वैकल्पिक रूप से, C और C ++ यथोचित रूप से संगत हैं। आप कुछ परिवर्तनों के साथ पूरे कोडबेस को केवल C ++ के रूप में संकलित करने में सक्षम हो सकते हैं - आपके पास "वर्ग" या "टेम्पलेट" नाम का सामयिक चर होगा जिसे आपको नाम बदलने की आवश्यकता है, लेकिन व्यवहार में यह सब होगा। (sizeof ('a') C और C ++ में अलग है, लेकिन मुझे नहीं लगता कि मैंने कभी इसका इस्तेमाल किया है)।

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


1
मुझे यहां असहमत होना पड़ेगा। C और C ++ अलग भाषाएं हैं, और कुछ एक सी ++ संकलक (स्पष्ट रूप से वापसी मान कास्टिंग के लिए आवश्यक कोड malloc) सी में बुरा व्यवहार के अर्थ में माना जाता है constऔर inlineभी है बहुत C और C ++ के बीच अलग, और निश्चित रूप सी के ++ नहीं समझती __restrict। भाषाओं को विनिमेय के रूप में व्यवहार न करें, यहां तक ​​कि उन स्रोतों के सबसेट में भी जो दोनों में संकलित हैं।
Angew अब

1

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

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

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

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