परिचय: आपकी समीक्षा युद्ध का मैदान क्यों बन जाती है?
\n\nआपने Merge Request भेजा। सब कुछ साफ है, तर्क सही है, कोड कंपाइल हो रहा है। एक घंटे बाद सीनियर से जवाब आता है: "ग्रिफिंडोर को -10 अंक" और 200 लाइनों के कोड पर 35 टिप्पणियाँ। परिचित लगता है?
\n\nC++ कोड समीक्षा केवल सिंटैक्स की जाँच नहीं है। यह एक कला है जो जूनियर और सीनियर को अलग करती है। C++ डेवलपर को मेमोरी और प्रदर्शन पर भारी शक्ति देता है, लेकिन महान शक्ति के साथ अनिर्धारित व्यवहार और संसाधन लीक की बड़ी जिम्मेदारी आती है।
\n\nइस लेख में, हम एक अनुभवी समीक्षक के दिमाग में झाँकेंगे। मैंने वास्तविक टिप्पणियाँ एकत्र की हैं जो सीनियर प्रोडक्शन प्रोजेक्ट्स पर code review में छोड़ते हैं। यदि आप C++ में लिखते हैं और चाहते हैं कि आपके PR पहली बार में स्वीकार हों - ध्यान से पढ़ें। और यदि आप टीम लीड हैं - तो नए लोगों को ऑनबोर्ड करने के लिए इस चेकलिस्ट का उपयोग करें।
\n\n1. खुद को गोली मारना: मैन्युअल मेमोरी प्रबंधन
\n\nसमीक्षा पर सबसे आम विवाद - "तुम स्मार्ट पॉइंटर्स का उपयोग क्यों नहीं कर रहे?"। सीनियर आधुनिक C++ (C++11 और उससे नए) में नंगे new और delete से नफरत करते हैं।
खराब उदाहरण
\nclass DataProcessor {\n int* buffer;\n size_t size;\npublic:\n DataProcessor(size_t s) : size(s) {\n buffer = new int[s]; // कौन हटाएगा?\n }\n\n ~DataProcessor() {\n delete[] buffer; // और अगर कंस्ट्रक्टर में अपवाद हो?\n }\n};\n\nसीनियर की टिप्पणी: "RAII का उल्लंघन। यदि कंस्ट्रक्टर मेमोरी आवंटन के बाद अपवाद फेंकता है - डिस्ट्रक्टर कॉल नहीं होगा। मेमोरी लीक। std::vector या std::unique_ptr का उपयोग करें।"
सही उदाहरण
\nclass DataProcessor {\n std::vector<int> buffer;\npublic:\n explicit DataProcessor(size_t s) : buffer(s) {}\n};\n\nसीनियर RAII (Resource Acquisition Is Initialization) को पसंद करते हैं। यदि आप कोड में new लिखते हैं, तो यह समझाने के लिए तैयार रहें कि std::make_unique या std::vector आपके लिए उपयुक्त क्यों नहीं हैं। 95% मामलों में - वे उपयुक्त हैं।
2. Const-correctness: अपने आप को 'अल्पविराम' लगाएँ
\n\nछूटा हुआ const किसी भी C++ सीनियर डेवलपर के लिए लाल झंडा है। यह केवल शैली नहीं है, यह कोड पाठक और कंपाइलर के साथ एक अनुबंध है।
समीक्षा में क्या गुस्सा दिलाता है
\nstd::string getName() { // const क्यों नहीं?\n return name;\n}\n\nvoid printData(std::vector<int>& data) { // कॉपी? रेफरेंस? बदलता है?\n for (auto& item : data) {\n std::cout << item;\n }\n}\n\nसीनियर की टिप्पणी: "विधि getName() ऑब्जेक्ट को नहीं बदलती - इसे const बनाएँ। पैरामीटर data नहीं बदलता - const std::vector<int>& पास करें। अन्यथा कॉल करने वाला कोड नहीं जानता कि आप उसका डेटा बदलेंगे या नहीं।"
सुधार
\nstd::string getName() const { // const विधि\n return name;\n}\n\nvoid printData(const std::vector<int>& data) { // const रेफरेंस\n for (const auto& item : data) {\n std::cout << item;\n }\n}\n\nनियम सरल है: यदि विधि ऑब्जेक्ट की स्थिति नहीं बदलती - const। यदि फ़ंक्शन तर्क नहीं बदलता - const T&। C++ में Const correctness कोई विकल्प नहीं है, यह एक मानक है।
3. Move-सिमैंटिक्स: कॉपी करना हमारा धर्म नहीं है
\n\nआधुनिक C++ कॉपी करने के बजाय मूव करने के बारे में है। सीनियर तुरंत देख लेते हैं कि आप अनावश्यक कॉपी कहाँ बना रहे हैं और प्रदर्शन को मार रहे हैं।
\n\nखराब पैटर्न
\nstd::vector<int> processData(std::vector<int> data) { // इनपुट पर कॉपी\n // ... बहुत सारा तर्क ...\n return data; // आउटपुट पर कॉपी? या NRVO?\n}\n\nvoid caller() {\n std::vector<int> bigData = {1, 2, 3, ... 1000000};\n auto result = processData(bigData); // एक और कॉपी!\n}\n\nटिप्पणी