स्वच्छ कोड: कुछ मापदंडों के साथ छोटी विधियों के परिणाम


15

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

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

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

मुझे संदेह है कि यह कोड बड़े पैरामीटर सूचियों (<3 पैरामीटर) से बचने के लिए तरीकों को छोटा (<= 5 लाइनों का कोड) रखने की सलाह से प्रेरित है और निर्माणकर्ताओं को काम नहीं करना चाहिए (जैसे किसी प्रकार की गणना करना) वह वस्तु की वैधता के लिए आवश्यक है)।

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

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

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


6
1. एक पल के लिए शैतान का वकील खेलना ... क्या कोड वास्तव में काम करता है? क्योंकि डेटा ट्रांसफर ऑब्जेक्ट एक पूरी तरह से मान्य तकनीक है, और अगर यह सब है ...
रॉबर्ट हार्वे

7
2. यदि आपके पास समस्या का वर्णन करने के लिए शब्दों की कमी है, तो आपके पास अपने सहकर्मी की स्थिति का खंडन करने के लिए पर्याप्त अनुभव नहीं है।
रॉबर्ट हार्वे

4
3. अगर आपके पास कुछ काम करने वाले कोड हैं, तो आप इसे कोड रिव्यू में पोस्ट कर सकते हैं, और उन्हें इस पर एक नज़र डाल सकते हैं। अन्यथा, यह सिर्फ एक भटक सामान्यता है।
रॉबर्ट हार्वे

5
@RobertHarvey "मान जो गणना से उत्पन्न होते हैं, उन्हें पूरी कक्षा में कई निजी तरीकों के अंदर उपयोग किए जाने वाले गुणों के लिए सौंपा गया है" मेरे लिए एक स्वाभिमानी डीटीओ की तरह नहीं है। मैं इस बात से सहमत हूं कि थोड़ी और विशिष्टता सहायक होगी।
Topo Reinstate Monica

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

जवाबों:


13

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

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

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

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

इसके अलावा, क्लीन क्लासेस को कोसिव होना चाहिए , जिसका अर्थ है कि इसके अधिकांश तरीके इसकी अधिकांश विशेषताओं का उपयोग करते हैं। जैसे, एक अधिकतम सामंजस्यपूर्ण वर्ग वह है जहाँ सभी विधियाँ अपनी सभी विशेषताओं का उपयोग करती हैं; एक उदाहरण के रूप में, एक चित्रमय ऐप में आपके पास Vectorविशेषताओं के साथ एक वर्ग हो सकता है Point aऔर Point b, जहाँ केवल विधियाँ हैं scaleBy(double factor)और printTo(Canvas canvas)दोनों विशेषताओं पर काम कर रहे हैं । इसके विपरीत, एक न्यूनतम सहवर्ती वर्ग वह है जहां प्रत्येक विशेषता का उपयोग केवल एक विधि में किया जाता है, और कभी भी प्रत्येक विधि के लिए एक से अधिक विशेषता का उपयोग नहीं किया जाता है। औसत में, एक वर्ग गैर-समकारी भागों के "गैर-चिपकने वाला" समूह प्रस्तुत करता है - अर्थात कुछ विधियां विशेषताओं का उपयोग करती हैं a, bऔर c, शेष उपयोग cऔरd - अर्थ यह है कि यदि हम कक्षा को दो में विभाजित करते हैं, तो हम दो कोसिव वस्तुओं के साथ समाप्त होते हैं।

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

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


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

1
SRP सबसे महत्वपूर्ण दिशानिर्देश है; एक अंगूठी उन सभी और सभी पर शासन करने के लिए। अच्छी तरह से किया एसआरपी स्वाभाविक रूप से कम तरीकों में परिणाम करता है। उदाहरण: मेरे सामने एक सामने वाला वर्ग w / केवल 2 सार्वजनिक और लगभग 8 गैर-सार्वजनिक तरीके हैं। कोई भी ~ 3 लाइनों से अधिक नहीं है; पूरी कक्षा लगभग 35 LOC है। लेकिन मैंने यह क्लास आखिरी लिखी थी! जब तक सभी अंतर्निहित कोड लिखे गए थे तब तक इस वर्ग ने अनिवार्य रूप से खुद लिखा था और मेरे पास नहीं था, वास्तव में तरीकों को बड़ा नहीं कर सकता था। किसी भी समय मैंने यह नहीं कहा "मैं इन विधियों को 5 लाइनों में लिखने जा रहा हूं यदि यह मुझे मारता है।" हर बार जब आप एसआरपी लागू करते हैं तो ऐसा ही होता है।
राडार

11

यह मेरी समझ है कि वर्ग निर्माता पूरी तरह से एक वैध वस्तु के निर्माण के लिए जिम्मेदार है और इसका मुख्य कार्य किसी वस्तु (निजी) गुणों का असाइनमेंट है।

यह आमतौर पर एक प्रारंभिक वैध स्थिति में वस्तु डालने के लिए जिम्मेदार है, हाँ; अन्य गुण या विधियाँ तब राज्य को किसी अन्य मान्य स्थिति में बदल सकती हैं।

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

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

संदेह है कि यह कोड विधियों को छोटा रखने के लिए सलाह से प्रेरित है (<= कोड की 5 पंक्तियाँ), बड़े पैरामीटर सूचियों (<3 मापदंडों) से बचने के लिए और निर्माणकर्ताओं को काम नहीं करना चाहिए (जैसे कि किसी प्रकार की गणना करना) वस्तु की वैधता के लिए आवश्यक है)।

दूसरों की अनदेखी करते हुए कुछ कोडिंग दिशानिर्देशों का पालन करने से अक्सर मूर्खतापूर्ण कोड होता है। यदि हम एक निर्माणकर्ता को काम करने से बचना चाहते हैं, उदाहरण के लिए, समझदार तरीका आमतौर पर निर्माण से पहले काम करना होगा और निर्माणकर्ता को उस काम का परिणाम देना होगा। (उस दृष्टिकोण के लिए एक तर्क यह हो सकता है कि आप अपनी कक्षा को दो ज़िम्मेदारियाँ देने से बच रहे हैं: इसके आरंभ का काम, और इसका 'मुख्य काम', जो भी हो।)

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

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

ऐसा करने के लिए आप शायद सही होंगे। सीधा प्रक्रियात्मक कोड लिखने में कुछ भी गलत नहीं है; OO प्रतिमान को अपवित्र प्रक्रियात्मक कोड लिखने के लिए दुरुपयोग करने में एक समस्या है।

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

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


2
upvote क्योंकि: 1. एसआरपी पर जोर देना। "... छोटे तरीके ... स्वाभाविक रूप से पालन करें" 2. कंस्ट्रक्टर उद्देश्य - मान्य स्थिति। 3. "दूसरों की अनदेखी करते हुए कुछ कोडिंग दिशानिर्देशों का पालन करें।" यह कोडिंग का वॉकिंग डेड है।
राडारोब ऑक्ट

6

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

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

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