OO भाषा में तार्किक रूप से प्रक्रियात्मक सॉफ्टवेयर लिखने का सबसे साफ तरीका


12

मैं एक इलेक्ट्रिकल इंजीनियर हूं और मुझे नहीं पता कि मैं क्या कर रहा हूं। कृपया मेरे कोड के भावी अनुरक्षकों को बचाएं।

हाल ही में मैं कई छोटे कार्यक्रमों पर काम कर रहा हूं (C # में) जिनकी कार्यक्षमता तार्किक रूप से "प्रक्रियात्मक" है। उदाहरण के लिए, उनमें से एक ऐसा प्रोग्राम है जो विभिन्न डेटाबेस से जानकारी एकत्र करता है, उस जानकारी का उपयोग एक प्रकार का सारांश पेज बनाने के लिए करता है, उसे प्रिंट करता है और फिर बाहर निकालता है।

इन सभी के लिए आवश्यक तर्क लगभग 2000 लाइनें हैं। मैं निश्चित रूप से उस सभी को एक एकल में सामान नहीं करना चाहता हूं main()और फिर "इसे साफ करें" #regionएस के साथ कुछ पिछले डेवलपर्स कर रहे हैं (कंपकंपी)।

यहाँ कुछ चीजें हैं जो मैंने पहले ही बहुत संतुष्टि के बिना आजमा ली हैं:

कार्यक्षमता के प्रत्येक मोटे बिट के लिए स्थिर उपयोगिताओं को बनाएं, जैसे एक डेटाबेसइन्फोएग्टर, सारांशपेजरेंटर और एक PrintUtility। मुख्य कार्य की तरह लग रहा है:

int main()
{
    var thisThing = DatabaseInfoGetter.GetThis();
    var thatThing = DatabaseInfoGetter.GetThat();
    var summary = SummaryPageGenerator.GeneratePage(thisThing, thatThing);

    PrintUtility.Print(summary);
}

एक कार्यक्रम के लिए मैं भी इंटरफेस के साथ गया था

int main()
{
    /* pardon the psuedocode */

    List<Function> toDoList = new List<Function>();
    toDoList.Add(new DatabaseInfoGetter(serverUrl));
    toDoList.Add(new SummaryPageGenerator());
    toDoList.Add(new PrintUtility());

    foreach (Function f in toDoList)
        f.Do();
}

इसमें से कोई भी सही नहीं लगता है। जैसे-जैसे कोड लंबा होता जाता है, ये दोनों दृष्टिकोण बदसूरत होने लगते हैं।

इस तरह से सामान तैयार करने का एक अच्छा तरीका क्या है?


2
मुझे यकीन नहीं है कि यह सख्ती से एक डुप्लिकेट है, लेकिन कृपया कई मापदंडों बनाम कई विधियों के साथ एकल विधि पढ़ें जो क्रम में बुलाया जाना चाहिए


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

@ एक प्रबंधनीय स्तर पर जटिलता को कम करने के विचार को विकसित करने के लिए एक बहुत अच्छा कौशल है। कोई भी बड़े कोड बेस को नहीं समझ सकता, सुपरमैन को भी नहीं (शायद बैटमैन को)। विचारों को सरल रूप से व्यक्त करने और कोड को सेल्फ-डॉक्यूमेंट करने के तरीके खोजना महत्वपूर्ण है।

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

जवाबों:


18

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

मुझे लगता है कि आपकी पहली वृत्ति, "यह बात-वह बात" पहले उदाहरण में कोड सही ट्रैक है। यह स्पष्ट और स्पष्ट है कि आप क्या करना चाहते हैं। कोड दक्षता के बारे में बहुत ज्यादा चिंता न करें, स्पष्टता अधिक महत्वपूर्ण है।

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

---- पोस्टस्क्रिप्ट: OO डिजाइन जाल

OO प्रोग्रामिंग के साथ सफलतापूर्वक काम करना मुश्किल हो सकता है। यहां तक ​​कि कुछ लोग हैं जो पूरे मॉडल को दोषपूर्ण मानते हैं। एक बहुत अच्छी किताब है जिसका इस्तेमाल मैंने पहली बार ओओ प्रोग्रामिंग को थिंकिंग इन जावा (अब इसके 4 वें संस्करण में) कहा है। उसी लेखक के पास C ++ के लिए एक संबंधित पुस्तक है। ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में सामान्य नुकसान से निपटने वाले प्रोग्रामर पर वास्तव में एक और सवाल है ।

कुछ नुकसान परिष्कृत हैं, लेकिन बहुत बुनियादी तरीकों से समस्याएं पैदा करने के बहुत सारे तरीके हैं। उदाहरण के लिए, कुछ साल पहले मेरी कंपनी में एक इंटर्न था जिसने कुछ सॉफ्टवेयर का पहला संस्करण लिखा था जो मुझे विरासत में मिला था और उसने हर उस चीज़ के लिए इंटरफेस बनाया जो शायद होकिसी दिन कई कार्यान्वयन होते हैं। बेशक, 98% मामलों में केवल एक ही कार्यान्वयन था, इसलिए कोड को अप्रयुक्त इंटरफेस के साथ लोड किया गया था, जो डीबगिंग को बहुत कष्टप्रद बनाता था क्योंकि आप इंटरफ़ेस कॉल के माध्यम से वापस कदम नहीं उठा सकते हैं, इसलिए आपको अंत करना होगा कार्यान्वयन के लिए पाठ खोज (हालांकि अब मैं IntelliJ का उपयोग करता हूं, "शो ऑल इम्प्लीमेंटेशन" सुविधा थी, लेकिन दिन में वापस मेरे पास ऐसा नहीं था)। यहां का नियम प्रक्रियात्मक प्रोग्रामिंग के लिए समान है: हमेशा एक चीज को हार्डकोड करें। केवल जब आपके पास दो या अधिक चीजें हों, तो एक अमूर्त बनाएं।

जावा स्विंग एपीआई में इसी तरह का डिज़ाइन ब्लंडर पाया जा सकता है। वे स्विंग मेनू सिस्टम के लिए एक प्रकाशन-सदस्यता मॉडल का उपयोग करते हैं। यह एक पूर्ण दुःस्वप्न स्विंग बनाने और डिबगिंग मेनू बनाता है। विडंबना यह है कि यह पूरी तरह से व्यर्थ है। वस्तुतः कभी भी ऐसी स्थिति नहीं होती है जिसमें एक मेनू क्लिक पर कई कार्यों को "सदस्यता" देने की आवश्यकता होती है। इसके अलावा, प्रकाशित-सदस्यता वहाँ एक पूर्ण मिसफायर थी क्योंकि एक मेनू सिस्टम सामान्य रूप से हमेशा उपयोग में रहता है। यह ऐसा नहीं है कि फ़ंक्शंस सदस्यता ले रहे हैं और फिर बेतरतीब ढंग से सदस्यता समाप्त कर रहे हैं। तथ्य यह है कि सन में "पेशेवर" डेवलपर्स ने इस तरह से एक विस्फोट किया, यह दर्शाता है कि ओओ डिजाइन में स्मारकीय स्क्रू अप बनाने के लिए पेशेवरों के लिए यह कितना आसान है।

मैं ओओ प्रोग्रामिंग में दशकों के अनुभव के साथ एक बहुत ही विशेषज्ञ डेवलपर हूं, लेकिन यहां तक ​​कि मैं पहली बार मानता हूं कि टन मुझे नहीं पता है और अब भी मैं बहुत अधिक ओओ का उपयोग करने के बारे में सतर्क हूं। मैं एक सहकर्मी से लंबे व्याख्यान सुनता था, जो विशेष डिजाइन करने के तरीके के बारे में एक ओओ जोलेट था। वह वास्तव में जानता था कि वह क्या कर रहा था, लेकिन सभी ईमानदारी से मुझे उनके कार्यक्रमों को समझने में एक कठिन समय था क्योंकि उनके पास ऐसे परिष्कृत डिजाइन मॉडल थे।


1
+1 के लिए "स्पष्टता बहुत अधिक महत्वपूर्ण है [दक्षता से]"
स्टीफन

क्या आप मुझे एक ऐसे लिंक की ओर संकेत कर सकते हैं जो बताता है कि एक "बुरी तरह से लिखा गया OO प्रोग्राम" क्या है या एक संपादन में इसके बारे में कुछ और जानकारी जोड़ सकता है?
लोम्बार्ड

@ लम्बरार्ड मैंने ऐसा ही किया।
टायलर डर्डन

1

पहला तरीका ठीक है। प्रक्रियात्मक भाषाओं में, सी की तरह, मानक दृष्टिकोण को कार्यक्षमता को नामस्थान में विभाजित करना है - जैसे स्थिर वर्गों का उपयोग DatabaseInfoGetterकरना मूल रूप से एक ही बात है। स्पष्ट रूप से यह दृष्टिकोण सरल, अधिक मॉड्यूलर और अधिक पठनीय / बनाए रखने योग्य कोड की ओर जाता है, जो सबकुछ एक वर्ग में रखने के बजाए, भले ही सब कुछ विधियों में टूट गया हो।

जिसमें से बोलते हुए, संभव के रूप में कुछ कार्य करने के लिए विधियों को सीमित करने का प्रयास करें। कुछ प्रोग्रामर थोड़ी कम ग्रैन्युलैरिटी पसंद करते हैं , लेकिन विशाल तरीकों को हमेशा हानिकारक माना जाता है।

यदि आप अभी भी जटिलता से जूझ रहे हैं, तो आपको सबसे अधिक संभावना है कि आप आगे भी अपने कार्यक्रम को तोड़ सकते हैं। पदानुक्रम में और अधिक स्तर बनाएं - शायद DatabaseInfoGetterकुछ अन्य वर्गों जैसे कि ProductTableEntryया कुछ और को संदर्भित करने की आवश्यकता है। आप प्रक्रियात्मक कोड लिख रहे हैं, लेकिन याद रखें, आप C # का उपयोग कर रहे हैं, और OOP आपको जटिलता को कम करने के लिए उपकरणों का एक गुच्छा देता है, जैसे:

int main() 
{
    var thisthat = Database.GetThisThat();
}

public class ThisThatClass
{
    public String This;
    public String That;
}

public static class Database 
{
    public ThisThatClass GetThisThat()
    {
        return new ThisThatClass 
        {
            This = GetThis(),
            That = GetThat()
        };
    }

    public static String GetThis() 
    { 
        //stuff
    }
    public static String GetThat() 
    { 
        //stuff
    }

}

इसके अलावा, स्थिर वर्गों के साथ सावधान रहें। डेटाबेस कक्षाएं अच्छे उम्मीदवार हैं .. जब तक आपके पास आमतौर पर एक डेटाबेस होता है .. आपको विचार मिलता है।

अंततः यदि आप गणितीय कार्यों में सोचते हैं और C # आपकी शैली के अनुरूप नहीं है, तो कुछ स्केला, हास्केल आदि की कोशिश करें, वे बहुत अच्छे हैं।


0

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

var summary = SummaryPageGenerator.GeneratePage(thisThing, thatThing);

इस मामले में:

var summary = SummaryPageGenerator.GeneratePage(new This(DatabaseInfoGetter), new That(DatabaseInfoGetter));

अब, प्रक्रियात्मक कोड की उन 2,000+ पंक्तियों को देखना दिलचस्प होगा और यह निर्धारित करना होगा कि विभिन्न भागों को अलग-अलग वर्गों में एक साथ कैसे वर्गीकृत किया जा सकता है और विभिन्न प्रक्रियाओं को उन वर्गों में स्थानांतरित किया जा सकता है।
प्रत्येक वर्ग को सरल होना चाहिए और सिर्फ एक काम करने पर ध्यान केंद्रित करना चाहिए। और यह मुझे लगता है कि कोड के कुछ हिस्से पहले से ही सुपरक्लास के साथ काम कर रहे हैं, जो वास्तव में उपयोगी होने के लिए बहुत बड़े हैं। डेटाबेसइन्फ़ॉगर, उदाहरण के लिए, भ्रमित करने का तरीका लगता है। वैसे भी यह क्या हो रहा है? यह बहुत सामान्य लगता है। फिर भी सारांशपेजरेंटर बहुत विशिष्ट है! और PrintUtility फिर से जेनेरिक की जा रही है।
तो, शुरू करने के लिए, आपको अपनी कक्षाओं के लिए सामान्य नामों से बचना चाहिए और इसके बजाय अधिक विशिष्ट नामों का उपयोग करना शुरू करना चाहिए। PrintUtility वर्ग, उदाहरण के लिए, एक हेडर वर्ग, एक पाद लेख वर्ग, एक TextBlock वर्ग, एक छवि वर्ग के साथ एक प्रिंट वर्ग और संभवतः यह इंगित करने के लिए कुछ तरीके होंगे कि वे प्रिंट में कैसे प्रवाहित होंगे। यह सब हो सकता है PrintUtility नाम स्थान , यद्यपि।
डेटाबेस के लिए, इसी तरह की कहानी। यहां तक ​​कि अगर आप डेटाबेस एक्सेस के लिए एंटिटी फ्रेमवर्क का उपयोग करते हैं, तो आपके पास यह आपके द्वारा उपयोग की जाने वाली चीजों तक सीमित होना चाहिए, और इसे तार्किक समूहों में विभाजित किया गया है।
लेकिन मुझे आश्चर्य है कि अगर आप 4 साल बाद भी इस समस्या से जूझ रहे हैं। यदि ऐसा है, तो यह एक मानसिकता है जिसे "प्रक्रियात्मक अवधारणा" से दूर और "वस्तु उन्मुख अवधारणा" में बदलने की आवश्यकता है। जो चुनौतीपूर्ण है अगर आपके पास अनुभव नहीं है ...


-3

मेरी राय है, आपको अपना कोड बदलना चाहिए ताकि यह सरल, सुसंगत और पठनीय हो।

मैंने इस विषय पर कुछ ब्लॉग पोस्ट लिखे, और मुझे विश्वास है कि वे समझने में सरल हैं: अच्छा कोड क्या है

सरल: जैसे एक सर्किट बोर्ड में अलग-अलग टुकड़े होते हैं, प्रत्येक एक जिम्मेदारी के साथ। कोड को छोटे, सरल भागों में विभाजित किया जाना चाहिए।

संगत: पेटेंट, नामकरण तत्वों और चीजों के लिए एक मानक का उपयोग करें। आपको ऐसे उपकरण पसंद हैं जो हर समय उसी तरह से काम करते हैं और आप यह जानना चाहते हैं कि उन्हें कहां खोजना है। कोड के साथ भी ऐसा ही है।

पठनीय: जब तक वे व्यापक रूप से उपयोग नहीं किए जाते और डोमेन को लक्षित कर रहे हैं (मैट्नज़) के भीतर जाना जाता है, तब तक समरूपता का उपयोग न करें, स्पष्ट और आसान समझने वाले नामों को प्राथमिकता दें।


1
यदि वे व्यापक रूप से उपयोग किए जाते हैं और डोमेन के भीतर जाने वाले सॉफ़्टवेयर को लक्षित कर रहे हैं, तो वे स्वीकार्य हैं। एयर ट्रैफ़िक कंट्रोल सॉफ़्टवेयर लिखने की कोशिश करें - बिना किसी जोड़-तोड़ के हमने बना दिया है - किसी को नहीं पता होगा कि आप जिस बारे में बात कर रहे थे, क्या आपने उसका पूरा नाम इस्तेमाल किया है। नेटवर्किंग के लिए HTTP, ऑटोमोटिव आदि में ABS जैसी चीजें पूरी तरह से स्वीकार्य हैं।
मटनज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.