पठनीयता बनाम अनुरक्षण, नेस्टेड फ़ंक्शन कॉल लिखने का विशेष मामला


57

नेस्टेड फ़ंक्शन कॉल के लिए मेरी कोडिंग शैली निम्नलिखित है:

var result_h1 = H1(b1);
var result_h2 = H2(b2);
var result_g1 = G1(result_h1, result_h2);
var result_g2 = G2(c1);
var a = F(result_g1, result_g2);

मैं हाल ही में एक विभाग में बदल गया हूँ जहाँ निम्नलिखित कोडिंग शैली बहुत उपयोग में है:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

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

मुझे डर है कि, पहली बार प्रोग्राम की गई उसी समस्या के कारण क्रैश होने की स्थिति में, मैं यह नहीं जान पाऊंगा कि किस फंक्शन के कारण क्रैश हुआ है।

दूसरी ओर, आप एक लाइन पर जितना अधिक प्रोसेसिंग करते हैं, उतना ही तर्क आपको एक पेज पर मिलता है, जो पठनीयता को बढ़ाता है।

क्या मेरा डर सही है या क्या मुझे कुछ याद आ रहा है, और सामान्य तौर पर, जो व्यावसायिक वातावरण में पसंद किया जाता है? पठनीयता या रखरखाव?

मुझे नहीं पता कि यह प्रासंगिक है, लेकिन हम C ++ (STL) / C # में काम कर रहे हैं।


17
@gnat: आप एक सामान्य प्रश्न का उल्लेख करते हैं, जबकि मैं विशेष रूप से नेस्टेड फंक्शन कॉल के उल्लेखित मामले और क्रैश डंप विश्लेषण के मामले में परिणाम में दिलचस्पी रखता हूं, लेकिन लिंक के लिए धन्यवाद, इसमें काफी दिलचस्प जानकारी शामिल है।
डोमिनिकन

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

4
क्या चर नाम है result_g1जो आप वास्तव में उपयोग करेंगे या इस मूल्य वास्तव में एक समझदार नाम के साथ कुछ का प्रतिनिधित्व करते हैं; उदा percentageIncreasePerSecond। वह वास्तव में दोनों के बीच फैसला करने के लिए मेरी परीक्षा होगी
रिचर्ड टिंगल

3
कोडिंग शैली पर आपकी भावनाओं के बावजूद, आपको उस सम्मेलन का पालन करना चाहिए जो पहले से ही है जब तक कि यह स्पष्ट रूप से गलत नहीं है (ऐसा नहीं लगता कि यह इस मामले में है)।
n00b

4
@ t3chb0t आपको अपनी पसंद के अनुसार वोट देने के लिए स्वतंत्र हैं, लेकिन कृपया इस साइट पर अच्छे, उपयोगी, ऑन-टॉपिक प्रश्नों (और बुरे लोगों को हतोत्साहित करने वाले) को प्रोत्साहित करने के हित में सजग रहें, ताकि एक प्रश्न के ऊपर या नीचे मतदान का उद्देश्य हो। यह इंगित करने के लिए कि क्या कोई प्रश्न उपयोगी और स्पष्ट है, इसलिए अन्य कारणों से मतदान जैसे कि वोट का उपयोग करने के साधन के रूप में कुछ उदाहरण कोड पर आलोचना प्रदान करने के लिए प्रश्न के संदर्भ की सहायता के लिए आम तौर पर साइट की गुणवत्ता बनाए रखने में सहायक नहीं है : softwareengineering.stackexchange.com/help/privileges/vote-down
बेन कॉटरेल

जवाबों:


111

यदि आप एक लाइनर जैसे विस्तार करने के लिए मजबूर महसूस किया

 a = F(G1(H1(b1), H2(b2)), G2(c1));

मैं आपको दोषी नहीं ठहराऊंगा। यह न केवल पढ़ने के लिए कठिन है, यह डिबग करना कठिन है।

क्यों?

  1. यह सघन है
  2. कुछ डिबगर केवल एक ही बार में पूरी बात को उजागर करेंगे
  3. यह वर्णनात्मक नामों से मुक्त है

यदि आप इसे मध्यवर्ती परिणामों के साथ बढ़ाते हैं, तो आप प्राप्त करते हैं

 var result_h1 = H1(b1);
 var result_h2 = H2(b2);
 var result_g1 = G1(result_h1, result_h2);
 var result_g2 = G2(c1);
 var a = F(result_g1, result_g2);

और यह अभी भी पढ़ना मुश्किल है। क्यों? यह दो समस्याओं का हल करता है और एक चौथे का परिचय देता है:

  1. यह सघन है
  2. कुछ डिबगर केवल एक ही बार में पूरी बात को उजागर करेंगे
  3. यह वर्णनात्मक नामों से मुक्त है
  4. यह गैर-वर्णनात्मक नामों के साथ बरबाद है

यदि आप इसे ऐसे नामों के साथ विस्तारित करते हैं जो नए, अच्छे, शब्दार्थ अर्थ जोड़ते हैं, तो और भी बेहतर! एक अच्छा नाम मुझे समझने में मदद करता है।

 var temperature = H1(b1);
 var humidity = H2(b2);
 var precipitation = G1(temperature, humidity);
 var dewPoint = G2(c1);
 var forecast = F(precipitation, dewPoint);

अब कम से कम यह एक कहानी कहता है। यह समस्याओं को ठीक करता है और स्पष्ट रूप से यहां दी गई किसी भी चीज़ से बेहतर है लेकिन इसके लिए आपको नामों के साथ आने की आवश्यकता है।

अगर आप इसे अर्थहीन नामों के साथ पसंद करते हैं result_thisऔर result_thatक्योंकि आप केवल अच्छे नामों के बारे में नहीं सोच सकते हैं, तो मैं वास्तव में आपको पसंद करूंगा कि हम निरर्थक नाम को अव्यवस्थित करें और कुछ अच्छे पुराने व्हाट्सएप का उपयोग करके इसका विस्तार करें:

int a = 
    F(
        G1(
            H1(b1), 
            H2(b2)
        ), 
        G2(c1)
    )
;

यह उतना ही पठनीय है, यदि अधिक नहीं, तो अर्थहीन परिणाम वाले नामों की तुलना में (न कि ये फ़ंक्शन नाम उस महान हैं)।

  1. यह सघन है
  2. कुछ डिबगर केवल एक ही बार में पूरी बात को उजागर करेंगे
  3. यह वर्णनात्मक नामों से मुक्त है
  4. यह गैर-वर्णनात्मक नामों के साथ बरबाद है

जब आप अच्छे नामों के बारे में नहीं सोच सकते हैं, तो यह उतना ही अच्छा है जितना इसे मिलता है।

कुछ कारणों से डिबगर नई लाइनों से प्यार करते हैं, इसलिए आपको पता होना चाहिए कि यह डीबग करना मुश्किल नहीं है:

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

यदि यह पर्याप्त नहीं है, तो कल्पना G2()को एक से अधिक स्थानों पर बुलाया गया और फिर यह हुआ:

Exception in thread "main" java.lang.NullPointerException
    at composition.Example.G2(Example.java:34)
    at composition.Example.main(Example.java:18)

मुझे लगता है कि यह अच्छा है कि चूंकि प्रत्येक G2()कॉल स्वयं की लाइन पर होगी, इसलिए यह शैली आपको सीधे मुख्य कॉलिंग में ले जाती है।

तो कृपया 1 और 2 की समस्याओं को हमें समस्या के साथ चिपकाने के बहाने के रूप में उपयोग न करें। 4. जब आप उनके बारे में सोच सकते हैं तो अच्छे नामों का उपयोग करें। जब आप नहीं कर सकते तो निरर्थक नामों से बचें।

ऑर्बिट की टिप्पणी में लाइटनेस दौड़ सही ढंग से बताती है कि ये कार्य कृत्रिम हैं और इनमें ख़राब नाम हैं। तो यहाँ इस शैली को जंगली से कुछ कोड पर लागू करने का एक उदाहरण है:

var user = db.t_ST_User.Where(_user => string.Compare(domain,  
_user.domainName.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
.Where(_user => string.Compare(samAccountName, _user.samAccountName.Trim(), 
StringComparison.OrdinalIgnoreCase) == 0).Where(_user => _user.deleted == false)
.FirstOrDefault();

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

var user = db
    .t_ST_User
    .Where(
        _user => string.Compare(
            domain, 
            _user.domainName.Trim(), 
            StringComparison.OrdinalIgnoreCase
        ) == 0
    )
    .Where(
        _user => string.Compare(
            samAccountName, 
            _user.samAccountName.Trim(), 
            StringComparison.OrdinalIgnoreCase
        ) == 0
    )
    .Where(_user => _user.deleted == false)
    .FirstOrDefault()
;

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


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

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

4
विस्तारित संस्करण बदसूरत दिखता है। वहाँ बहुत अधिक व्हॉट्सएप है जो कि कम करता है, जो कि कम कर देता है sssinceeverythingisem phasizedwithit, meaningnothingi s।
मतीन उलहाक

5
@MateenUlhaq केवल अतिरिक्त व्हाट्सएप है जो कुछ नई कहानियों और कुछ इंडेंटेशन है, और यह सभी सावधानीपूर्वक सार्थक सीमाओं पर रखा गया है। इसके बजाय आपकी टिप्पणी गैर-सार्थक सीमाओं पर व्हाट्सएप को जगह देती है। मेरा सुझाव है कि आप थोड़ा और अधिक खुले रूप में देखें।
jpmc26

3
@MateenUlhaq के विपरीत, मैं इस तरह के फ़ंक्शन नामों के साथ इस विशेष उदाहरण में व्हाट्सएप के बारे में बाड़ पर हूं, लेकिन वास्तविक फ़ंक्शन नामों (जो लंबाई में दो से अधिक वर्णों के साथ हैं, ठीक है?) यह वही हो सकता है जो मैं जाऊंगा।
को मोनिका

50

दूसरी ओर, आप एक लाइन पर जितना अधिक प्रोसेसिंग करते हैं, उतना ही तर्क आपको एक पेज पर मिलता है, जो पठनीयता को बढ़ाता है।

मैं इससे पूरी तरह असहमत हूं। बस अपने दो कोड उदाहरणों को देखते हुए इसे गलत कहते हैं:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

पढ़ने के लिए सुना है। "पठनीयता" का अर्थ सूचना घनत्व नहीं है; इसका मतलब है "पढ़ने, समझने और बनाए रखने में आसान"।

कभी-कभी, कोड सरल होता है और यह एक पंक्ति का उपयोग करने के लिए समझ में आता है। दूसरी बार, ऐसा करने से केवल एक पंक्ति में अधिक cramming से परे कोई स्पष्ट लाभ के लिए, पढ़ना मुश्किल हो जाता है।

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

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


37
जबकि मैं मानता हूं कि F(G1(H1(b1), H2(b2)), G2(c1))पढ़ना कठिन है, इसका घनीभूत होने से कोई लेना-देना नहीं है। (यह निश्चित नहीं है कि आपके कहने का मतलब क्या है, लेकिन इसकी व्याख्या इस तरह से की जा सकती है।) एक ही पंक्ति में तीन या चार कार्यों का घोंसला पूरी तरह से पठनीय हो सकता है, विशेष रूप से यदि कुछ फ़ंक्शन सरल इन्फिक्स ऑपरेटर हैं। यह समस्या है कि nondescriptive नाम यहाँ हैं, लेकिन यह समस्या मल्टी-लाइन संस्करण में और भी बदतर है, जहाँ अभी तक अधिक nondescriptive नाम पेश किए गए हैं। केवल बॉयलरप्लेट को जोड़ना लगभग कभी भी पठनीयता को प्रभावित नहीं करता है।
14:22

23
@leftractionabout: मेरे लिए, कठिनाई यह है कि यह स्पष्ट नहीं है कि क्या G13 पैरामीटर या केवल 2 हैं और G2एक और पैरामीटर है F। मुझे कोष्ठक को गिनना और गिनना है।
Matthieu M.

4
@MatthieuM। यह एक मुद्दा हो सकता है, हालांकि यदि कार्यों को अच्छी तरह से जाना जाता है तो यह अक्सर स्पष्ट होता है जो कितने तर्क लेता है। विशेष रूप से, जैसा कि मैंने कहा, इन्फिक्स कार्यों के लिए यह तुरंत स्पष्ट है कि वे दो तर्क लेते हैं। (इसके अलावा, कोष्ठक-टुपल्स सिंटैक्स अधिकांश भाषाओं में इस समस्या का उपयोग किया जाता है; ऐसी भाषा में जो करी को स्वचालित रूप से साफ़ करना पसंद करती है:) F (G1 (H1 b1) (H2 b2)) (G2 c1)
15:22 बजे लेफ्टरनबाउट

5
व्यक्तिगत रूप से मैं अधिक कॉम्पैक्ट रूप पसंद करता हूं, जब तक कि मेरी पूर्व टिप्पणी की तरह इसमें चारों ओर स्टाइल हो, क्योंकि यह मानसिक रूप से ट्रैक रखने के लिए कम स्थिति की गारंटी देता है - result_h1इसका उपयोग नहीं किया जा सकता है यदि यह मौजूद नहीं है, और 4 चर के बीच पाइपलाइन है स्पष्ट।
इज़काता 16

8
मुझे लगता है कि कोड है कि आम तौर पर डिबग करने के लिए आसान है कोड है कि डिबगिंग की जरूरत नहीं है।
रोब के

25

आपका पहला उदाहरण, एकल-असाइनमेंट-फॉर्म अपठनीय है, क्योंकि चुने हुए नाम पूरी तरह से अर्थहीन हैं। हो सकता है कि आपकी ओर से आंतरिक जानकारी का खुलासा न करने की कोशिश करने का एक तरीका हो सकता है, सही कोड उस संबंध में ठीक हो सकता है, हम नहीं कह सकते। वैसे भी, यह बहुत कम सूचना-घनत्व के कारण लंबे समय से घुमावदार है, जो आमतौर पर आसान समझ के लिए उधार नहीं देता है।

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

सार्थक नामों को प्रस्तुत करने के बाद, आप यह देख सकते हैं कि क्या कोई एक रूप प्राकृतिक लगता है, या यदि शूट करने के लिए एक सुनहरा मध्य है।

अब जब आपके पास पठनीय कोड है, तो अधिकांश बग स्पष्ट हो जाएंगे, और अन्य कम से कम आपके पास एक कठिन समय छिपा सकते हैं।


17

हमेशा की तरह, जब यह पठनीयता की बात आती है, तो विफलता चरम सीमा में होती है । आप किसी भी अच्छी प्रोग्रामिंग सलाह को ले सकते हैं , इसे धार्मिक नियम में बदल सकते हैं, और इसका उपयोग पूरी तरह से अपठनीय कोड बनाने के लिए कर सकते हैं। (यदि आप मुझे इस पर विश्वास नहीं करते हैं, तो इन दो IOCCC विजेताओं बोर्सनी और गोरेन की जांच करें और एक नज़र डालें कि कोड को पूरी तरह से अपठनीय प्रदान करने के लिए वे कितने अलग-अलग कार्यों का उपयोग करते हैं। संकेत: बोरसैनी एक फ़ंक्शन, गोरेन का उपयोग करता है, बहुत अधिक। ...)

आपके मामले में, दो चरम सीमाएं केवल 1 हैं) केवल एकल अभिव्यक्ति बयानों का उपयोग करते हुए, और 2) सब कुछ बड़े, प्रतिकूल और जटिल बयानों में शामिल हो रहा है। या तो चरम पर ले जाया गया आपके कोड को अपठनीय बनाता है।

आपका कार्य, एक प्रोग्रामर के रूप में, एक संतुलन बनाना है । आपके द्वारा लिखे गए प्रत्येक कथन के लिए, प्रश्न का उत्तर देना आपका कार्य है: "क्या यह कथन समझ में आसान है, और क्या यह मेरे कार्य को पठनीय बनाने के लिए काम करता है?"


मुद्दा यह है कि कोई एकल मापने योग्य बयान जटिलता नहीं है जो यह तय कर सकती है कि किसी एक बयान में शामिल होने के लिए क्या अच्छा है। उदाहरण के लिए लाइन लें:

double d = sqrt(square(x1 - x0) + square(y1 - y0));

यह काफी जटिल बयान है, लेकिन उनके नमक के लायक किसी भी प्रोग्रामर को तुरंत यह समझने में सक्षम होना चाहिए कि यह क्या करता है। यह काफी प्रसिद्ध पैटर्न है। जैसे, यह समकक्ष के मुकाबले बहुत अधिक पठनीय है

double dx = x1 - x0;
double dy = y1 - y0;
double dxSquare = square(dx);
double dySquare = square(dy);
double dSquare = dxSquare + dySquare;
double d = sqrt(dSquare);

जो अच्छी तरह से ज्ञात पैटर्न को सरल चरणों की प्रतीत होती अर्थहीन संख्या में तोड़ देता है। हालाँकि, आपके प्रश्न का कथन

var a = F(G1(H1(b1), H2(b2)), G2(c1));

यह मेरे लिए जटिल लगता है, भले ही यह दूरी की गणना से एक ऑपरेशन कम हो । बेशक, यह मेरे बारे F()में G1(), G2()और H1(), या , के बारे में कुछ भी नहीं जानने का एक सीधा परिणाम है H2()। अगर मैं उनके बारे में अधिक जानता हूं तो मैं अलग तरह से निर्णय ले सकता हूं। लेकिन यह ठीक समस्या है: एक बयान की सलाह देने योग्य जटिलता दृढ़ता से संदर्भ पर निर्भर करती है, और इसमें शामिल संचालन पर। और आप, एक प्रोग्रामर के रूप में, इस संदर्भ पर एक नज़र डालनी चाहिए और यह तय करना चाहिए कि किसी एक कथन में क्या शामिल किया जाए। यदि आप पठनीयता की परवाह करते हैं, तो आप इस ज़िम्मेदारी को कुछ स्थैतिक नियम से दूर नहीं कर सकते।


14

@ मुख्य, मुझे लगता है कि आपके प्रश्न के विश्लेषण में, आप गलती कर रहे हैं कि "पठनीयता" और "स्थिरता" दो अलग-अलग चीजें हैं।

क्या ऐसा कोड होना संभव है जो बनाए रखने योग्य लेकिन अपठनीय हो? इसके विपरीत, यदि कोड अत्यंत पठनीय है, तो यह पठनीय होने के कारण अप्राप्य क्यों हो जाएगा? मैंने कभी किसी ऐसे प्रोग्रामर के बारे में नहीं सुना, जो एक-दूसरे को चुनने के लिए इन कारकों को एक-दूसरे के खिलाफ करता हो!

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

लेकिन मैं निश्चित रूप से यह नहीं कहता हूं कि फंक्शन कॉल्स को कभी भी नेस्टेड नहीं होना चाहिए। यह परिस्थितियों में निर्णय का सवाल है।

मैं कहूंगा कि निर्णय पर निम्नलिखित बिंदु होंगे:

  1. यदि कहे जाने वाले कार्य मानक गणितीय कार्यों का प्रतिनिधित्व करते हैं, तो वे उन कार्यों की तुलना में अधिक सक्षम होते हैं जो कुछ अस्पष्ट डोमेन लॉजिक का प्रतिनिधित्व करते हैं जिनके परिणाम अप्रत्याशित होते हैं और जरूरी नहीं कि उनका मूल्यांकन पाठक द्वारा मानसिक रूप से किया जाए।

  2. एकल पैरामीटर वाला फ़ंक्शन कई मापदंडों वाले फ़ंक्शन की तुलना में एक घोंसले (या तो आंतरिक या बाहरी फ़ंक्शन के रूप में) में भाग लेने में अधिक सक्षम है। अलग-अलग घोंसले के स्तरों पर विभिन्न धमनी के कार्यों को मिलाकर कोड को सूअर के कान की तरह देखने के लिए प्रवण होता है।

  3. एक प्रकार का फ़ंक्शन जो प्रोग्रामर एक विशेष तरीके से व्यक्त देखने के आदी हैं - शायद इसलिए कि यह एक मानक गणितीय तकनीक या समीकरण का प्रतिनिधित्व करता है, जिसका एक मानक कार्यान्वयन है - अगर यह मध्यवर्ती चर में टूट गया है तो इसे पढ़ना और सत्यापित करना अधिक कठिन हो सकता है।

  4. फ़ंक्शन कॉल का एक छोटा सा घोंसला जो सरल कार्यक्षमता करता है और पढ़ने के लिए पहले से ही स्पष्ट है, और फिर अत्यधिक टूट गया है और एटमाइज़्ड है, एक से अधिक पढ़ने में मुश्किल होने में सक्षम है जो कि बिल्कुल भी टूट नहीं गया था।


3
+1 करने के लिए "क्या यह संभव है कि कोड बनाए रखने योग्य लेकिन अपठनीय हो?"। मेरी पहली सोच भी यही थी।
रॉनजॉन

4

दोनों ही उपप्रधान हैं। टिप्पणियों पर विचार करें।

// Calculating torque according to Newton/Dominique, 4th ed. pg 235
var a = F(G1(H1(b1), H2(b2)), G2(c1));

या सामान्य लोगों के बजाय विशिष्ट कार्य:

var a = Torque_NewtonDominique(b1,b2,c1);

यह तय करते समय कि कौन सा परिणाम वर्तनी में आता है, प्रत्येक कथन के लिए लागत (कॉपी बनाम संदर्भ, एल-मूल्य बनाम आर-मूल्य), पठनीयता और जोखिम को ध्यान में रखें।

उदाहरण के लिए, अपनी इकाई पर सरल इकाई / प्रकार रूपांतरणों को स्थानांतरित करने से कोई अतिरिक्त मूल्य नहीं है, क्योंकि ये पढ़ने में आसान हैं और असफल होने की संभावना बेहद कम है:

var radians = ExtractAngle(c1.Normalize())
var a = Torque(b1.ToNewton(),b2.ToMeters(),radians);

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


आरजी पास करने की लागत को फिर से लें: अनुकूलन के दो नियम हैं। 1) नहीं। 2) (केवल विशेषज्ञों के लिए) अभी तक नहीं
रबरडैक

1

पठनीयता बनाए रखने का प्रमुख हिस्सा है। मुझ पर शक? एक बड़ी परियोजना को उस भाषा में चुनें जिसे आप नहीं जानते (संभवतः प्रोग्रामिंग भाषा और प्रोग्रामर दोनों की भाषा), और देखें कि आप इसे कैसे फिर से तैयार करेंगे ...

मैं पठनीयता को put० और ९ ० के बीच रख-रखाव के रूप में रखूंगा। अन्य 10-20 प्रतिशत यह कैसे refenoring करने के लिए उत्तरदायी है।

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

संबंधित नहीं पर, आप कहते हैं कि पृष्ठ पर अधिक तर्क पठनीयता को प्रभावित करता है। यह गलत है, मीट्रिक पृष्ठ नहीं है, यह विधि है, और LESS तर्क में एक विधि शामिल है, यह अधिक पठनीय है।

पठनीय का अर्थ है कि प्रोग्रामर अपने सिर में तर्क (इनपुट, आउटपुट और एल्गोरिथम) को पकड़ सकता है। यह जितना अधिक होता है, LESS एक प्रोग्रामर इसे समझ सकता है। साइक्लोमैटिक जटिलता पर पढ़ें।


1
पठनीयता के बारे में आप जो कहते हैं, मैं उससे सहमत हूं। लेकिन मैं इस बात से सहमत नहीं हूं कि एक तार्किक ऑपरेशन को अलग-अलग तरीकों से क्रैक करना , आवश्यक रूप से इसे अलग-अलग लाइनों में क्रैक करने की तुलना में अधिक पठनीय बनाता है (दोनों तकनीकें, जो अधिक उपयोग होने पर, सरल तर्क को कम पठनीय बना सकती हैं, और पूरे प्रोग्राम को अधिक अव्यवस्थित बनाती हैं) - यदि आप चीजों को बहुत दूर तक तोड़ते हैं, तो आप असेंबली भाषा मैक्रोज़ का अनुकरण करते हैं और दृष्टि खो देते हैं कि वे समग्र रूप से कैसे एकीकृत होते हैं। इसके अलावा, इस अलग पद्धति में, आपको अभी भी एक ही समस्या का सामना करना पड़ेगा: कॉल को घोंसला करें, या उन्हें मध्यवर्ती चर में क्रैक करें।
स्टीव

@Steve: मैंने हमेशा ऐसा करने के लिए नहीं कहा, लेकिन अगर आप एक मान प्राप्त करने के लिए 5 लाइनों का उपयोग करने के बारे में सोच रहे हैं, तो एक अच्छा मौका है कि एक फ़ंक्शन बेहतर होगा। कई लाइनों बनाम जटिल रेखा के लिए: यदि यह एक अच्छे नाम के साथ एक फ़ंक्शन है, तो दोनों समान रूप से अच्छी तरह से काम करेंगे।
जमेरो

1

भले ही आप सी # या सी ++ में हों, जब तक आप डिबग बिल्ड में हैं, एक संभावित समाधान कार्यों को लपेट रहा है।

var a = F(G1(H1(b1), H2(b2)), G2(c1));

आप ऑनलाइन अभिव्यक्ति लिख सकते हैं, और फिर भी इंगित किया जा सकता है जहां समस्या केवल स्टैक ट्रेस को देखकर है।

returnType F( params)
{
    returnType RealF( params);
}

बेशक, यदि आप एक ही फ़ंक्शन को एक ही पंक्ति में कई बार कॉल करते हैं, तो आप यह नहीं जान सकते कि कौन सा फ़ंक्शन है, हालांकि आप अभी भी इसे पहचान सकते हैं:

  • फ़ंक्शन मापदंडों को देखते हुए
  • यदि पैरामीटर समान हैं और फ़ंक्शन के साइड इफेक्ट नहीं हैं तो दो समान कॉल 2 समान कॉल आदि बन जाते हैं।

यह एक चांदी की गोली नहीं है, लेकिन इतना बुरा आधा रास्ता नहीं है।

यह उल्लेख करने के लिए कि फ़ंक्शन की रैपिंग समूह कोड की पठनीयता के लिए और भी अधिक फायदेमंद हो सकती है:

type CallingGBecauseFTheorem( T b1, C b2)
{
     return G1( H1( b1), H2( b2));
}

var a = F( CallingGBecauseFTheorem( b1,b2), G2( c1));

1

मेरी राय में, स्व-दस्तावेजीकरण कोड भाषा की परवाह किए बिना बनाए रखने और पठनीयता दोनों के लिए बेहतर है।

ऊपर दिया गया बयान सघन है, लेकिन "स्व दस्तावेज":

double d = sqrt(square(x1 - x0) + square(y1 - y0));

जब चरणों में टूट जाता है (परीक्षण के लिए आसान, निश्चित रूप से) ऊपर वर्णित सभी संदर्भ खो देता है:

double dx = x1 - x0;
double dy = y1 - y0;
double dxSquare = square(dx);
double dySquare = square(dy);
double dSquare = dxSquare + dySquare;
double d = sqrt(dSquare);

और स्पष्ट रूप से चर और फ़ंक्शन नामों का उपयोग करते हुए जो उनके उद्देश्य को स्पष्ट रूप से अमूल्य बताते हैं।

यहां तक ​​कि "यदि" ब्लॉक स्व-दस्तावेजीकरण में अच्छा या बुरा हो सकता है। यह बुरा है क्योंकि आप आसानी से पहले 2 स्थितियों को तीसरे का परीक्षण करने के लिए मजबूर नहीं कर सकते ... सभी असंबंधित हैं:

if (Bill is the boss) && (i == 3) && (the carnival is next weekend)

यह अधिक "सामूहिक" अर्थ देता है और परीक्षण की स्थिति बनाने में आसान है:

if (iRowCount == 2) || (iRowCount == 50) || (iRowCount > 100)

और यह कथन एक स्व-दस्तावेजी परिप्रेक्ष्य से देखे गए पात्रों का एक यादृच्छिक स्ट्रिंग है:

var a = F(G1(H1(b1), H2(b2)), G2(c1));

उपरोक्त कथन को देखते हुए, यदि H1 और H2 दोनों एक ही "H" फ़ंक्शन में एकीकृत होने के बजाय H1 और H2 दोनों एक ही "सिस्टम स्टेट वैरिएबल" को बदल देते हैं, तो स्थिरता अभी भी एक बड़ी चुनौती है, क्योंकि कोई अंततः H1 को बदले बिना भी सोच में बदल जाएगा। H2 देखने के लिए कार्य करता है और H2 को तोड़ सकता है।

मेरा मानना ​​है कि अच्छा कोड डिज़ाइन बहुत चुनौतीपूर्ण है क्योंकि कोई कठिन और तेज़ नियम नहीं है जिसे व्यवस्थित रूप से पता लगाया जा सके और लागू किया जा सके।

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