स्वच्छ कोड प्रथाओं का पालन करके आप अधिक कोड को कैसे सही ठहराते हैं?


106

मॉडरेटर नोट
इस सवाल पर पहले ही सत्रह उत्तर दिए गए हैं। नया उत्तर पोस्ट करने से पहले, कृपया मौजूदा उत्तर पढ़ें और सुनिश्चित करें कि आपका दृष्टिकोण पहले से पर्याप्त रूप से कवर नहीं किया गया है।

मैं रॉबर्ट मार्टिन की "क्लीन कोड" पुस्तक में सुझाई गई कुछ प्रथाओं का पालन कर रहा हूं, विशेष रूप से वे जो मैं जिस प्रकार के सॉफ़्टवेयर के साथ काम करता हूं और जो मेरे लिए समझ में आता है (मैं इसे हठधर्मिता के रूप में पालन नहीं करता हूं) पर लागू होता है ।

हालाँकि, मैंने देखा है कि "क्लीन" कोड जो मैं लिखता हूँ, वह अधिक कोड है अगर मैंने कुछ प्रथाओं का पालन नहीं किया है। इसके लिए विशिष्ट अभ्यास निम्न हैं:

  • सशर्त अतिक्रमण

इसलिए इसके बजाय

if(contact.email != null && contact.emails.contains('@')

मैं इस तरह एक छोटा सा तरीका लिख ​​सकता था

private Boolean isEmailValid(String email){...}
  • एक अन्य निजी विधि के साथ एक इनलाइन टिप्पणी को प्रतिस्थापित करना, ताकि विधि नाम इसके शीर्ष पर एक इनलाइन टिप्पणी होने के बजाय खुद का वर्णन करता है
  • एक वर्ग को बदलने का केवल एक कारण होना चाहिए

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

मुझे पता है कि अति पर लिया गया कोई भी अभ्यास हानिकारक हो सकता है।

मैं जिस ठोस प्रश्न की तलाश में हूँ, वह है:

क्या यह साफ कोड लिखने का स्वीकार्य बायप्रोडक्ट है? यदि हां, तो कुछ तर्क क्या हैं जिनका उपयोग मैं इस तथ्य को सही ठहराने के लिए कर सकता हूं कि अधिक एलओसी लिखे गए हैं?

संगठन विशेष रूप से अधिक एलओसी के बारे में चिंतित नहीं है, लेकिन अधिक एलओसी बहुत बड़ी कक्षाओं में परिणाम कर सकता है (जो फिर से, पठनीयता के लिए उपयोग-एक बार सहायक कार्यों के एक समूह के बिना एक लंबी विधि के साथ प्रतिस्थापित किया जा सकता है)।

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

यह विशिष्ट चिंता है ... उन कक्षाओं में एक एकल वर्ग हो सकता है जो अभी भी कई छोटी विधियों की सहायता के बिना "एक बात" प्राप्त करता है। यह शायद 3 या 4 विधियों और कुछ टिप्पणियों के साथ एक एकल वर्ग हो सकता है।


98
यदि आपका संगठन आपके कोड आधारों के लिए मीट्रिक के रूप में केवल LOC का उपयोग करता है , तो स्वच्छ कोड को सही ठहराना शुरू करने के लिए निराशाजनक है।
किलन फ़ॉथ

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

29
एक उत्तर नहीं है, लेकिन एक बिंदु बनाया जाना है: संभव के रूप में कुछ पंक्तियों / प्रतीकों के साथ कोड लिखने के बारे में एक पूरी अवज्ञा है। codegolf.stackexchange.com एक तर्क दे सकता है कि अधिकांश उत्तर उतने पठनीय नहीं हैं जितने कि वे हो सकते हैं।
एंटीथियोस

14
हर बेहतरीन प्रैक्टिस के पीछे कारण जानें न सिर्फ खुद पर राज करना। कारणों के बिना निम्नलिखित नियम कार्गो पंथ हैं। हर एक नियम का अपना एक कारण होता है।
घुमारवीं

9
बस एक तरफ, और अपने उदाहरण का उपयोग करते हुए, कभी-कभी चीजों को तरीकों पर धकेलने से आपको लगता है कि: "शायद एक पुस्तकालय समारोह है जो आप कर सकते हैं"। उदाहरण के लिए, एक ईमेल पते को मान्य करने के लिए, आप एक System.Net.Mail.Mail.Address बना सकते हैं जो इसे आपके लिए मान्य करेगा। आप इसे सही करने के लिए उस पुस्तकालय के लेखक पर भरोसा कर सकते हैं। इसका मतलब है कि आपके कोडबेस में अधिक सार होगा, और आकार में कमी होगी।
ग्रेगरी करी

जवाबों:


130

... हम एक बहुत बड़ी टीम हैं जो अपेक्षाकृत बड़े और अनजाने कोड कोड (जो हमें विरासत में मिले) का समर्थन करते हैं, इसलिए कुछ डेवलपर्स / प्रबंधक चीजों को प्राप्त करने के लिए कम कोड लिखने में मूल्य देखते हैं ताकि हमारे पास बनाए रखने के लिए कम कोड हो

इन लोगों ने कुछ की सही पहचान की है: वे चाहते हैं कि कोड को बनाए रखना आसान हो। हालांकि वे गलत हो गए हैं, लेकिन यह मानते हुए कि कम कोड है, इसे बनाए रखना जितना आसान है।

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

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


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

63
ज़रूर, लेकिन इन परीक्षणों को बनाए रखने में खो गया समय तब तक बौना हो जाता है जब तक कि आप उन बगों का निदान और फिक्सिंग नहीं कर लेते जिन्हें परीक्षण रोकते हैं।
मेटाफ़ाइट

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

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

22
@JackAidley आप किसी भी एपीआई या इंटरफ़ेस को बदले बिना बहुत रिफ्लेक्टर कर सकते हैं। इसका मतलब है कि आप इकाई या कार्यात्मक परीक्षणों में एक भी लाइन को बदलने के बिना कोड को संशोधित करते हुए पागल हो सकते हैं। यही है, अगर आपके परीक्षण एक विशिष्ट कार्यान्वयन का परीक्षण नहीं करते हैं।
एरिक डुमिनील

155

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

छोटे टुकड़ों का पुन: उपयोग करना भी आसान है, जो आपके समग्र कार्यक्रम के लिए आपकी लाइन की संख्या को कम करता है। EmailValidatorसभी जगह एक का उपयोग किया जा सकता है। कोड की कुछ पंक्तियाँ जो ईमेल सत्यापन करती हैं, लेकिन डेटाबेस एक्सेस कोड के साथ एक साथ जांच की जाती हैं, उनका पुन: उपयोग नहीं किया जा सकता है।

और फिर विचार करें कि यदि ईमेल सत्यापन नियमों को कभी भी बदलने की आवश्यकता हो तो क्या किया जाना चाहिए - जो आप बल्कि: एक ज्ञात स्थान; या कई स्थानों, संभवतः कुछ याद आ रही है?


10
बहुत बेहतर जवाब तो थकाऊ "इकाई परीक्षण आपकी सभी समस्याओं को हल करता है"
डिर्क बोअर

13
यह उत्तर एक महत्वपूर्ण बिंदु पर हिट करता है कि अंकल बॉब और दोस्त हमेशा याद करने लगते हैं - छोटे तरीकों में फिर से कायम करना केवल तभी मदद करता है जब आपको यह जानने के लिए सभी छोटे तरीकों को पढ़ने की ज़रूरत नहीं है कि आपका कोड क्या कर रहा है। ईमेल पतों को मान्य करने के लिए एक अलग वर्ग बनाना बुद्धिमानी है। कोड iterations < _maxIterationsको एक विधि में खींचना जिसे बेवकूफ कहा जाता ShouldContinueToIterateहै ।
बीजे मायर्स

4
@ दाविदनो: "उपयोगी होने के लिए! =" आपकी सभी समस्याओं का हल करता है "
क्रिश्चियन हैकल

2
@DavidArno: जब कोई व्यक्ति उस इकाई परीक्षण को लागू करने वाले लोगों के बारे में शिकायत करता है "आपकी सभी समस्याओं को हल करता है", तो उनका स्पष्ट रूप से मतलब है कि जो लोग उस इकाई का परीक्षण करते हैं, या कम से कम सॉफ्टवेयर इंजीनियरिंग में लगभग सभी समस्याओं के समाधान में योगदान करते हैं। मुझे लगता है कि युद्ध, गरीबी और बीमारी को समाप्त करने के तरीके के रूप में किसी को भी इकाई परीक्षण का सुझाव देने का आरोप नहीं है। इसे लगाने का एक और तरीका यह है कि इस सवाल पर, न केवल सामान्य तौर पर एसई पर, कई उत्तरों में इकाई परीक्षण की चरम सीमा की आलोचना की जा रही है।
क्रिश्चियन हैकल

2
हाय @DavidArno, मेरी टिप्पणी स्पष्ट रूप से एक हाइपरबोले नहीं एक स्ट्रोमैन थी;) मेरे लिए यह इस तरह है: मैं पूछ रहा हूं कि मेरी कार को कैसे तय किया जाए और धार्मिक लोग आएं और मुझे बताएं कि मुझे कम पापी जीवन जीना चाहिए। सिद्धांत रूप में कुछ चर्चा करने लायक है, लेकिन यह वास्तव में कारों को ठीक करने में बेहतर होने में मेरी मदद नहीं कर रहा है।
डर्क बोअर

34

बिल गेट्स को यह कहने के लिए प्रसिद्ध किया गया था, "कोड की लाइनों द्वारा प्रोग्रामिंग प्रगति को मापना वजन द्वारा विमान निर्माण प्रगति को मापने के समान है।"

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

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

आप कहाँ मुसीबत में जब आप एक बनाने के है isEmailValid, जो विधि साइड इफेक्ट या चेक बातें ई-मेल के अलावा अन्य गया है क्योंकि यह है बदतर बस यह सब लिख बाहर से। यह बदतर है क्योंकि यह भ्रामक है और मुझे इसकी वजह से एक बग याद आ सकती है।

हालांकि स्पष्ट रूप से आप इस मामले में ऐसा नहीं कर रहे हैं, इसलिए मैं आपको प्रोत्साहित करूंगा कि आप जो कर रहे हैं उसे जारी रखें। आपको हमेशा अपने आप से पूछना चाहिए कि क्या परिवर्तन करने से, पढ़ना आसान है, और यदि आपका मामला ऐसा है, तो इसे करें!


1
हालांकि, विमान का वजन एक महत्वपूर्ण मीट्रिक है। और डिजाइन के दौरान अपेक्षित वजन की बारीकी से निगरानी की जाती है। प्रगति के संकेत के रूप में नहीं, बल्कि एक बाधा के रूप में। कोड की निगरानी लाइनों का सुझाव है कि अधिक बेहतर है, जबकि विमान डिजाइन में कम वजन बेहतर है। इसलिए मुझे लगता है कि मिस्टर गेट्स अपनी बात के लिए बेहतर उदाहरण चुन सकते थे।
जॉस

21
@jos जिस विशेष टीम ओपी के साथ काम कर रहा है, ऐसा प्रतीत होता है कि कम LOC को 'बेहतर' माना जाता है। बिल गेट्स का कहना था कि एलओसी किसी भी सार्थक तरीके से प्रगति से संबंधित नहीं है , ठीक उसी तरह जैसे विमान निर्माण का वजन सार्थक तरीके से प्रगति से संबंधित नहीं है। निर्माणाधीन विमान में अपने अंतिम वजन का 95% अपेक्षाकृत जल्दी हो सकता है, लेकिन यह सिर्फ एक खाली शेल होगा जिसमें कोई नियंत्रण प्रणाली नहीं होगी, यह 95% पूर्ण नहीं है। सॉफ्टवेयर में भी, यदि किसी प्रोग्राम में कोड की 100k लाइनें हैं, तो इसका मतलब यह नहीं है कि प्रत्येक 1000 लाइनें 1% कार्यक्षमता प्रदान करती हैं।
मि। मिंडोर

7
प्रगति की निगरानी एक कठिन काम है, है ना? गरीब प्रबंधक।
Jos

@jos: कोड में भी समान कार्यक्षमता के लिए कम लाइनें होना बेहतर है, अगर बाकी सब समान हो।
रेमकोगर्लिच

@ जोस ध्यान से पढ़ें। गेट्स इस बारे में कुछ नहीं कहते हैं कि क्या वजन किसी विमान के लिए एक महत्वपूर्ण उपाय है। उनका कहना है कि हवाई जहाज बनाने की प्रगति के लिए वजन एक भयानक उपाय है । आखिरकार, उस उपाय के द्वारा जैसे ही आपके पास जमीन पर फेंका हुआ पूरा पतवार हो, आप मूल रूप से पूरे विमान के वजन के 9x% के लिए उस मात्रा में हो।
वू

23

इसलिए कुछ डेवलपर्स / प्रबंधक चीजों को प्राप्त करने के लिए कम कोड लिखने में मूल्य देखते हैं ताकि हमारे पास बनाए रखने के लिए कम कोड हो

यह वास्तविक लक्ष्य पर दृष्टि खोने का मामला है।

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

बाकी जवाब इस बात के उदाहरण हैं कि स्वच्छ कोड कैसे समय के लाभ को जन्म दे सकता है।


लॉगिंग

एक आवेदन (ए) लें जिसमें कोई लॉगिंग नहीं है। अब एप्लिकेशन B बनाएं, जो एक ही एप्लिकेशन A है लेकिन लॉगिंग के साथ। बी में हमेशा कोड की अधिक लाइनें होंगी, और इस तरह आपको अधिक कोड लिखना होगा।

लेकिन बहुत समय के लिए मुद्दों और कीड़ों की जांच में डूब जाएगा, और यह पता लगाएगा कि क्या गलत हुआ।

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

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

यह मिनट, घंटे या दिनों की बचत के मामले में हो सकता है; कोडबेस के आकार और जटिलता के आधार पर।


प्रतिगमन

एप्लिकेशन A लें, जो DRY-friendly बिल्कुल नहीं है।
अनुप्रयोग B को लें, जो DRY है, लेकिन अतिरिक्त सार के कारण अधिक लाइनों की आवश्यकता समाप्त हो गई है।

एक परिवर्तन अनुरोध दायर किया जाता है, जिसे तर्क में बदलाव की आवश्यकता होती है।

आवेदन बी के लिए, डेवलपर परिवर्तन अनुरोध के अनुसार (अद्वितीय, साझा) तर्क बदलता है।

आवेदन ए के लिए, डेवलपर को इस तर्क के सभी उदाहरणों को बदलना होगा, जहां वह इसे उपयोग किए जाने को याद रखता है।

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

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


डेवलपर की परिवर्तनशीलता

डेवलपर ए निर्मित एप्लिकेशन ए। कोड साफ नहीं है और न ही पठनीय है, लेकिन यह एक आकर्षण की तरह काम करता है और उत्पादन में चल रहा है। अप्रत्याशित रूप से, कोई प्रलेखन भी नहीं है।

डेवलपर A छुट्टियों के कारण एक महीने के लिए अनुपस्थित है। एक आपातकालीन परिवर्तन अनुरोध दायर किया जाता है। यह देव ए के लौटने के लिए एक और तीन सप्ताह इंतजार नहीं कर सकता।

डेवलपर बी को इस बदलाव को अंजाम देना है। उसे अब पूरे कोडबेस को पढ़ने की जरूरत है, यह समझें कि सब कुछ कैसे काम करता है, क्यों काम करता है, और इसे पूरा करने की कोशिश करता है। इसमें उम्र लगती है, लेकिन मान लें कि वह इसे तीन सप्ताह के समय में कर सकता है।

उसी समय, एप्लिकेशन बी (जो देव बी बनाया गया) में एक आपातकालीन स्थिति है। देव बी का कब्जा है, लेकिन देव सी उपलब्ध है, भले ही वह कोडबेस को नहीं जानता है। हम क्या करें?

  • यदि हम B को A पर कार्य करते हुए रखते हैं, और C को B पर कार्य करने के लिए रखते हैं, तो हमारे पास दो डेवलपर हैं, जो नहीं जानते कि वे क्या कर रहे हैं, और कार्य उप-रूप से निष्पादित किया जा रहा है।
  • यदि हम B को A से दूर करते हैं और उसे B करते हैं, और अब हम C को A पर रखते हैं, तो डेवलपर B के सभी कार्य (या इसका एक महत्वपूर्ण भाग) समाप्त हो सकते हैं। यह संभावित दिनों / हफ्तों का व्यर्थ प्रयास है।

देव ए अपनी छुट्टी से वापस आता है, और देखता है कि बी ने कोड को नहीं समझा, और इस तरह इसे बुरी तरह से लागू किया। यह बी की गलती नहीं है, क्योंकि उन्होंने सभी उपलब्ध संसाधनों का उपयोग किया, स्रोत कोड अभी पर्याप्त रूप से पठनीय नहीं था। क्या A को अब कोड की पठनीयता तय करने में समय बिताना होगा?


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

प्रबंधन को यह समझने की जरूरत है कि अब एक छोटा कार्य आपको भविष्य में कई लंबे कार्यों से बचाएगा। योजना बनाने में असफ़ल होना योजना में असफ़ल होना है।

यदि हां, तो कुछ तर्क क्या हैं जिनका उपयोग मैं इस तथ्य को सही ठहराने के लिए कर सकता हूं कि अधिक एलओसी लिखे गए हैं?

मेरा गोटो स्पष्टीकरण प्रबंधन से पूछ रहा है कि वे क्या पसंद करेंगे: 100KLOC कोडबेस वाला एक आवेदन जिसे तीन महीने में विकसित किया जा सकता है, या 50KLOC कोडबेस जिसे छह महीने में विकसित किया जा सकता है।

वे स्पष्ट रूप से छोटे विकास के समय को उठाएंगे , क्योंकि प्रबंधन KLOC के बारे में परवाह नहीं करता है । केएलओसी पर ध्यान केंद्रित करने वाले प्रबंधक प्रबंधन करने की कोशिश कर रहे हैं, इसके बारे में जानकारी नहीं होने के बावजूद, माइक्रोक्रोमिंग कर रहे हैं।


23

मुझे लगता है कि आपको "क्लीन कोड" प्रथाओं को लागू करने के बारे में बहुत सावधान रहना चाहिए जब वे अधिक समग्र जटिलता की ओर ले जाते हैं। शीघ्रपतन कई बुरी चीजों की जड़ है।

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

मैं यह नहीं कह रहा हूं कि आपको सशर्त नहीं निकालना चाहिए , बस आपको सावधानीपूर्वक विचार करना चाहिए यदि आपको आवश्यकता है।

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

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

मैं कहूंगा, यदि संदेह है, तो हमेशा सबसे सरल और सबसे सरल कोड चुनें।


7
मुझे सहमत होना होगा, हर सशर्त को एक मान्यता पद्धति में बदलना रखरखाव और कोड समीक्षाओं की बात आने पर अधिक अवांछित जटिलता का परिचय दे सकता है। अब आपको कोड में आगे और पीछे स्विच करना होगा ताकि यह सुनिश्चित किया जा सके कि आपके सशर्त तरीके सही हैं। और क्या होता है जब आपके पास एक ही मूल्य के लिए अलग-अलग स्थितियां होती हैं? अब आपके पास कई छोटे तरीकों के साथ एक नामकरण दुःस्वप्न हो सकता है जो केवल एक बार कॉल करते हैं और ज्यादातर समान दिखते हैं।
pboss3010

7
आसानी से यहाँ सबसे अच्छा जवाब। विशेष रूप से अवलोकन (तीसरे पैराग्राफ में) कि जटिलता केवल एक पूरे के रूप में पूरे कोड की संपत्ति नहीं है, लेकिन कुछ मौजूद है, और एक साथ कई अमूर्त स्तरों पर अलग है।
क्रिश्चियन हैकल

2
मुझे लगता है कि इसे लगाने का एक तरीका यह है कि सामान्य तौर पर, किसी शर्त को निकालने का काम केवल तभी किया जाना चाहिए जब उस स्थिति के लिए एक सार्थक, गैर-अस्पष्ट नाम हो। यह एक आवश्यक लेकिन पर्याप्त स्थिति नहीं है।
जिमीजैम

Re "... क्योंकि अब आपके पास एक फ़ंक्शन है जो प्रोग्राम में अधिक बिंदुओं से दिखाई देता है" : पास्कल में स्थानीय कार्यों के लिए संभव है - "... प्रत्येक प्रक्रिया या फ़ंक्शन के पास गोटो लेबल, कॉन्स्टेंट की अपनी घोषणाएं हो सकती हैं। , प्रकार, चर, और अन्य प्रक्रियाओं और कार्यों, ... "
पीटर मोर्टेंसन

2
@PeterMortensen: यह C # और जावास्क्रिप्ट में भी संभव है। और वह महान है! लेकिन बिंदु रहता है, एक फ़ंक्शन, यहां तक ​​कि एक स्थानीय फ़ंक्शन, इनलाइन कोड के टुकड़े की तुलना में एक बड़े दायरे में दिखाई देता है।
जैक्सबी

9

मैं इंगित करता हूँ कि इसमें कुछ भी गलत नहीं है:

if(contact.email != null && contact.email.contains('@')

कम से कम यह मानते हुए कि यह एक बार उपयोग किया गया है।

मुझे इससे बहुत आसानी से समस्या हो सकती है:

private Boolean isEmailValid(String email){
   return email != null && email.contains('@');
}

कुछ चीजें जिन्हें मैं देखूंगा:

  1. यह निजी क्यों है? यह एक संभावित उपयोगी ठूंठ जैसा दिखता है। क्या यह एक निजी पद्धति होने के लिए पर्याप्त उपयोगी है और इसका कोई भी मौका अधिक व्यापक रूप से उपयोग नहीं किया जा रहा है?
  2. मैं व्यक्तिगत रूप से IsValidEmail विधि का नाम नहीं दूंगा, संभवतः ContainsAtSign या LooksVaguelyLikeEmailAddress क्योंकि यह लगभग कोई वास्तविक सत्यापन नहीं करता है, जो कि शायद अच्छा है, शायद यह नहीं है कि क्या उम्मीद है।
  3. क्या यह एक से अधिक बार उपयोग किया जा रहा है?

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

दूसरी ओर मैंने देखा है कि विधियाँ कुछ इस तरह से होती हैं:

if (contact.email != null && contact.email.contains('@')) { ... }
else if (contact.email != null && contact.email.contains('@') && contact.email.contains("@mydomain.com")) { //headquarters email }
else if (contact.email != null && contact.email.contains('@') && (contact.email.contains("@news.mydomain.com") || contact.email.contains("@design.mydomain.com") ) { //internal contract teams }

वह उदाहरण स्पष्ट रूप से DRY नहीं है।

या यहां तक ​​कि सिर्फ अंतिम कथन एक और उदाहरण दे सकता है:

if (contact.email != null && contact.email.contains('@') && (contact.email.contains("@news.mydomain.com") || contact.email.contains("@design.mydomain.com") )

कोड को अधिक पठनीय बनाने के लिए लक्ष्य होना चाहिए:

if (LooksSortaLikeAnEmail(contact.Email)) { ... }
else if (LooksLikeFromHeadquarters(contact.Email)) { ... }
else if (LooksLikeInternalEmail(contact.Email)) { ... }

एक अन्य परिदृश्य:

आपके पास एक विधि हो सकती है जैसे:

public void SaveContact(Contact contact){
   if (contact.email != null && contact.email.contains('@'))
   {
       contacts.Add(contact);
       contacts.Save();
   }
}

यदि यह आपके व्यापार तर्क को फिट करता है और इसका पुन: उपयोग नहीं किया जाता है तो यहां कोई समस्या नहीं है।

लेकिन जब कोई पूछता है कि "क्यों @ 'बचाया गया है, क्योंकि यह सही नहीं है!" और आप किसी प्रकार के वास्तविक सत्यापन को जोड़ने का निर्णय लेते हैं, फिर इसे निकालें!

आपको खुशी होगी कि जब आपने राष्ट्रपतियों के लिए दूसरे ईमेल अकाउंट Pr3 $ sid3nt @ h0m3! @ Mydomain.com पर अकाउंट करने की जरूरत महसूस की और सभी को बाहर करने का प्रयास किया और RFC 2822 का समर्थन किया।

पठनीयता पर:

// If there is an email property and it contains an @ sign then process
if (contact.email != null && contact.email.contains('@'))

यदि आपका कोड यह स्पष्ट है, तो आपको यहां टिप्पणियों की आवश्यकता नहीं है। वास्तव में, आपको यह कहने के लिए टिप्पणियों की आवश्यकता नहीं है कि कोड अधिकांश समय क्या कर रहा है, बल्कि यह क्यों कर रहा है:

// The UI passes '@' by default, the DBA's made this column non-nullable but 
// marketing is currently more concerned with other fields and '@' default is OK
if (contact.email != null && contact.email.contains('@'))

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

संक्षेप में: इन बातों को न नापें; सिद्धांत है कि पाठ (सूखा, ठोस, KISS) से बनाया गया था पर ध्यान दें।

// A valid class that does nothing
public class Nothing 
{

}

3
Whether the comments above an if statement or inside a tiny method is to me, pedantic.यह एक "पुआल है जिसने ऊंट की पीठ को तोड़ दिया" समस्या। आप सही हैं कि यह एक बात विशेष रूप से एकमुश्त पढ़ना मुश्किल नहीं है। लेकिन अगर आप एक बड़ा विधि (जैसे एक बड़े आयात) जो इन छोटे मूल्यांकन के दर्जनों है, इन पठनीय विधि के नाम में समाहित होने है ( IsUserActive, GetAverageIncome, MustBeDeleted, ...) कोड को पढ़ने पर एक उल्लेखनीय सुधार हो जाएगा। उदाहरण के साथ समस्या यह है कि यह केवल एक पुआल को देखता है, न कि पूरे बंडल को जो ऊंट की पीठ को तोड़ता है।
फ्लेटर

@ मुझे और मुझे उम्मीद है कि यह पाठक की भावना है।
अथोमसेफेरे

1
यह "एनकैप्सुलेशन" एक विरोधी पैटर्न है, और जवाब वास्तव में यह दर्शाता है। हम डिबगिंग के उद्देश्यों और कोड को विस्तारित करने के उद्देश्यों के लिए कोड को पढ़ने के लिए वापस आते हैं। दोनों मामलों में यह समझना कि कोड वास्तव में क्या करता है महत्वपूर्ण है। कोड ब्लॉक शुरू if (contact.email != null && contact.email.contains('@'))छोटी गाड़ी है। यदि असत्य है, तो रेखाओं में से कोई भी सत्य नहीं हो सकता है। LooksSortaLikeAnEmailब्लॉक में ऐसा बिल्कुल नहीं है । कोड की एकल पंक्ति वाला एक फ़ंक्शन यह बताने से बेहतर नहीं है कि लाइन कैसे काम करती है।
क्विक

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

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

6

क्लीन कोड एक उत्कृष्ट पुस्तक है, और अच्छी तरह से पढ़ने लायक है, लेकिन यह ऐसे मामलों पर अंतिम अधिकार नहीं है।

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

एक विकल्प जब यह पूरी तरह से नया फ़ंक्शन बनाने के लायक नहीं है, तो बस एक मध्यवर्ती चर का उपयोग करना है:

boolean isEmailValid = (contact.email != null && contact.emails.contains('@');

if (isEmailValid) {
...

यह कोड को फ़ाइल के चारों ओर कूदने के बिना अनुसरण करने में आसान बनाने में मदद करता है।

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


कुछ हालत के पास कोड की अतिरिक्त लाइन के बारे में चिंतित हैं (मैं बिल्कुल नहीं), लेकिन शायद आपके जवाब में यह पता है।
पीटर मोर्टेंसन

5

इस तथ्य को ध्यान में रखते हुए कि "ई-मेल मान्य" स्थिति है जो आपके पास वर्तमान में बहुत अमान्य ईमेल पते को स्वीकार करेगी " @", मुझे लगता है कि आपके पास एक EmailValidator वर्ग को समाप्त करने का हर कारण है। और भी बेहतर, ईमेल पतों को मान्य करने के लिए एक अच्छी, अच्छी तरह से जाँच की गई लाइब्रेरी का उपयोग करें।

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

  • क्या आपके पास बहुत अधिक कोड हैं?
  • क्या आपके पास बहुत कम कोड है?

महत्वपूर्ण प्रश्न हैं:

  • एक पूरे के रूप में आवेदन सही ढंग से बनाया गया है?
  • क्या कोड सही तरीके से लागू किया गया है?
  • क्या कोड बनाए रखने योग्य है?
  • कोड परीक्षण योग्य है?
  • क्या कोड का पर्याप्त परीक्षण किया गया है?

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

ज़रूर, शायद मैं एक उपयोगिता पद्धति के बजाय बूलियन संचालन की एक लंबी श्रृंखला का उपयोग कर सकता हूं, लेकिन क्या मुझे करना चाहिए?

आपका प्रश्न वास्तव में मुझे लगता है कि मैंने लिखी गई बुलियन की कुछ लंबी श्रृंखलाओं के बारे में सोचा है और मुझे लगता है कि शायद मुझे एक या एक से अधिक उपयोगिता विधि लिखनी चाहिए।


3

एक स्तर पर, वे सही हैं - कम कोड बेहतर है। एक अन्य उत्तर गेट के हवाले से, मुझे पसंद है:

"यदि डिबगिंग सॉफ़्टवेयर बग्स को हटाने की प्रक्रिया है, तो प्रोग्रामिंग को उन्हें डालने की प्रक्रिया होनी चाहिए।"

“डिबगिंग करते समय, नौसिखिए सुधारात्मक कोड डालते हैं; विशेषज्ञ दोषपूर्ण कोड निकालते हैं। "- रिचर्ड पैटीस

सबसे सस्ता, सबसे तेज़ और सबसे विश्वसनीय घटक वे हैं जो वहां नहीं हैं। - गॉर्डन बेल

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

यहां जो महत्वपूर्ण है, वह यह है कि ये सभी कार्यक्षमता को संदर्भित करते हैं, और केवल इसे करने के लिए न्यूनतम आवश्यकता होती है। यह कैसे व्यक्त किया जाता है इसके बारे में कुछ नहीं कहता है।

स्वच्छ कोड रखने का प्रयास करके आप जो कर रहे हैं वह उपरोक्त के खिलाफ नहीं है। आप अपने LOC में जोड़ रहे हैं लेकिन अप्रयुक्त कार्यक्षमता को नहीं जोड़ रहे हैं।

अंतिम लक्ष्य पठनीय कोड है, लेकिन कोई अतिश्योक्तिपूर्ण एक्स्ट्रा कलाकार नहीं है। दो सिद्धांतों को एक दूसरे के खिलाफ कार्य नहीं करना चाहिए।

एक रूपक एक कार का निर्माण होगा। कोड का कार्यात्मक हिस्सा चेसिस, इंजन, पहिए है ... जो कार को चलाता है। आप कैसे टूटते हैं कि निलंबन, पावर स्टीयरिंग और इतने पर अधिक है, यह संभालना आसान बनाता है। आप अपने मैकेनिक को अपना काम करते समय जितना संभव हो सके उतना सरल चाहते हैं, ताकि चीजों के गलत होने की संभावना कम हो, लेकिन यह आपको अच्छी सीटों से नहीं रोकता है।


2

मौजूदा उत्तरों में बहुत ज्ञान है, लेकिन मैं एक और कारक में जोड़ना चाहूंगा: भाषा

कुछ भाषाएं समान प्रभाव पाने के लिए दूसरों की तुलना में अधिक कोड लेती हैं। विशेष रूप से, जबकि जावा (जो मुझे संदेह है कि प्रश्न में भाषा है) बेहद प्रसिद्ध है और आम तौर पर बहुत ठोस और स्पष्ट और सीधी है, कुछ और आधुनिक भाषाएं अधिक संक्षिप्त और अभिव्यंजक हैं।

उदाहरण के लिए, जावा में, तीन गुणों के साथ एक नया वर्ग लिखने के लिए आसानी से 50 पंक्तियां ली जा सकती हैं, प्रत्येक एक गेट्टर और सेटर के साथ, और एक या एक से अधिक निर्माता - जबकि आप कोटलिन * या स्काला की एक ही पंक्ति में बिल्कुल समान कर सकते हैं। (यहां तक कि अधिक से अधिक की बचत करता है, तो आप भी उपयुक्त चाहते थे equals(), hashCode()और toString()तरीकों।)

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

(यह कोड की 'सतह' की जटिलता और विचारों / मॉडलों / प्रसंस्करण की जटिलताओं की जटिलता को उजागर करता है। कोड की पंक्तियाँ पहले का एक बुरा माप नहीं है, लेकिन दूसरे के साथ ऐसा करने के लिए बहुत कम है। ।)

इसलिए चीजों को सही करने की 'लागत' भाषा पर निर्भर करती है। शायद एक अच्छी भाषा का एक संकेत वह है जो आपको अच्छी तरह से काम करने और बस उन्हें करने के बीच चयन नहीं करता है !

(* यह वास्तव में एक प्लग के लिए जगह नहीं है, लेकिन कोटलिन एक नज़र IMHO के लायक है।)


1

मान लेते हैं कि आप Contactवर्तमान में कक्षा के साथ काम कर रहे हैं । तथ्य यह है कि आप ईमेल पते के सत्यापन के लिए एक और विधि लिख रहे हैं, इस तथ्य का प्रमाण है कि वर्ग Contactएक भी जिम्मेदारी नहीं संभाल रहा है।

यह कुछ ईमेल जिम्मेदारी भी संभाल रहा है, जो आदर्श रूप से, अपनी कक्षा होनी चाहिए।


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

private void LargeMethod() {
    //A lot of code which modifies a lot of values. You do all sorts of tricks here.
    //Code.
    //Code..
    //Code...

    //Email validation code becoming very difficult to test as it will be difficult to ensure 
    //that you have the right data till you reach here in the method
    ValidateEmail();

    //Another whole lot of code that modifies all sorts of values.
    //Extra work to preserve the result of ValidateEmail() for your asserts later.
}

दूसरी ओर, यदि आपके पास ईमेल सत्यापन के लिए एक अलग ईमेल वर्ग है, तो अपने सत्यापन कोड को जांचने के लिए आप बस Email.Validation()अपने परीक्षण डेटा के साथ एक सरल कॉल करेंगे ।


बोनस सामग्री: परीक्षण और अच्छी डिजाइन के बीच गहरे तालमेल के बारे में एमएफ हीर की बात


1

एलओसी में कमी को कम दोषों के साथ सहसंबद्ध पाया गया है , और कुछ नहीं। यह मानते हुए कि कभी भी आपने एलओसी को कम किया है, तो आपने दोषों की संभावना को कम कर दिया है और यह माना जाता है कि सह-संबंध बराबर है। कम LOC अच्छी विकास प्रथाओं का परिणाम है और न कि कोड को अच्छा बनाता है।

मेरे अनुभव में, जो लोग कम कोड (एक समतल स्तर पर) के साथ एक समस्या को हल कर सकते हैं, वे उन लोगों की तुलना में अधिक कुशल होते हैं जो समान कार्य करने के लिए अधिक कोड लिखते हैं। इन कुशल डेवलपर्स कोड की लाइनों को कम करने के लिए क्या करते हैं / आम समस्याओं को हल करने के लिए अमूर्त और पुन: प्रयोज्य समाधान बनाते हैं। वे कोड की पंक्तियों को गिनने में समय व्यतीत नहीं करते हैं और इस बात पर नाराज होते हैं कि वे यहां या वहां लाइन काट सकते हैं। अक्सर वे जो कोड लिखते हैं, वह आवश्यक से अधिक क्रियात्मक होता है, वे बस इसके बारे में कम लिखते हैं।

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

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


1

आपने एक मान्य ट्रेड-ऑफ की पहचान की है

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

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

लालची एल्गोरिथ्म इन मामलों में विफल हो सकता है

जटिलता ने कोड को एक निश्चित अर्थ में भी अधिक के बजाय कम पठनीय बना दिया है। एक पूर्व नौकरी में मैंने एक HTTP एपीआई के साथ निपटाया जो बहुत सावधानी से और ठीक से कई परतों में संरचित था, प्रत्येक समापन बिंदु एक नियंत्रक द्वारा निर्दिष्ट किया जाता है जो आने वाले संदेश के आकार को मान्य करता है और फिर इसे कुछ "बिजनेस-लॉजिक-लेयर" प्रबंधक को सौंप देता है , जिसने तब कुछ "डेटा लेयर" के कुछ अनुरोध किए, जो कुछ "डेटा एक्सेस ऑब्जेक्ट" लेयर के लिए कई प्रश्न बनाने के लिए ज़िम्मेदार था, जो कई SQL डेलिगेट्स बनाने के लिए ज़िम्मेदार था, जो वास्तव में आपके प्रश्न का उत्तर देगा। इसके बारे में मैं जो पहली बात कह सकता हूं, वह कुछ इस तरह थी कि 90% कोड कॉपी-और-पेस्ट बॉयलरप्लेट था, दूसरे शब्दों में यह बिना-ऑप्स था। इसलिए कई मामलों में किसी भी दिए गए कोड को पढ़ना बहुत ही "आसान" था, क्योंकि "ओह, यह प्रबंधक केवल उस डेटा ऑब्जेक्ट के लिए अनुरोध को फॉरवर्ड करता है।"बहुत सारी संदर्भ-स्विचिंग और फ़ाइलें ढूंढना और उन सूचनाओं को ट्रैक करने की कोशिश करना, जिन्हें आपको कभी भी ट्रैक नहीं करना चाहिए था, "इसे इस परत पर X कहा जाता है, इसे इस अन्य परत पर X 'कहा जाता है, फिर इसे अन्य में X' 'कहा जाता है अन्य परत। "

मुझे लगता है कि जब मैं रवाना हुआ था, तो यह सरल CRUD एपीआई उस स्तर पर था जहां अगर आप इसे प्रति पृष्ठ 30 लाइनों पर मुद्रित करते हैं, तो यह एक शेल्फ पर 10-20 पांच सौ-पृष्ठ की पाठ्यपुस्तकों को ले जाएगा: यह दोहराव का एक पूरा विश्वकोश था कोड। आवश्यक जटिलता के संदर्भ में, मुझे यकीन नहीं है कि वहाँ आवश्यक जटिलता की एक पाठ्यपुस्तक का आधा भी था; इसे संभालने के लिए हमारे पास केवल 5-6 डेटाबेस आरेख थे। इसमें कोई भी मामूली बदलाव करना एक विशाल उपक्रम था, यह सीखना एक विशाल उपक्रम था, नई कार्यक्षमता को जोड़ना इतना दर्दनाक था कि हमारे पास वास्तव में बॉयलरप्लेट टेम्पलेट फाइलें थीं जो हम नई कार्यक्षमता जोड़ने के लिए उपयोग करेंगे।

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

सर्वोत्तम अभ्यास: कॉल करने के लिए DRY और लंबाई का उपयोग करें

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

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

और उनकी उद्दंड प्रतिक्रिया बस थी, "हम हमेशा बाद में कर सकते हैं, अगर हमें ज़रूरत है।"

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

यदि हम उस सलाह को गंभीरता से लेते हैं तो हमें यह पहचानना होगा कि "बाद में" कब आया है। संभवतः सबसे स्पष्ट बात शैली कारणों के लिए चीजों की लंबाई पर एक ऊपरी सीमा स्थापित करना होगा। और मुझे लगता है कि शेष सबसे अच्छी सलाह DRY का उपयोग करना होगा - अपने आप को दोहराएं नहीं - इन सिद्धांतों के साथ SOLID सिद्धांतों में छेद को लंबा करने के लिए लाइन की लंबाई। 30 पंक्तियों के अनुमान के आधार पर पाठ का "पृष्ठ" और गद्य के साथ एक सादृश्य,

  1. जब आप इसे कॉपी-पेस्ट करना चाहते हैं, तो एक फ़ंक्शन / विधि में एक चेक को रिफलेक्टर करें। जैसे कॉपी-पेस्ट करने के लिए कभी-कभार वैध कारण होते हैं लेकिन आपको हमेशा इसके बारे में गंदा महसूस करना चाहिए। जब तक वे वास्तव में एक विषय को उजागर करने की कोशिश नहीं कर रहे हैं, तब तक वास्तविक लेखक आपको कथा में 50 गुना बड़ा वाक्य नहीं सुनाते।
  2. एक फ़ंक्शन / विधि आदर्श रूप से एक "पैराग्राफ" होना चाहिए। अधिकांश फ़ंक्शंस लगभग आधे पृष्ठ लंबे, या 1-15 पंक्तियों के कोड होने चाहिए, और हो सकता है कि आपके कार्यों के केवल 10% को पृष्ठ और डेढ़, 45 लाइनों या अधिक तक सीमित किया जाए। एक बार जब आप कोड की 120+ पंक्तियों पर होते हैं और टिप्पणी करते हैं कि उस चीज़ को भागों में विभाजित करने की आवश्यकता है।
  3. एक फ़ाइल को आदर्श रूप से "अध्याय" होना चाहिए। अधिकांश फाइलें 12 पेज लंबी या उससे कम होनी चाहिए, इसलिए कोड और टिप्पणियों की 360 लाइनें। हो सकता है कि आपकी 10% फ़ाइलों को केवल 50 पृष्ठों की लंबी, या कोड और टिप्पणियों की 1500 पंक्तियों तक सीमित करने की अनुमति दी जाए।
  4. आदर्श रूप से, आपके अधिकांश कोड को फ़ंक्शन के आधार रेखा या एक स्तर गहरे से प्रेरित होना चाहिए। लिनक्स स्रोत पेड़ के बारे में कुछ अनुमानों के आधार पर, यदि आप इसके बारे में धार्मिक हैं, तो हो सकता है कि आपके कोड का केवल 10%, बेसलाइन के भीतर 2 स्तर या उससे अधिक होना चाहिए, 5% से कम 3 स्तर या उससे अधिक। इसका मतलब विशेष रूप से है कि जिन चीजों को किसी अन्य चिंता को "लपेटने" की आवश्यकता होती है, जैसे कि बड़ी कोशिश / कैच में त्रुटि से निपटने, वास्तविक तर्क से बाहर निकाला जाना चाहिए।

जैसा कि मैंने वहां उल्लेख किया है, मैंने इन आंकड़ों को वर्तमान लिनक्स स्रोत पेड़ के खिलाफ उन अनुमानित प्रतिशतों को खोजने के लिए परीक्षण किया, लेकिन वे साहित्यिक सादृश्य में तर्क के लिए भी खड़े हैं।

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