"डू वन थिंग" प्रतिमान कब हानिकारक हो जाता है?


21

तर्क के लिए यहां एक नमूना फ़ंक्शन है जो किसी दिए गए फ़ाइल लाइन-बाय-लाइन की सामग्री को प्रिंट करता है।

संस्करण 1:

void printFile(const string & filePath) {
  fstream file(filePath, ios::in);
  string line;
  while (std::getline(file, line)) {
    cout << line << endl;
  }
}

मुझे पता है कि यह सिफारिश की जाती है कि कार्य एक स्तर पर अमूर्तता का काम करते हैं। मेरे लिए, हालांकि ऊपर कोड बहुत अधिक एक काम करता है और काफी परमाणु है।

कुछ पुस्तकें (जैसे रॉबर्ट सी। मार्टिन क्लीन कोड) उपरोक्त कार्यों को अलग-अलग कार्यों में तोड़ने का सुझाव देती हैं।

संस्करण 2:

void printFile(const string & filePath) {
  fstream file(filePath, ios::in);
  printLines(file);
}

void printLines(fstream & file) {
  string line;
  while (std::getline(file, line)) {
    printLine(line);
  }
}

void printLine(const string & line) {
  cout << line << endl;
}

मैं समझता हूं कि वे क्या हासिल करना चाहते हैं (खुली फाइल / लाइनों को पढ़ें / प्रिंट करें), लेकिन क्या यह अधिक ओवरकिल नहीं है?

मूल संस्करण सरल है और कुछ अर्थों में पहले से ही एक काम करता है - एक फ़ाइल प्रिंट करता है।

दूसरा संस्करण वास्तव में छोटे कार्यों की एक बड़ी संख्या को जन्म देगा जो पहले संस्करण की तुलना में कम सुगम हो सकता है।

क्या इस मामले में, कोड को एक स्थान पर रखना बेहतर होगा?

"डू वन थिंग" प्रतिमान किस बिंदु पर हानिकारक हो जाता है?


13
इस तरह की कोडिंग प्रैक्टिस हमेशा केस द्वारा केस पर आधारित होती है। एक भी दृष्टिकोण कभी नहीं है।
.मिलिंद

1
@ एलेक्स - स्वीकृत उत्तर का शाब्दिक रूप से सवाल से कोई लेना देना नहीं है। मुझे वह बहुत अजीब लगता है।
ChaosPandion

2
मैं ध्यान देता हूं कि आपका रिफैक्टेड संस्करण उल्टा है, जो पठनीयता की कमी में योगदान देता है। फ़ाइल नीचे पढ़ना, आप को देखने के लिए उम्मीद करेंगे printFile, printLinesऔर अंत में printLine
एंथनी पेगमेर

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

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

जवाबों:


15

बेशक, यह सिर्फ यह सवाल है कि " एक बात क्या है ?" क्या एक लाइन को पढ़ना और एक लाइन को एक और लिखना है? या एक चीज को एक स्ट्रीम से दूसरी स्ट्रीम में कॉपी करना एक चीज माना जाता है? या एक फाइल की नकल?

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

आईएमओ एक फ़ंक्शन जिसमें कोड की केवल एक पंक्ति शामिल है, शायद ही कभी परेशानी के लायक है। सीधे 1printLine() का उपयोग करने पर आपका कोई फायदा नहीं है । यदि मैं देखता हूं , तो मुझे यह मानकर चलना होगा कि इसका नाम क्या कहता है, या इसे देखें और जांचें। अगर मैं देखता हूं , मुझे तुरंत पता है कि यह क्या करता है, क्योंकि यह एक स्ट्रिंग की सामग्री को एक पंक्ति के रूप में आउटपुट करने का विहित तरीका है ।std::cout << line << '\n'printLine()std::cout << line << '\n'std::cout

हालांकि, प्रतिमान का एक और महत्वपूर्ण लक्ष्य कोड का पुन: उपयोग करने की अनुमति देना है, और यह एक उद्देश्य अधिक माप है। उदाहरण के लिए, अपने 2 संस्करण में printLines() कर सकता है आसानी से ऐसा लिखा जा है कि यह एक सार्वभौमिक उपयोगी एल्गोरिथ्म है कि एक धारा से दूसरे में प्रतियां लाइनों:

void copyLines(std::istream& is, std::ostream& os)
{
  std::string line;
  while( std::getline(is, line) );
    os << line << '\n';
  }
}

इस तरह के एक एल्गोरिथ्म को अन्य संदर्भों में भी पुन: उपयोग किया जा सकता है।

फिर आप इस एक उपयोग के मामले में एक जेनेरिक एल्गोरिदम को कॉल करने वाले फ़ंक्शन के लिए विशिष्ट सब कुछ डाल सकते हैं:

void printFile(const std::string& filePath) {
  std::ifstream file(filePath.c_str());
  printLines(file, std::cout);
}

1 ध्यान दें कि मैंने इसके '\n'बजाय इस्तेमाल किया std::endl'\n'एक नई लाइन के आउटपुट के लिए डिफ़ॉल्ट विकल्प होना चाहिए , std::endlविषम मामला है


2
+1 - मैं ज्यादातर सहमत हूं, लेकिन मुझे लगता है कि "आंत भावना" की तुलना में यह अधिक है। परेशानी तब होती है जब लोग कार्यान्वयन विवरणों की गिनती करके "एक बात" का न्याय करते हैं। मेरे लिए, फ़ंक्शन को एक ही स्पष्ट अमूर्तता को लागू करना चाहिए (और इसका नाम वर्णन)। आपको "do_x_and_y" फ़ंक्शन का नाम कभी नहीं देना चाहिए। कार्यान्वयन में कई (सरल) चीजें करनी चाहिए - और उन सरल चीजों में से प्रत्येक को कई सरल चीजों में भी विघटित किया जा सकता है। यह केवल एक अतिरिक्त नियम के साथ कार्यात्मक अपघटन है - कि फ़ंक्शन (और उनके नाम) प्रत्येक को एक एकल स्पष्ट अवधारणा / कार्य / जो कुछ भी वर्णन करना चाहिए।
स्टीव ३४

@ स्टीव 314: मैंने कार्यान्वयन विवरण को संभावनाओं के रूप में सूचीबद्ध नहीं किया है। एक धारा से दूसरी धारा में प्रतिलिपि बनाना स्पष्ट रूप से एक बात है। या यह है? और इसके बजाय do_x_and_y()फ़ंक्शन का नामकरण करने से बचना आसान है do_everything()। हां, यह एक मूर्खतापूर्ण उदाहरण है, लेकिन यह दर्शाता है कि यह नियम खराब डिजाइन के सबसे चरम उदाहरणों को रोकने में भी विफल रहता है। IMO यह है एक आंत महसूस निर्णय एक सम्मेलनों से तय हो उतना। अन्यथा, यदि यह उद्देश्य था, तो आप इसके लिए एक मीट्रिक ला सकते हैं - जो आप नहीं कर सकते।
sbi

1
मैं विरोधाभास करने का इरादा नहीं था - केवल एक अतिरिक्त सुझाव देने के लिए। मुझे लगता है कि मैं जो कहना भूल गया, वह यह है कि सवाल से, printLineआदि के लिए विघटित वैध है - उनमें से प्रत्येक एक अमूर्त है - लेकिन इसका मतलब यह नहीं है कि आवश्यक नहीं है। printFileपहले से ही "एक बात" है। यद्यपि आप तीन अलग-अलग निचले स्तर के अमूर्त में विघटित कर सकते हैं, लेकिन आपको अमूर्तता के हर संभव स्तर पर विघटित होने की आवश्यकता नहीं है । प्रत्येक फ़ंक्शन को "एक काम" करना चाहिए, लेकिन हर संभव "एक चीज़" को एक फ़ंक्शन होने की आवश्यकता नहीं है। कॉल ग्राफ़ में बहुत अधिक जटिलता बढ़ना स्वयं एक समस्या हो सकती है।
स्टीव 314

7

एक कार्य करने के बाद केवल "एक चीज" दो वांछनीय छोरों का साधन है, न कि ईश्वर की आज्ञा।

  1. यदि आपका कार्य केवल "एक बात" करता है, तो यह आपको कोड दोहराव और एपीआई ब्लोट से बचने में मदद करेगा, क्योंकि आप उच्च-स्तरीय, कम-कमनीय कार्यों के दहनशील विस्फोट होने के बजाय अधिक जटिल चीजों को प्राप्त करने के लिए कार्यों की रचना करने में सक्षम होंगे। ।

  2. केवल "एक काम" करने के लिए कार्य करने से कोड अधिक पठनीय हो सकता है । यह इस बात पर निर्भर करता है कि क्या आप चीजों को समझने से ज्यादा स्पष्टता और तर्क की आसानी से हासिल कर लेते हैं, क्योंकि आप उन निर्माणों की वाचालता, अप्रत्यक्षता और वैचारिक अतिशयता से हार जाते हैं जो आपको चीजों को कम करने की अनुमति देते हैं।

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

यदि आपको अमूर्तता के निचले स्तरों पर अधिक नियंत्रण की आवश्यकता होती है और सूक्ष्म दोहराव और दहनशील विस्फोट (यानी printLinesफ़ाइल नाम और वस्तुओं के printLinesलिए पूरी तरह से अलग fstream, printLinesकंसोल के लिए और printLinesफ़ाइलों के लिए) के साथ printLinesसमाप्त होता है, तो स्तर पर एक से अधिक काम कर रहा है अमूर्तता की आप परवाह करते हैं।


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

@PersonalNexus: मैं परीक्षण के मुद्दे पर कुछ हद तक सहमत हूं, लेकिन IMHO कार्यान्वयन विवरणों का परीक्षण करने के लिए मूर्खतापूर्ण है। मेरे लिए एक इकाई परीक्षण "एक बात" का परीक्षण करना चाहिए जैसा कि मेरे उत्तर में परिभाषित किया गया है। कुछ भी बारीक दाने आपके परीक्षणों को भंगुर बना रहे हैं (क्योंकि कार्यान्वयन विवरण बदलने से आपके परीक्षणों को बदलने की आवश्यकता होगी) और आपका कोड कष्टप्रद क्रिया, अप्रत्यक्ष, आदि (क्योंकि आप परीक्षण का समर्थन करने के लिए अप्रत्यक्ष जोड़ देंगे)।
dsimcha

6

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

printLines(FileSet files) {
   files.each({ 
       file -> file.eachLine({ 
           line -> printLine(line); 
       })
   })
}

अब फ़ाइल पुनरावृत्ति को अलग से परीक्षण किया जा सकता है।

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


4
लगता है आपने उसे पकड़ लिया। यदि हमें एक पंक्ति की व्याख्या करने के लिए एक टिप्पणी की आवश्यकता है, तो यह हमेशा एक विधि निकालने का समय है।
रोजर सीएस वर्नरसन

5

जब आप चीजों को समझाने के लिए टिप्पणी की आवश्यकता महसूस करते हैं तो तरीके निकालें।

ऐसी विधियाँ लिखिए जो या तो केवल उनके नाम को स्पष्ट रूप से बताती हैं, या चतुराई से नाम वाली विधियों को बुलाकर कहानी कहती हैं।


3

आपके साधारण मामले में भी, आपको यह विवरण याद आ रहा है कि एकल जिम्मेदारी सिद्धांत आपको बेहतर प्रबंधन करने में मदद करेगा। उदाहरण के लिए, क्या होता है जब फ़ाइल खोलने के साथ कुछ गलत हो जाता है। फ़ाइल एक्सेस एज मामलों के खिलाफ सख्त करने के लिए अपवाद हैंडलिंग में जोड़ने से आपके फ़ंक्शन में कोड की 7-10 पंक्तियां जुड़ जाएंगी।

फ़ाइल खोलने के बाद, आप अभी भी सुरक्षित नहीं हैं। यह आप से yanked किया जा सकता है (विशेष रूप से अगर यह एक नेटवर्क पर एक फ़ाइल है), तो आप स्मृति से बाहर चला सकते हैं, फिर से कई किनारे के मामले हो सकते हैं जो आप के खिलाफ सख्त करना चाहते हैं और आपके अखंड फ़ंक्शन को फूला देंगे।

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

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


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

टिप्पणी के लिए धन्यवाद। नोट मैं समय से पहले गर्भपात की वकालत नहीं कर रहा हूँ, सिर्फ तार्किक कार्यों को विभाजित करना ताकि बाद में ऐसा करना आसान हो।
माइकल ब्राउन 12

2

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

सामान्य उपयोगिता कार्य:

void printLine(ostream& output, const string & line) { 
    output << line << endl; 
} 

void printLines(istream& input, ostream& output) { 
    string line; 
    while (getline(input, line)) {
        printLine(output, line); 
    } 
} 

डोमेन-विशिष्ट फ़ंक्शन:

void printFile(const string & filePath, ostream& output = std::cout) { 
    fstream file(filePath, ios::in); 
    printLines(file, output); 
} 

अब printLinesऔर printLineन केवल fstream, बल्कि किसी भी धारा के साथ काम कर सकते हैं ।


2
मैं असहमत हूं। उस printLine()फ़ंक्शन का कोई मूल्य नहीं है। मेरा जवाब देखिए ।
sbi

1
ठीक है, अगर हम प्रिंटलाइन () रखते हैं तो हम एक डेकोरेटर जोड़ सकते हैं जो लाइन नंबर या सिंटैक्स रंग जोड़ता है। ऐसा कहने के बाद, मैं उन तरीकों को नहीं निकालूंगा, जब तक मुझे कोई कारण नहीं मिल जाता।
रोजर सीएस वर्नरसन

2

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

इस प्रकार, प्रश्न का सही उत्तर भविष्य में "पूर्वाभास" करने के लिए एक अच्छी क्षमता की आवश्यकता है, जैसे:

  • मैं अभी करने के लिए आवश्यक हूँ AऔरB
  • क्या संभावना है, निकट भविष्य में मुझे भी करने की आवश्यकता होगी A-और B+(यानी ऐसा कुछ जो ए और बी की तरह दिखता है, लेकिन बस थोड़ा अलग है)?
  • अधिक दूर भविष्य में क्या संभावना है, कि A + बनेगा A*या नहीं A*-?

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

यदि वह संभावना बहुत कम है (जो भी संस्करण लगभग Aअनिवार्य रूप से Aखुद से ज्यादा कुछ भी नहीं है), तो अध्ययन करें कि आगे कैसे विघटित किया जाएगा और सबसे अधिक समय बर्बाद होने की संभावना होगी।

एक उदाहरण के रूप में, मैं आपको यह वास्तविक कहानी बताता हूं:

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

कुछ जांच के बाद मुझे पता चला कि, एक लगातार समस्या होने के कारण, सभी छात्र उसके लिए एक फ़ंक्शन का उपयोग करने के विचार में आते हैं। उन्हें बताया कि उसके बाद एक पुस्तकालय समारोह है (strlen ) के , उनमें से कई ने जवाब दिया कि चूंकि समस्या इतनी सरल और तुच्छ थी, इसलिए सी लाइब्रेरी मैनुअल मांगने की तुलना में उनके लिए अपना स्वयं का फ़ंक्शन (कोड की 2 लाइनें) लिखना अधिक प्रभावी था। (यह 1984 था, WEB और गूगल को भूल गए!) यह देखने के लिए कि क्या कोई तैयार कार्य है, सख्त वर्णमाला क्रम में है।

यह एक ऐसा उदाहरण है जहां एक प्रभावी पहिया कैटलॉग के बिना भी प्रतिमान "पहिया को मजबूत नहीं करता है" हानिकारक हो सकता है!


2

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

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

आपका अच्छा और काफी रैखिक छोटा कार्य अचानक एक जटिल गड़बड़ी में समाप्त हो जाता है जो अलग-अलग कार्यों में विभाजित होने की भीख माँगता है।


2

IMO तब हानिकारक हो जाता है जब यह चला जाता है कि एक फ़ंक्शन शायद ही कुछ भी करता है, लेकिन प्रतिनिधि दूसरे फ़ंक्शन पर काम करता है, क्योंकि यह एक संकेत है कि यह अब किसी भी चीज का अमूर्त नहीं है और इस तरह के कार्यों के लिए मानसिकता हमेशा खतरे में है बिगड़े काम ...

मूल पद से

void printLine(const string & line) {
  cout << line << endl;
}

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

void printLine(const string & line) {
  reallyPrintLine(line);
  addEndLine();
}

void reallyPrintLine(const string & line) {
  cout << line;
}

void addEndLine() {
  cout << endl;
}

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

void printLine(const string & line) {
  for (int i=0; i<2; i++)
    reallyPrintLine(line, i);
}

void reallyPrintLine(const string & line, int action) {
  cout << (action==0?line:endl);
}

1

संक्षिप्त उत्तर ... यह निर्भर करता है।

इस बारे में सोचें: क्या होगा अगर, भविष्य में, आप केवल मानक आउटपुट पर प्रिंट नहीं करना चाहेंगे, लेकिन एक फ़ाइल के लिए।

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

यदि आप निश्चित हैं कि आपको केवल कंसोल में आउटपुट की आवश्यकता है, तो यह वास्तव में बहुत मायने नहीं रखता है। एक "आवरण" लिखना cout <<बेकार लगता है।


1
लेकिन कड़ाई से बोलना, क्या प्रिंटलाइन समारोह लाइनों पर चलने से अमूर्तता का एक अलग स्तर नहीं है?

@Petr मुझे ऐसा लगता है, यही वजह है कि वे आपको कार्यक्षमता अलग करने का सुझाव देते हैं। मुझे लगता है कि अवधारणा सही है, लेकिन आपको इसे केस-टू-केस आधार पर लागू करने की आवश्यकता है।

1

संपूर्ण कारण यह है कि "एक काम करो" के गुणों के लिए किताबें समर्पित अध्याय हैं, वहाँ अभी भी डेवलपर्स हैं जो 4 पेज लंबे और घोंसले के सशर्त 6 स्तरों वाले कार्य लिखते हैं। यदि आपका कोड सरल और स्पष्ट है तो आपने इसे सही किया है।


0

जैसा कि अन्य पोस्टरों ने टिप्पणी की है, एक काम करना पैमाने की बात है।

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

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