Rust पर कोड रिव्यू सिर्फ ब्रैकेट जाँचना नहीं है
\n\nRust एक ऐसी भाषा है जो सुरक्षित मेमोरी प्रबंधन और उच्च प्रदर्शन का वादा करती है। लेकिन सबसे सख्त कंपाइलर भी तार्किक त्रुटियों, गैर-इडियोमैटिक कोड या unsafe के अनुचित उपयोग से नहीं बचा सकता। Rust पर कोड रिव्यू एक कला है। आप सिर्फ यह नहीं देखते कि कर्ली ब्रैकेट बंद हैं या नहीं। आप जाँचते हैं कि डेवलपर ने borrow checker की सीमाओं को कैसे पार किया (या नहीं किया), वह इटरेटर का कितने कुशलता से उपयोग करता है, और क्या वह रॉ पॉइंटर्स के साथ सिस्टम को "धोखा" देने की कोशिश कर रहा है।
इस लेख में, मैं बताऊंगा कि Rust कोड की समीक्षा करते समय किन पहलुओं पर ध्यान देना चाहिए। बिना अनावश्यक सिद्धांत के — केवल व्यावहारिक सुझाव, उदाहरण और एक चेकलिस्ट जिसे आप दीवार पर लटका सकते हैं (या बुकमार्क कर सकते हैं)। चलिए शुरू करते हैं!
\n\n1. स्वामित्व, उधार और जीवनकाल: दर्द का मुख्य स्रोत
\n\nपहली चीज़ जो जाँचनी चाहिए वह है कि स्वामित्व प्रणाली सही ढंग से काम कर रही है या नहीं। भले ही कोड कंपाइल हो जाए, इसका मतलब यह नहीं कि वह सही है। सामान्य समस्याएँ:
\n\n- \n
- अनावश्यक क्लोनिंग। जहाँ रेफरेंस का उपयोग किया जा सकता था, वहाँ डेवलपर डेटा कॉपी करता है। इससे प्रदर्शन खराब होता है। \n
- म्यूटेबल और इम्यूटेबल उधार। यदि एक ही स्कोप में
&mut Tऔर&Tएक साथ हों — तो त्रुटि होगी। लेकिन कभी-कभी कोड को पुनर्व्यवस्थित करके इससे बचा जा सकता है। \n - गलत जीवनकाल (lifetimes)। विशेष रूप से कई रेफरेंस वाली जटिल संरचनाओं में। \n
उदाहरण: खराब कोड
\nfn process(data: &Vec<i32>) -> i32 {\n let mut sum = 0;\n for &x in data.iter() {\n sum += x;\n }\n // सब ठीक है, लेकिन &Vec क्यों पास करें जब &[i32] काफी है?\n sum\n}\n\nअच्छा कोड
\nfn process(data: &[i32]) -> i32 {\n data.iter().sum()\n}\n\nरिव्यू पर क्या जाँचें: क्या &Vec, &String या &HashMap वहाँ पास किया जा रहा है जहाँ स्लाइस पर्याप्त है? क्या बिना आवश्यकता के clone() का उपयोग किया गया है? क्या जीवनकाल एनोटेशन सही ढंग से रखे गए हैं?
2. Unsafe: लाल क्षेत्र
\n\nunsafe ब्लॉक सुरक्षित Rust में एक खुले हैच की तरह हैं। वे उचित, न्यूनतम और सावधानीपूर्वक प्रलेखित होने चाहिए। कोड रिव्यू पर ध्यान दें:
- \n
- unsafe का उपयोग क्यों किया गया है? अक्सर सुरक्षित एब्स्ट्रैक्शन से काम चल सकता है। \n
- रॉ पॉइंटर्स की सटीकता। क्या नल पॉइंटर को डीरेफरेंस नहीं किया जा रहा है? क्या मेमोरी मुक्त होने के बाद कोई रेफरेंस लटका हुआ है? \n
- इनवेरिएंट।
unsafeवाले कोड को स्पष्ट रूप से बताना चाहिए कि वह किन इनवेरिएंट को बनाए रखता है। \n
उदाहरण: खतरनाक unsafe
\nunsafe fn dangerous() {\n let ptr = 0x12345 as *mut i32;\n *ptr = 42; // क्या होगा अगर इस पते पर कुछ नहीं है?\n}\n\nऐसा कोड रिव्यू पास नहीं करना चाहिए। भले ही "यह काम करता है" — यह कोई तर्क नहीं है।
\n\nअच्छा unsafe
\nunsafe fn init_buffer(buf: &mut [u8]) {\n // हमें विश्वास है कि buf वैध मेमोरी की ओर इशारा करता है,\n // क्योंकि कॉल करने वाला पक्ष इसकी गारंटी देता है।\n std::ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len());\n}\n\nक्या जाँचें: क्या प्रत्येक unsafe के लिए स्पष्टीकरण वाली टिप्पणी है? क्या सीमा मामलों की जाँच करने वाले परीक्षण हैं? क्या सुरक्षा गारंटी का उल्लंघन हो रहा है?
3. क्लोज़र और फंक्शनल शैली
\n\nRust फंक्शनल दृष्टिकोण को प्रोत्साहित करता है: इटरेटर, क्लोज़र, map, filter, fold। लेकिन इससे अत्यधिक जटिलता हो सकती है। रिव्यू पर देखें:
- \n
- क्या क्लोज़र का दुरुपयोग हो रहा है? यदि क्लोज़र बहुत सारे वेरिएबल कैप्चर करता है, तो शायद तर्क को एक अलग फंक्शन में निकालना चाहिए।