लिंटिंग संभावित समस्याओं की खोज में कोड का स्थिर विश्लेषण करने की प्रक्रिया है।
इस मामले में क्या एक समस्या है, यह प्रोग्रामिंग भाषाओं में भिन्न हो सकता है, या यहां तक कि एक ही भाषा के भीतर परियोजनाओं में भी। मैं इन समस्याओं को कुछ अलग श्रेणियों में रखूंगा:
- प्रोग्रामेटिक
- सुरक्षा
- शैलीगत
- प्रदर्शन
आइए प्रत्येक के कुछ उदाहरण देखें।
शैलीगत समस्याएं
कोड को स्टाइल करने का कोई वस्तुनिष्ठ सही तरीका नहीं है, क्योंकि यह पाठक की प्राथमिकता के बारे में है। कुंजी स्थिरता है। बहस के सामान्य बिंदुओं में शामिल हैं:
- डबल-कोट्स बनाम सिंगल-कोट्स
- टैब बनाम स्पेस
- अधिकतम लाइन लंबाई
- मल्टीलाइन कॉल का इंडेंटेशन, जैसा कि नीचे दिखाया गया है:
# हमेशा सिंगल-लाइन foo(:a, :b, :c) # पहले आर्गुमेंट के साथ संरेखित foo(:a, :b, :c ) # फ़ंक्शन नाम के साथ संरेखित foo( :a, :b )
ये पूरी तरह से व्यक्तिपरक हैं, लेकिन आमतौर पर प्रत्येक विशेष परियोजना के लिए एक मानक पर सहमत होना फायदेमंद होता है, ताकि संपूर्ण कोडबेस सुसंगत रहे।
प्रोग्रामेटिक समस्याएं
मैं यहां ऐसी समस्याओं को शामिल करता हूं जैसे:
- बेहद लंबे मेथड बॉडी, जो पठनीयता और रखरखाव के मुद्दों की ओर ले जाती हैं
- साइक्लोमैटिक जटिलता, कोड जटिलता को मापने के लिए आमतौर पर इस्तेमाल किया जाने वाला एक मीट्रिक
- शर्तों के भीतर असाइनमेंट। सबसे अधिक संभावना है, यदि आप
if x = trueटाइप करते हैं, तो आपका वास्तव में मतलबif x == trueथा। और यहां तक कि यदि आपने असाइनमेंट का इरादा किया था, तो यह अभी भी कम सहज दृष्टिकोण है
सुरक्षा समस्याएं
कुछ फ़ंक्शन या प्रथाओं में संभावित सुरक्षा समस्याएं होती हैं जिनके बारे में डेवलपर्स को जानकारी नहीं हो सकती है।
उदाहरण के लिए, Ruby में, Kernel#open एक लचीला फ़ंक्शन है जो फ़ाइलों या बाहरी URL को खोलने की अनुमति देता है। लेकिन यह open("| ls") जैसे अजीब कॉल के साथ मनमाना फाइल सिस्टम एक्सेस भी अनुमति देता है। इसलिए, डेवलपर्स को इसके बारे में चेतावनी देना समझदारी है ताकि वे या तो एक सुरक्षित दृष्टिकोण का उपयोग कर सकें (File#open, IO.popen, URI.parse#open), या अपने जोखिम पर व्यवहार को स्पष्ट रूप से बनाए रखने का निर्णय ले सकें।
प्रदर्शन समस्या
Ruby के आंतरिक कामकाज के बारे में कई विवरण हैं जो संदर्भ के आधार पर कुछ विकल्पों को दूसरों की तुलना में अधिक प्रदर्शनकारी बनाते हैं।
एक लिंटर हमें उनके बारे में चेतावनी देकर हमें रास्ते में सीखने में मदद करता है जबकि हमारे कार्यक्रम के कुछ विवरणों को अनुकूलित करता है।
उदाहरण के लिए, Ruby 2.5 ने String#delete_suffix पेश किया जो एक स्ट्रिंग के अंत से एक सबस्ट्रिंग को हटाता है। ये दो लाइनें समकक्ष हैं, लेकिन बाद वाली अधिक प्रदर्शनकारी है क्योंकि यह एक सामान्य स्ट्रिंग रेगेक्स मैच पर भरोसा नहीं करती:
str = 'string_with_suffix' # बुरा str.gsub(/suffix\z/, '') # अच्छा str.delete_suffix('suffix')
ऑटो फिक्सिंग
लिंटर्स का एक महत्वपूर्ण पहलू उनकी कुछ या सभी पाई गई समस्याओं को स्वचालित रूप से ठीक करने की क्षमता है। लाइन लंबाई जैसे स्टाइलिंग पहलुओं को आसानी से स्वचालित किया जाता है, इसलिए उस बोझ को डेवलपर से हटाना समझ में आता है। अन्य मुद्दे व्यक्तिपरक हो सकते हैं या मानवीय हस्तक्षेप की आवश्यकता हो सकती है, जैसे एक बड़े मेथड को रिफैक्टर करना। इन मामलों में, कोई स्वचालन संभव नहीं है।
कन्वेंशन या कॉन्फ़िगरेशन
एक समुदाय या परियोजना के भीतर अक्सर भारी बहस होती है कि कौन से नियम समझ में आते हैं।
पारंपरिक समाधान प्रत्येक टीम को अपने सदस्यों के भीतर बहस को हल करने की अनुमति देना है जिससे उन्हें लिंटिंग नियमों को अपने स्वाद के अनुसार कॉन्फ़िगर करने की अनुमति मिलती है। हालांकि, हाल के वर्षों में, कई भाषाओं में एकल कन्वेंशन को मानकीकृत करने की दिशा में एक धक्का लगा है। हालांकि यह हर जगह लागू नहीं है, सामान्य विचार यह है कि डेवलपर्स के पास कोड स्टाइल करते समय मानसिक ओवरहेड को पूरी तरह से हटा दिया जाए। इस बात पर चर्चा करने के बजाय कि कौन सी लाइन लंबाई सबसे अच्छी है, हर कोई केवल समुदाय-सहमत नियमों का उपयोग करता है।
Ruby में, यह कमोबेश दो मौजूदा लिंटर्स में अनुवादित होता है: RuboCop, जो पूर्ण-कॉन्फ़िगरेशन की अनुमति देता है और StandardRB, जो विपरीत दृष्टिकोण अपनाता है और एक सामान्य मानक को परिभाषित करता है।
RuboCop
नियमों के एक प्रलेखित सेट को नियोजित करता है, जिनमें से प्रत्येक एक विशेष समस्या की तलाश करता है। डेवलपर अपनी परियोजनाओं के भीतर कुछ नियमों को अक्षम या ट्वीक करने में सक्षम हैं:
# अधिकतम अनुमत लाइन लंबाई कॉन्फ़िगर करें Layout/LineLength: Max: 80 # साइक्लोमैटिक जटिलता अक्षम करें Metrics/CyclomaticComplexity: Enabled: false
इसमें पहले से ही समझदार डिफ़ॉल्ट शामिल हैं, इसलिए कॉन्फ़िगरेशन केवल उन विशिष्ट नियमों के लिए आवश्यक है जिन्हें आप बदलना चाहते हैं।
bundle exec rubocop चलाने से RuboCop संपूर्ण कोडबेस का विश्लेषण करेगा और पाए गए सभी मुद्दों को सूचीबद्ध करेगा:
# test.rb def badName if something return "inner result" end "outer result" end
$ bundle exec rubocop Inspecting 1 file C Offenses: test.rb:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment. def badName ^ test.rb:1:5: C: Naming/MethodName: Use snake_case for method names. def badName ^^^^^^^ test.rb:2:3: C: [Correctable] Style/IfUnlessModifier: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &&/||. if something ^^ test.rb:3:12: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. return "inner result" ^^^^^^^^^^^^^^ test.rb:6:3: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. "outer result" ^^^^^^^^^^^^^^ 1 file inspected, 5 offenses detected, 4 offenses auto-correctable
आप फिर bundle exec rubocop --auto-correct चला सकते हैं, और आपके अधिकांश मुद्दे आपके कॉन्फ़िगरेशन के अनुसार ठीक हो जाएंगे।
अपने CI पाइपलाइन के हिस्से के रूप में bundle exec rubocop सेट करने से यह सुनिश्चित होगा कि कोई भी कोड लिंटिंग नियमों को पूरा किए बिना पास नहीं होता।
StandardRB
एक अधिक हालिया प्रोजेक्ट, जो वास्तव में हुड के नीचे RuboCop का उपयोग करता है। StandardRB का मुख्य लक्ष्य पूरी तरह से अलग लिंटर बनाना नहीं है, बल्कि एक मानक तक पहुंचना है जिसे हर कोई बहस करने के बजाय उपयोग कर सके।
लाइटनिंग टॉक जहां इसे पहली बार घोषित किया गया था, प्रेरणाओं के बारे में काफी स्पष्ट है: यदि लोग सिंटैक्टिक विवरणों के बारे में बहस करने में कम समय बिताते हैं और बस समुदाय-व्यापी समझौते के निर्णयों का पालन करते हैं, तो हम सभी अपना अधिक समय वही करने में बिता सकते हैं जो वास्तव में मायने रखता है: महान उत्पाद और लाइब्रेरी बनाना।
चूंकि RuboCop का उपयोग नीचे किया जाता है, आपको मिलने वाला आउटपुट वास्तव में उसी प्रारूप में है। एकमात्र अंतर यह है कि आपको किसी भी नियम को अनुकूलित करने की अनुमति नहीं है।
StandardRB हाल ही में 1.0.0 पर पहुंच गया, जिसका अर्थ है कि किन नियमों का उपयोग करना है, इस बारे में अधिकांश चर्चा पहले ही उनके मुद्दों के पेज पर हो चुकी है। यदि आप किसी विशेष नियम के बारे में परवाह करते हैं या असहमत हैं, तो संभावना है कि आप वहां संबंधित चर्चा देखेंगे।
अंततः, हालांकि, आप आश्वस्त हो सकते हैं कि इसकी कुछ गहराई से चर्चा की गई थी। पूरे समुदाय के लिए सभी बिंदुओं पर 100% सहमत होना असंभव है। इस दृष्टिकोण का दर्शन यह है कि लोग लचीले हैं और एक निर्णय से असहमत हो सकते हैं और प्रतिबद्ध हो सकते हैं।
अंतिम विचार
पिछली परियोजनाओं में लिंटिंग नियमों पर बारीकियों को चुनने में जितना समय मुझे गर्व है, उससे अधिक समय बिताने के बाद, मैं निश्चित रूप से StandardRB के दृष्टिकोण में मूल्य देखता हूं और जब भी संभव हो इसका उपयोग करने की सलाह देता हूं।
चर्चाओं के ओवरहेड को हटाते हुए स्थिरता के सभी लाभों को बनाए रखना, अधिकांश नियमों के लिए स्वचालित सुधारों के साथ, हमें अधिक कुशलता से बेहतर सॉफ्टवेयर वितरित करने में मदद करता है, और जो वास्तव में मायने रखता है उस पर ध्यान केंद्रित करता है।
अन्य भाषाएं समान लो-कॉन्फ़िगरेबिलिटी कोड फॉर्मेटर्स अपना रही हैं। Elixir में mix formatter, और Rust में rustfmt दोनों कुछ कॉन्फ़िगरेबिलिटी की अनुमति देते हैं, लेकिन समुदाय आश्चर्यजनक रूप से मानक के भीतर रहने के साथ ऑनबोर्ड है।
इसके साथ कहा, RuboCop अभी भी एक पूरी तरह से वैध विकल्प है यदि आप, विडंबना यह है कि, इस भावना से असहमत हैं।
P.S. यदि आप Ruby Magic पोस्ट को प्रेस से निकलते ही पढ़ना चाहते हैं, तो हमारे Ruby Magic न्यूज़लेटर की सदस्यता लें और कभी भी एक भी पोस्ट मिस न करें!