क्लीन कोड - क्या मुझे शाब्दिक 1 को स्थिरांक में बदलना चाहिए?


14

जादू की संख्या से बचने के लिए, हम अक्सर सुनते हैं कि हमें शाब्दिक अर्थ को सार्थक नाम देना चाहिए। जैसे कि:

//THIS CODE COMES FROM THE CLEAN CODE BOOK
for (int j = 0; j < 34; j++) {
    s += (t[j] * 4) / 5;
}

-------------------- Change to --------------------

int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j = 0; j < NUMBER_OF_TASKS; j++) {
    int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
    int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
    sum += realTaskWeeks;
}

मेरे पास एक डमी विधि है:

समझाएं: मुझे लगता है कि मेरे पास सेवा करने के लिए लोगों की एक सूची है और डिफ़ॉल्ट रूप से, हम केवल खाना खरीदने के लिए $ 5 खर्च करते हैं, लेकिन जब हमारे पास एक से अधिक व्यक्ति हैं, तो हमें पानी और भोजन खरीदने की आवश्यकता है, हमें अधिक पैसा खर्च करना होगा, शायद $ 6। मैं अपना कोड बदलूंगा , कृपया शाब्दिक 1 पर ध्यान दें , इसके बारे में मेरा प्रश्न।

public int getMoneyByPersons(){
    if(persons.size() == 1){ 
        // TODO - return money for one person
    } else {
        // TODO - calculate and return money for people.
    }

}

जब मैंने अपने दोस्तों को अपने कोड की समीक्षा करने के लिए कहा, तो एक ने कहा कि मूल्य 1 के लिए एक नाम देना क्लीनर कोड होगा, और दूसरे ने कहा कि हमें यहां एक निरंतर नाम की आवश्यकता नहीं है, क्योंकि मूल्य अपने आप से सार्थक है।

तो, मेरा सवाल यह है कि क्या मुझे शाब्दिक मूल्य 1 का नाम देना चाहिए? एक मूल्य एक जादू संख्या कब है और यह कब नहीं है? मैं सबसे अच्छा समाधान चुनने के लिए संदर्भ को कैसे भेद कर सकता हूं?


कहाँ personsसे आता है और क्या वर्णन करता है? आपके कोड में कोई टिप्पणी नहीं है जो भी यह अनुमान लगाने में कठिन है कि यह क्या कर रहा है।
ह्यूबर्ट ग्रौस्सोवाकियाक

7
यह 1. की तुलना में कोई भी स्पष्ट नहीं मिलता है। मैं "आकार" को "गिनती" में बदलूंगा। और MoneyService बेवकूफ है क्योंकि यह है, यह तय करने में सक्षम होना चाहिए कि व्यक्तियों के संग्रह के आधार पर कितना पैसा वापस करना है। इसलिए मैं व्यक्तियों को पास करूंगा और उन्हें किसी भी असाधारण मामले को सुलझाने दूंगा।
मार्टिन माट

4
यदि आप एक नई विधि के लिए क्लॉज़ कर सकते हैं, तो आप अपनी तार्किक अभिव्यक्ति निकाल सकते हैं। शायद इसे IsSinglePerson () कहते हैं। इस तरह से आप केवल एक चर से थोड़ा अधिक निकालते हैं, लेकिन अगर खंड को थोड़ा और अधिक पठनीय
बनाते हैं


2
शायद यह तर्क moneyService.getMoney () में बेहतर अनुकूल होगा? क्या कभी ऐसा क्षण आएगा जहां आपको 1 व्यक्ति के मामले में गेटमनी बुलानी पड़ेगी? लेकिन मैं सामान्य भावना से सहमत हूं कि 1 स्पष्ट है। मैजिक नंबर वो नंबर होते हैं, जहां आपको अपना सिर खुजलाना होता है, जिसमें पूछा जाता है कि प्रोग्रामर उस नंबर पर कैसे आया ..if(getErrorCode().equals(4095)) ...
नील

जवाबों:


23

नहीं। उदाहरण में, 1 पूरी तरह से सार्थक है।

हालाँकि, क्या होगा यदि व्यक्ति। आकार () शून्य है? अजीब लगता है जो persons.getMoney()0 और 2 के लिए काम करता है लेकिन 1 के लिए नहीं।


मैं मानता हूं कि 1 सार्थक है। धन्यवाद, वैसे, मैंने अपना प्रश्न अपडेट किया। मेरा विचार पाने के लिए आप इसे फिर से देख सकते हैं।
जैक

3
एक वाक्यांश जो मैंने वर्षों में कई बार सुना है वह यह है कि मैजिक नंबर 0 और 1 के अलावा कोई भी अज्ञात स्थिरांक हैं। जबकि मैं संभावित रूप से उन उदाहरणों के बारे में सोच सकता हूं जहां इन नंबरों का नाम होना चाहिए, 99% का पालन करना काफी सरल नियम है समय।
बाल्ड्रिक

@ बाल्डरिक कभी-कभी, अन्य सांख्यिक शाब्दिक नाम के पीछे छिपा नहीं होना चाहिए।
डिडुप्लीकेटर

@Deduplicator कोई उदाहरण दिमाग में आया?
बाल्ड्रिक


18

कोड के एक टुकड़े में वह विशेष शाब्दिक मूल्य क्यों होता है?

  • क्या इस मान का समस्या डोमेन में कोई विशेष अर्थ है ?
  • या क्या यह मूल्य केवल एक कार्यान्वयन विवरण है , जहां वह मूल्य आसपास के कोड का प्रत्यक्ष परिणाम है?

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

  • अपने पहले उदाहरण में, इस तरह के रूप शाब्दिक अर्थ 34, 4, 5नहीं संदर्भ से स्पष्ट है। इसके बजाय, इनमें से कुछ मान आपके समस्या डोमेन में एक विशेष अर्थ रखते हैं। इसलिए उन्हें नाम देना अच्छा था।

  • आपके दूसरे उदाहरण में, शाब्दिक 1का अर्थ संदर्भ से बहुत स्पष्ट है। किसी नाम का परिचय देना मददगार नहीं है।

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

  • यह बग को अस्पष्ट कर सकता है यदि नामित मान को बदल दिया गया है या गलत था, खासकर यदि समान चर कोड के असंबंधित टुकड़ों में पुन: उपयोग किया जाता है।

  • कोड का एक टुकड़ा एक विशिष्ट मूल्य के लिए भी ठीक काम कर सकता है, लेकिन सामान्य मामले में गलत हो सकता है। अनावश्यक अमूर्तता का परिचय देते हुए, कोड अब स्पष्ट रूप से सही नहीं है।

"स्पष्ट" शाब्दिक पर कोई आकार सीमा नहीं है क्योंकि यह पूरी तरह से संदर्भ पर निर्भर करता है। उदाहरण के लिए, शाब्दिक 1024फ़ाइल आकार गणना 31के संदर्भ में, या हैश फ़ंक्शन padding: 0.5emके संदर्भ में शाब्दिक या सीएसएस स्टाइलशीट के संदर्भ में शाब्दिक रूप से स्पष्ट हो सकता है ।


8

कोड के इस टुकड़े के साथ कई मुद्दे हैं, जो, इस तरह से छोटा किया जा सकता है:

public List<Money> getMoneyByPersons() {
    return persons.size() == 1 ?
        moneyService.getMoneyIfHasOnePerson() :
        moneyService.getMoney(); 
}
  1. यह स्पष्ट नहीं है कि एक व्यक्ति एक विशेष मामला क्यों है। मुझे लगता है कि एक विशिष्ट व्यवसाय नियम है जो बताता है कि एक व्यक्ति से पैसा प्राप्त करना कई व्यक्तियों से धन प्राप्त करने से अलग है। हालांकि, मैं जाने के लिए और दोनों के अंदर देखने के लिए है getMoneyIfHasOnePersonऔर getMoneyसमझने के लिए क्यों अलग मामलों रहे हैं उम्मीद कर रहा।

  2. नाम getMoneyIfHasOnePersonसही नहीं लगता है। नाम से, मैं यह जांचने की विधि की अपेक्षा करूंगा कि क्या कोई एकल व्यक्ति है और यदि यह मामला है, तो उससे धन प्राप्त करें; अन्यथा, कुछ न करें। आपके कोड से, यह वह नहीं है जो हो रहा है (या आप दो बार शर्त कर रहे हैं)।

  3. क्या List<Money>संग्रह के बजाय लौटने का कोई कारण है ?

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

मैं सबसे अच्छा समाधान चुनने के लिए संदर्भ को कैसे भेद कर सकता हूं?

आप अपने कोड को और अधिक स्पष्ट करते हैं।

उदाहरण 1

निम्नलिखित कोड की कल्पना करें:

if (sequence.size() == 0) {
    return null;
}

return this.processSequence(sequence);

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

if (sequence.isEmpty()) {
    return null;
}

return this.processSequence(sequence);

यहां, कोई अधिक स्थिर नहीं है, और कोड भी स्पष्ट है।

उदाहरण 2

कोड का एक और टुकड़ा लें:

const result = Math.round(input * 1000) / 1000;

यह समझने में बहुत अधिक समय नहीं लगता है कि यह जावास्क्रिप्ट जैसी भाषाओं में क्या करता है जिनमें round(value, precision)अधिभार नहीं है ।

अब, यदि आप एक स्थिरांक का परिचय देना चाहते हैं, तो इसे कैसे कहा जाएगा? निकटतम शब्द जो आपको मिल सकता है Precision। इसलिए:

const precision = 1000;
const result = Math.round(input * precision) / precision;

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

const result = Math.round(input * 100) / 1000;

एक स्थान पर मूल्य बदलना, और दूसरे में करना भूल जाते हैं।

उदाहरण 3

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

निम्नलिखित कोड का टुकड़ा लें:

class Point
{
    ...
    public void Reset()
    {
        x, y = (0, 0);
    }
}

यदि आप एक चर द्वारा शून्य को बदलने की कोशिश करते हैं, तो कठिनाई एक सार्थक नाम खोजने के लिए होगी। आप इसे कैसे नाम देंगे? ZeroPosition? Base? Default? यहां एक स्थाई का परिचय किसी भी तरह से कोड को नहीं बढ़ाएगा। यह इसे थोड़ा लंबा बनाता है, और बस।

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


मैं 3a जोड़ूंगा: पैसे के शब्द का प्रयोग चर नामों में न करें, राशि, संतुलन या इस तरह का उपयोग करें। धन के संग्रह का कोई मतलब नहीं है, राशियों का संग्रह या शेष राशि नहीं है। (ठीक है, मेरे पास विदेशी धन का एक छोटा संग्रह है (या सिक्के के बजाय) लेकिन यह एक अलग गैर-प्रोग्रामिंग मामला है)।
बेंट

3

आप एक ऐसा कार्य कर सकते हैं जो एक एकल पैरामीटर लेता है और पाँच से विभाजित चार गुना रिटर्न देता है जो पहले उदाहरण का उपयोग करते हुए एक साफ उर्फ ​​प्रदान करता है।

मैं सिर्फ अपनी सामान्य रणनीति पेश कर रहा हूं, लेकिन शायद मैं भी कुछ सीखूंगा।

मैं जो सोच रहा हूं वह है।

// Just an example name  
function normalize_task_value(task) {  
    return (task * 4) / 5;  // or to `return (task * 4) / NUMBER_OF_TASKS` but it really matters what logic you want to convey and there are reasons to many ways to make this logical. A comment would be the greatest improvement

}  

// Is it possible to just use tasks.length or something like that?  
// this NUMBER_OF_TASKS is the only one thats actually tricky to   
// understand right now how it plays its role.  

function normalize_all_task_values(tasks, accumulator) {  
    for (int i = 0; i < NUMBER_OF_TASKS; i++) {  
        accumulator += normalize_task_value(tasks[i]);
    }
}  

क्षमा करें, यदि मैं आधार से दूर हूं लेकिन मैं सिर्फ एक जावास्क्रिप्ट डेवलपर हूं। मुझे यकीन नहीं है कि मैंने किस रचना को उचित ठहराया है, मुझे लगता है कि सब कुछ एक सरणी या सूची में नहीं है लेकिन .length समझदारी का एक बहुत कुछ होगा। और * 4 अच्छा स्थिरांक बना देगा क्योंकि इसकी उत्पत्ति अस्पष्ट है।


5
लेकिन उन मूल्यों का क्या मतलब है 4 और 5? यदि उनमें से किसी को कभी भी बदलने की आवश्यकता होती है, तो क्या आप उन सभी स्थानों को खोजने में सक्षम होंगे जहां संख्या का समान संदर्भ में उपयोग किया जाता है और तदनुसार उन स्थानों को अपडेट किया जाता है? यह मूल प्रश्न में क्रूरता है।
बार्ट वैन इनगेन शेनौ सेप

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

@BartvanIngenSchenau पूरे समारोह को अनुचित रूप से नाम दिया गया है। मैं एक बेहतर फ़ंक्शन नाम, एक कल्पना के साथ एक टिप्पणी पसंद करता हूं कि फ़ंक्शन को क्या माना जाता है, और एक टिप्पणी क्यों * 4/5 प्राप्त होती है। लगातार नामों की वास्तव में आवश्यकता नहीं है।
gnasher729

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

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

2

वह नंबर 1, क्या यह एक अलग संख्या हो सकती है? क्या यह 2, या 3 हो सकता है, या क्या तार्किक कारण हैं कि यह 1 होना चाहिए? यदि यह 1 होना चाहिए, तो 1 का उपयोग करना ठीक है। अन्यथा, आप एक स्थिरांक को परिभाषित कर सकते हैं। उस निरंतर एक फोन मत करो। (मैंने देखा है कि किया)।

एक मिनट में 60 सेकंड - क्या आपको निरंतर की आवश्यकता है? खैर, यह है 60 सेकंड, नहीं 50 या 70 और हर कोई यह जानता है। ताकि एक नंबर रह सके।

प्रति पृष्ठ 60 आइटम मुद्रित - वह संख्या आसानी से 59 या 55 या 70 हो सकती थी। वास्तव में, यदि आप फ़ॉन्ट आकार बदलते हैं, तो यह 55 या 70 हो सकता है। इसलिए यहां एक सार्थक स्थिरांक अधिक मांगा जाता है।

यह भी कि अर्थ कितना स्पष्ट है। यदि आप "मिनट = सेकंड / 60" लिखते हैं, तो यह स्पष्ट है। यदि आप "x = y / 60" लिखते हैं, तो यह स्पष्ट नहीं है। कहीं न कहीं कुछ सार्थक नाम अवश्य होंगे ।

एक पूर्ण नियम है: कोई पूर्ण नियम नहीं हैं। अभ्यास के साथ आप यह पता लगाएंगे कि संख्याओं का उपयोग कब करना है, और कब नामांकित का उपयोग करना है। ऐसा मत करो क्योंकि एक किताब ऐसा कहती है - जब तक आप यह नहीं समझते कि यह ऐसा क्यों कहता है।


"एक मिनट में 60 सेकंड ... और हर कोई इसे जानता है। ताकि एक नंबर रह सके।" - मेरे लिए कोई मान्य तर्क नहीं। यदि मेरे कोड में 200 स्थान हैं जहां "60" का उपयोग किया जाता है तो क्या होगा? मैं उन स्थानों को कैसे खोज सकता हूं जहां यह सेकंड से मिनट तक बनाम अन्य संभवतः समान रूप से "प्राकृतिक" उपयोग करता है? - व्यवहार में, हालांकि, मैं भी उपयोग करने की हिम्मत करता हूं minutes*60, कभी-कभी hours*3600तब भी जब मुझे अतिरिक्त स्थिरांक घोषित किए बिना इसकी आवश्यकता होती है। दिनों के लिए मैं शायद लिखूंगा d*24*3600या d*24*60*60क्योंकि 86400किनारे के करीब होगा जहां कोई उस जादू की संख्या को एक नज़र से नहीं पहचान पाएगा।
जिमीबी

@JimmyB यदि आप अपने कोड में 200 स्थानों पर "60" का उपयोग कर रहे हैं, तो यह बहुत संभावना है कि समाधान एक निरंतरता को प्रस्तुत करने के बजाय एक फ़ंक्शन को वापस कर रहा है।
klutt

0

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

इसलिए इसके बजाय एक स्थिरांक बनाएं, मैं (स्वच्छ कोड पद्धति में) एक नाम देने के लिए एक विधि बनाऊंगा या स्पष्ट करूंगा कि सशर्त का पता लगाने का इरादा क्या है (और इसे कैसे पता लगाता है):

public int getMoneyByPersons(){
  if(isSingleDepartmentHead()){ 
    // TODO - return money for one person
  } else {
    // TODO - calculate and return money for people.
  }
}

public boolean isSingleDepartmentHead() {
   return persons.size() == 1;
}

हैंडलिंग को एकीकृत करने के लिए बहुत बेहतर है। N तत्वों की सूची को समान रूप से माना जा सकता है जो भी n है।
डिडुप्लिकेटर

मैंने देखा है कि ऐसा नहीं है, जहां एकल मामला था, वास्तव में, एक अलग (सीमांत) मूल्य की तुलना में यह होता अगर यह एक ही उपयोगकर्ता एक n- आकार सूची का हिस्सा होता। एक अच्छी तरह से किए गए OO में, यह एक मुद्दा नहीं हो सकता है, लेकिन जब विरासत प्रणालियों के साथ काम करते हैं, तो एक अच्छा OO कार्यान्वयन हमेशा संभव नहीं होता है। हमें जो सबसे अच्छा मिला वह DAO तर्क पर एक उचित OO मुखौटा था।
क्रिस्टियन एच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.