बिना किसी प्रलेखन के हज़ारों पंक्तियों को कैसे पढ़ें? [बन्द है]


12

पहले मैं एक WPF प्रोजेक्ट के लिए एक अच्छा टाइमलाइन नियंत्रण खोज रहा था। मुझे यहां एक उत्तर मिला, जो मुझे इस कोडप्लेक्स परियोजना के लिए निर्देशित करता है ।

अब मैं अपनी संस्कृति की जरूरतों को पूरा करने के लिए कोड बदलना चाहता हूं। लेकिन कुछ बेमेल हैं!

मेरा सवाल यह है कि:

आप कोड की ऐसी हजारों लाइनों के साथ कैसे इंटरैक्ट करते हैं?

संपादित करें:

कोई भी शॉर्टकट बढ़िया होगा!


3
बढ़त की मांग करो। यह हमेशा मदद करता है। (वे इसमें से एक प्रेरक बना सकते हैं)
प्रदर्शन नाम

2
जब तक यह सब स्पष्ट नहीं हो जाता है तब तक अपने सिर को डेस्क के सामने रखें।
जेलिफ़िश्री

19
आप हाथी कैसे खा करते हैं? ... एक बार में एक काटता है।
बिल

1
@ जयलाल यही तो वे चाहते हैं कि आप सोचें।
मतीन उल्हाक

2
@DisplayName, प्रेरणा के लिए गाजर और स्टिक दृष्टिकोण को किसी भी काम के लिए एक खराब समाधान दिखाया गया है जिसके लिए अल्पविकसित संज्ञानात्मक कौशल की आवश्यकता होती है। प्रेरणा विज्ञान पुरस्कार प्रणाली की तुलना में अधिक जटिल है। डैन पिंक द्वारा ates ड्राइव: द हैवी सत्य ’हमें प्रेरित करता है, यह एक चौंकाने वाला सच है। या संघनित संस्करण के लिए आप यह ट्यूब वीडियो देखें। youtube.com/watch?v=u6XAPnuFjJc
रयान टेलर

जवाबों:


37

जब आप ऐसा करने में सक्षम होने के लिए पर्याप्त समझ गए हों, तो आप स्रोत कोड में टिप्पणियां जोड़ते हैं। जैसा कि आप अधिक से अधिक समझते हैं, इन टिप्पणियों को सख्ती से पढ़ें।


3
+1 और एक अच्छा तरीका यह है कि जब आप स्रोत कोड को ब्राउज़ करते हैं तो वास्तव में दस्तावेज़ीकरण लिखें। और ऑप कोऑर्डिनेटरों को अपना योगदान वापस क्यों भेजें?

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

1
यदि मूल परियोजना एक वितरित स्रोत नियंत्रण प्रणाली (जैसे गिट) में है, तो इसे कांटा करना, अपने परिवर्तनों को

8
  1. कोड के माध्यम से कदम
  2. आवश्यकतानुसार नाम बदलें
  3. आवश्यकतानुसार रिफ्लेक्टर
  4. तब तक दोहराएं जब तक आप पूरी तरह से समझ नहीं लेते

... और कोड आपको इसके लिए धन्यवाद देगा। ;-)


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

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

+1 कोडर। और यह उत्तर वर्तमान में इकाई परीक्षणों का भी उल्लेख नहीं करता है । डरावना।
MarkJ

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

5

सिंगल एक्शन लें, डिबग (बार-बार) कोड को यह पता लगाने के लिए कि एक्शन कैसे पूरा होता है। बेहतर समझ पाने के लिए सरल भाषा में इसे लिखें!


मैं आम तौर पर ऐसा तब तक करता हूं जब तक मुझे एक परियोजना का सामना नहीं करना पड़ता है जो डिबग मोड में चलने में सक्षम नहीं है! यह हमेशा स्टार्ट अप के दौरान दुर्घटनाग्रस्त होता है! :( लेकिन यह रिलीज़ मोड में ठीक चलता है: एस
अफ़रीज़ा एन। अरवी

@afriza क्या हुआ? यह कुछ गंभीर रूप से बुरा कोड है, जांच करें कि यह आपको क्या त्रुटियां देता है।
डैनियल एस

@afriza, पहली बात तय!

4

जोएल स्पोल्स्की ने अपने ब्लॉग पर (अब लेख नहीं मिल सकता है) कुछ इस तरह लिखा कि वास्तव में इस बारे में मेरे साथ अटक गया:

उन्होंने कहा कि कैसे कोड प्राकृतिक मानव भाषा नहीं है, लेकिन प्रोग्रामर के रूप में, हम आसानी से यह सोचकर आलसी हो जाते हैं कि यह है, और हमें इसे पढ़ने में सक्षम होना चाहिए। नतीजतन, हम में से बहुत से लोग नए कोड को देखते हैं और उम्मीद करते हैं कि यह "इसे पढ़ें" और इसे तुरंत समझने में सक्षम हो, जैसे कि यह अंग्रेजी में पाठ का एक ब्लॉक था।

इसलिए मुझे लगता है कि कुंजी मूल रूप से धीमी, पद्धतिगत और वैज्ञानिक होनी चाहिए। और जैसा कि दूसरों ने कहा है - टिप्पणी (और यहां तक ​​कि रिफ्लेक्टर) जैसा कि आप जाते हैं। "मुझे बस इसे देखना चाहिए और तुरंत समझना चाहिए" की मानसिकता में मत पड़ो।

ओह, और हाँ, मैं अभी भी कभी-कभी इस जाल में पड़ता हूँ। "जैसा मैं कहूं वैसा करो, जैसा मैं करता हूं वैसा नहीं" और वह सब। :)


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

दरअसल, अच्छी तरह से लिखा कोड पढ़ना आसान है, लेकिन पाठ के रूप में नहीं। आप बिल्डिंग ब्लॉकों को देखने और मुख्य संरचना को समझने के लिए बस स्कैन करते हैं, सब कुछ पढ़ने की आवश्यकता नहीं है। खराब कोडिंग दृष्टिकोण, पुराने स्कूल कोड की तरह, या एसओएलआईडी और पैटर्न का दुरुपयोग इस कार्य को बहुत कठिन बना सकता है।
कोडर

4

एसई-रेडियो ने डेव थॉमस को इस विषय के बारे में बताया

इस पॉडकास्ट एपिसोड में परियोजना की 'संस्कृति' में प्रवेश करने और मूल निवासियों के रहने के तरीके को समझने के लिए कई सुझाव और तकनीकें हैं।


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

2

मुझे यह हाल ही में 100,000 से अधिक LOC की परियोजना के साथ करना था। मेरा पहला विचार यह था कि पाठ की 100,000 लाइनों की तुलना में 100 या 1000 नोड्स के ग्राफ से पैटर्न देखना आसान है।

इसलिए मैंने 45 मिनट बिताए और एक छोटी (<100LOC) पायथन कार्यक्रम लिखी, जो मुझे इसकी आवश्यकता थी, उसे पार्स करने के लिए और वस्तु संबंधों को आकर्षित करने के लिए। मैंने ग्राफविज़ स्रोत उत्पन्न किया , जो उत्पन्न करने के लिए वास्तव में आसान भाषा है। (यहां पाइथन के बारे में कुछ खास नहीं है: रूबी या सी # या कॉमन लिस्प या जो भी कर सकता था, वह ठीक है।)

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

(शायद यह इसलिए है क्योंकि मैंने कंपाइलर लिया था , लेकिन मुझे यह अजीब लगता है कि जब प्रोग्रामर को किसी समस्या का सामना करना पड़ता है, तो उत्तर हमेशा "एक प्रोग्राम लिखो!" लगता है, सिवाय तब जब समस्या प्रोग्राम के स्रोत कोड को शामिल करती है।: - )


1

डिबगर में इसके माध्यम से कदम रखें क्योंकि यह चलता है, इसका एक नया, बड़े कोड आधार को समझने का एकमात्र तरीका है।


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

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

@grrussel मुझे असहमत होना पड़ता है क्योंकि इसकी नहीं मैं क्या करता हूँ ... मुझे पता नहीं है कि मैं प्रतिनिधि हूँ या नहीं! मैं विषम विराम बिंदु का उपयोग कर सकता हूं (लेकिन अभी भी स्पष्ट रूप से कदम नहीं बढ़ा रहा हूं) और मैं एक टुकड़े को दूसरे से संबंधित करने की अनुमति देने के लिए आईडीई सुविधाओं का उपयोग करता हूं।
मर्फ़

1

यह समझें कि वास्तव में पूर्णता में टटोलने के लिए कोई शॉर्टकट नहीं हैं। (और यदि आप उस वाक्यांश से परेशान हैं, तो आपकी शिक्षा SORELY की उपेक्षा की गई है। यह रॉबर्ट ए हेनलिन द्वारा "स्ट्रेंजर इन ए स्ट्रेंज लैंड" से है।)

इसे पढ़ें, एक समय में एक पृष्ठ, एक समय में एक दिनचर्या। टिप्पणी करें। प्रमुख डेटा संरचनाओं के चित्र बनाएं। एल्गोरिदम को पहचानें। पिछले ज्ञान पर आकर्षित करें।

डीबगर को क्रैंक करने के प्रलोभन का विरोध करें। डीबगर व्यूपोर्ट बहुत छोटा है: आप एक समय में एक पंक्ति देखते हैं, लेकिन आप वास्तव में नहीं देखते हैं कि आप कहां हैं या आप कहां जा रहे हैं।


डिबगर कुछ कन्वेंशन को मूल कोड लेखक के कन्वेंशन के बारे में बताता है कि चरों के अंदर क्या उम्मीद की जाती है (जैसे क्या वे फुल-पाथ या फाइलनाम या रिलेटिव पाथ की उम्मीद करते हैं?) और कई अन्य चीजें इसलिए यह अभी भी मेरी राय में महत्वपूर्ण है
Afri N. Arief

2
-1 यह सोचने के लिए कि आप शांत हैं क्योंकि आप "
ग्रॉक

1

आप जो कुछ भी लिखते हैं, जितना आप साथ ले जा सकते हैं, उतना कोई भी कभी भी उसी स्थिति में समाप्त नहीं होता है, जैसा आपके पास है।


1

आपको सुराग का उपयोग करने की आवश्यकता है। अपने पर्यावरण या IDE की खोज कार्यक्षमता का बड़े पैमाने पर उपयोग करने के लिए आपको जो कुछ भी देखना है उसका एक सुराग प्राप्त करें जो आपको उस कोड के वांछित अनुभाग में ला सकता है जिसे आपको परिवर्तन करने की आवश्यकता है।

जावा कोड की 14 हजार पंक्तियों को पढ़ने का कोई मतलब नहीं है। खोज कार्यक्षमता आपके जीवन रक्षक है


0

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


0

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

बेशक, जैसा कि आप बिट्स को समझते हैं, उस समय आप जो जानते हैं, उसके लिए टिप्पणी करें, संभवतः उन चीज़ों के बारे में नोट करें जिन्हें आप नहीं समझते हैं।

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


0

मैं का उपयोग करके शुरू होगा सिंह संपादक में @shadow मोड के सक्रिय उपयोग के साथ क्लोन नोड्स । यह कोड को बदलने के बिना अध्ययन के तहत कोड के प्रत्येक अनुभाग के लिए नोट्स और टिप्पणियां जोड़ने की अनुमति देता है , और एनोटेशन हमेशा संदर्भ में रहेगा, कोड के बारे में बात कर रहा है। यहाँ एक उदाहरण है वर्कफ़्लो डॉक्स:

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

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


0

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


0

इससे पहले कि आप रिफ्लेक्टर करें कुछ भी परीक्षण लिखें। बहुत सारे परीक्षण। कोड के छोटे ब्लॉकों के लिए बहुत विशिष्ट परीक्षण जो कम से कम कॉल करने योग्य हैं, क्योंकि यह इस बात पर निर्भर करेगा कि आपकी विरासत में गड़बड़ी कैसे लिखी गई है।

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

इसे पहले परीक्षण करके, आप उस कोड में कुछ फेरबदल करने का जोखिम नहीं उठाते हैं, जिसके बारे में आपको पता नहीं है। जब आप कोड को रिफलेक्टर करने आएंगे तो आपके पास एक सुरक्षा जाल भी होगा।


0

मैं समग्र वर्ग आरेख उत्पन्न करने के लिए, डॉक्स ऑक्सीजन जैसे साधनों का उपयोग करता हूं, प्रत्येक वर्ग क्या करता है, इसके बारे में मेरी समझ को जोड़ता है।

फिर मैं बग कतार से कुछ आसान बग उठाता हूं (इससे पहले कि मेरा प्रबंधक मेरे लिए एक कठिन काम: पी) सौंपता है, फिर उस कार्यक्षमता के माध्यम से डिबगर में चला जाए और एक मोटा डेटा प्रवाह या कोड प्रवाह मॉडल उत्पन्न करने का प्रयास करें।

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


0

एक तुच्छ दोष, जैसे, NullPointerException। पहली बार में संगामिति के बारे में कुछ भी करने से बचें, इसकी प्रकृति से कुछ भी एक ही बार में बहुत सारे कोड को समझना शामिल होगा।

एक बार जब आप कुछ कीड़े तय कर लेते हैं तो आपके पास एक अच्छा विचार होगा। मेरे लिए किसी भी दर पर काम करता है।


-2

मूल रूप से एक साफ कोड लिखने की कार्रवाई को डिजाइन से सही शुरू करना चाहिए। अगर हम OOP में कोडिंग कर रहे हैं, तो UML के साथ भाषा आती है, साथियों के साथ साझा करें और आश्वस्त हो जाएं कि डिजाइन अस्पष्ट नहीं है। किसी भी मामले में हम डेवलपर्स को आश्वस्त होना चाहिए कि डिजाइन समस्या को हल करता है और अस्पष्ट नहीं।

जब कोडिंग की बात आती है तो हमें यह सुनिश्चित करना होता है कि डिजाइन कोड में परिवर्तित हो रहा है अर्थात एक वर्ग या संरचना का एक एंटिटी, चेकिंग अभियान आदि।

और मैं एक श्वेत पत्र के माध्यम से चला गया http://queue.acm.org/detail.cfm?id=2063168 जो शैली कोडिंग या कैसे हम अंतरिक्ष, खरोज, फ़ॉन्ट भिन्नता का उपयोग कर सकते सबसे IDEs कर के रूप में हम ज्यादा लिखने के लिए उपयोग कर सकते हैं के बारे में बात करती है सफाई कोड जहां हम इंसान समझ सकते हैं कि मशीनें जितना काम करती हैं। यह टिप्पणी मुक्त कोड लिखने पर अधिक जोर देता है ताकि हमारा कोड स्वयं पैराग्राफ के रूप में दिखाई दे।

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