"लीक एब्स्ट्रेक्शन" शब्द का क्या अर्थ है? (कृपया उदाहरण के साथ समझाएं। मेरे पास अक्सर एक कठिन सिद्धांत है।
"लीक एब्स्ट्रेक्शन" शब्द का क्या अर्थ है? (कृपया उदाहरण के साथ समझाएं। मेरे पास अक्सर एक कठिन सिद्धांत है।
जवाबों:
यहाँ एक मीटस्पेस उदाहरण है:
ऑटोमोबाइल में ड्राइवरों के लिए सार है। अपने शुद्धतम रूप में, स्टीयरिंग व्हील, एक्सेलेरेटर और ब्रेक है। यह अमूर्त विस्तार बहुत कुछ छुपाता है कि हुड के नीचे क्या है: इंजन, कैम, टाइमिंग बेल्ट, स्पार्क प्लग, रेडिएटर, आदि।
इस अमूर्तता के बारे में साफ-सुथरी बात यह है कि हम कार्यान्वयन के कुछ हिस्सों को उपयोगकर्ता को वापस लिए बिना बेहतर भागों के साथ बदल सकते हैं। मान लें कि हम वितरक कैप को इलेक्ट्रॉनिक इग्निशन से बदलते हैं, और हम निश्चित कैम को वेरिएबल कैम से बदल देते हैं। ये परिवर्तन प्रदर्शन में सुधार करते हैं, लेकिन उपयोगकर्ता अभी भी पहिया के साथ चलता है और पैडल का उपयोग शुरू करने और रोकने के लिए करता है।
यह वास्तव में काफी उल्लेखनीय है ... 16 साल का या 80 साल का व्यक्ति इस जटिल मशीनरी के संचालन को बिना सच में जाने बिना यह जान सकता है कि यह अंदर कैसे काम करता है!
लेकिन लीक हैं। ट्रांसमिशन एक छोटा रिसाव है। ऑटोमैटिक ट्रांसमिशन में आप कार को एक पल के लिए बिजली खो सकते हैं क्योंकि यह गियर स्विच करता है, जबकि सीवीटी में आप सभी तरह से चिकनी टॉर्क महसूस करते हैं।
बड़ी लीक हैं, भी। यदि आप इंजन को बहुत तेज चलाते हैं, तो आप इसे नुकसान पहुंचा सकते हैं। यदि इंजन ब्लॉक बहुत ठंडा है, तो कार शुरू नहीं हो सकती है या इसमें खराब प्रदर्शन हो सकता है। और यदि आप एक ही समय में रेडियो, हेडलाइट्स और एसी सभी को क्रैंक करते हैं, तो आप देखेंगे कि आपका गैस लाभ नीचे जाएगा।
इसका सीधा सा मतलब है कि आपका अमूर्त कार्यान्वयन विवरणों में से कुछ को उजागर करता है, या यह कि आपको अमूर्तता का उपयोग करते समय कार्यान्वयन विवरण के बारे में पता होना चाहिए। यह शब्द जोएल स्पोल्स्की के लिए जिम्मेदार है , लगभग 2002। अधिक जानकारी के लिए विकिपीडिया लेख देखें।
एक क्लासिक उदाहरण नेटवर्क लाइब्रेरी है जो आपको दूरस्थ फ़ाइलों को स्थानीय मानने की अनुमति देता है। इस अमूर्त का उपयोग करने वाले डेवलपर को पता होना चाहिए कि नेटवर्क की समस्याएं इस तरह से विफल हो सकती हैं जो स्थानीय फ़ाइलों में नहीं होती हैं। फिर आपको नेटवर्क लाइब्रेरी द्वारा प्रदान की गई अमूर्तता के बाहर विशेष रूप से त्रुटियों को संभालने के लिए कोड विकसित करने की आवश्यकता होती है।
इसके लिए विकिपीडिया की बहुत अच्छी परिभाषा है
एक टपका हुआ अमूर्त किसी भी लागू अमूर्त को संदर्भित करता है, जिसका उद्देश्य जटिलता को कम करना (या छिपाना) है, जहां अंतर्निहित विवरण पूरी तरह से छिपा नहीं है
या सॉफ्टवेयर के लिए दूसरे शब्दों में यह तब होता है जब आप प्रोग्राम में सीमाओं या दुष्प्रभावों के माध्यम से किसी सुविधा के कार्यान्वयन विवरण का निरीक्षण कर सकते हैं।
एक त्वरित उदाहरण C # / VB.Net क्लोजर होगा और रेफ / आउट मापदंडों को पकड़ने में उनकी अक्षमता होगी। उठाने की प्रक्रिया कैसे होती है, इसके कार्यान्वयन विस्तार के कारण उन्हें कैप्चर नहीं किया जा सकता है। यह कहना नहीं है, हालांकि ऐसा करने का एक बेहतर तरीका है।
यहां .NET डेवलपर्स से परिचित एक उदाहरण दिया गया है: ASP.NET Page
कक्षा HTTP ऑपरेशन के विवरण, विशेष रूप से फॉर्म डेटा के प्रबंधन को छिपाने का प्रयास करती है, ताकि डेवलपर्स को पोस्ट किए गए मानों से निपटना न पड़े (क्योंकि यह स्वचालित रूप से सर्वर पर मूल्यों को मैप करता है नियंत्रण)।
लेकिन अगर आप सबसे बुनियादी उपयोग परिदृश्यों से परे भटकते हैं तो Page
अमूर्त रिसाव शुरू हो जाता है और तब तक पृष्ठों के साथ काम करना मुश्किल हो जाता है जब तक कि आप वर्ग के कार्यान्वयन विवरण को नहीं समझते हैं।
एक सामान्य उदाहरण गतिशील रूप से एक पृष्ठ पर नियंत्रण जोड़ रहा है - गतिशील रूप से जोड़े गए नियंत्रणों का मूल्य आपके लिए तब तक मैप नहीं किया जाएगा जब तक कि आप उन्हें सही समय पर नहीं जोड़ते : अंतर्निहित इंजन से पहले आने वाले फ़ॉर्म मानों को उपयुक्त नियंत्रणों में मैप करता है। जब आपको यह सीखना होगा कि अमूर्तता लीक हो गई है ।
खैर, एक तरह से यह विशुद्ध रूप से सैद्धांतिक बात है, हालांकि महत्वहीन नहीं है।
हम सार का उपयोग चीजों को समझने में आसान बनाने के लिए करते हैं। मैं इस तथ्य को छिपाने के लिए कुछ भाषा में एक स्ट्रिंग क्लास पर काम कर सकता हूं कि मैं व्यक्तिगत आइटम वाले वर्णों के एक सेट के साथ काम कर रहा हूं। मैं इस तथ्य को छिपाने के लिए वर्णों के एक निर्धारित सेट से निपटता हूं कि मैं संख्याओं के साथ काम कर रहा हूं। मैं इस तथ्य को छिपाने के लिए संख्याओं से निपटता हूं कि मैं 1s और 0s के साथ काम कर रहा हूं।
एक टपका हुआ अमूर्त वह है जो विवरण को छिपाने के लिए नहीं छिपाता है। यदि Java या .NET में 5-कैरेक्टर स्ट्रिंग पर कॉल स्ट्रिंग। या तो मुझे 5 से 10 तक कोई भी उत्तर मिल सकता है, कार्यान्वयन विवरण के कारण जहां वे भाषाएं वर्ण कहलाती हैं, वे वास्तव में UTF-16 डेटा-पॉइंट हैं जो 1 या दोनों का प्रतिनिधित्व कर सकते हैं एक चरित्र का .5। अमूर्तन लीक हो गया है। हालांकि इसे लीक नहीं करना है, इसका मतलब है कि लंबाई को खोजने के लिए या तो अधिक स्टोरेज स्पेस की आवश्यकता होगी (वास्तविक लंबाई को स्टोर करने के लिए) या O (1) से O (n) होने पर (वास्तविक लंबाई क्या है) यह पता लगाने के लिए इसमें बदलाव करना होगा। अगर मुझे असली जवाब की परवाह है (अक्सर आप वास्तव में नहीं करते हैं) तो आपको उस ज्ञान पर काम करने की ज़रूरत है जो वास्तव में चल रहा है।
अधिक विवादित मामले ऐसे मामलों के साथ होते हैं, जहां एक विधि या संपत्ति आपको आंतरिक कामकाज में मिलती है, चाहे वे अमूर्त लीक हों, या अच्छी तरह से परिभाषित तरीके से अमूर्त स्तर पर चले जाएं, कभी-कभी ऐसे लोग असहमत हो सकते हैं।
मैं RPC का उपयोग करके उदाहरण देने की नस में जारी रखूँगा।
आरपीसी की आदर्श दुनिया में, एक दूरस्थ प्रक्रिया कॉल को स्थानीय प्रक्रिया कॉल की तरह दिखना चाहिए (या तो कहानी जाती है)। यह प्रोग्रामर के लिए पूरी तरह से पारदर्शी होना चाहिए, जब वे कहते हैं कि SomeObject.someFunction()
उन्हें पता नहीं है कि SomeObject
(या सिर्फ someFunction
उस मामले के लिए) स्थानीय रूप से संग्रहीत और निष्पादित या दूरस्थ रूप से संग्रहीत और निष्पादित किया गया है। सिद्धांत यह जाता है कि यह प्रोग्रामिंग को सरल बनाता है।
वास्तविकता अलग है क्योंकि स्थानीय फ़ंक्शन कॉल करने के बीच एक बड़ा अंतर है (भले ही आप दुनिया की सबसे धीमी व्याख्या की गई भाषा का उपयोग कर रहे हों) और:
अकेले समय में यह लगभग तीन आदेश (या अधिक!) परिमाण अंतर का है। परिमाण के उन तीन + आदेशों से प्रदर्शन में बहुत बड़ा बदलाव होने जा रहा है, जो आपके प्रक्रिया कॉल रिसाव को रोक देगा, बल्कि स्पष्ट रूप से पहली बार जब आप गलती से एक आरपीसी को वास्तविक फ़ंक्शन कॉल मानते हैं। इसके अलावा एक वास्तविक फ़ंक्शन कॉल, आपके कोड में गंभीर समस्याओं को छोड़कर, कार्यान्वयन बग के बाहर बहुत कम विफलता बिंदु होंगे। RPC कॉल में निम्नलिखित सभी संभावित समस्याएँ होती हैं, जो एक नियमित स्थानीय वेबसाइट से अपेक्षित मामलों में असफलता के मामलों के रूप में सामने आती हैं:
तो अब आपकी RPC कॉल जो "बस एक स्थानीय फ़ंक्शन कॉल की तरह है" में अतिरिक्त विफलता की स्थितियों का एक पूरा बोझ है जिसे आपको स्थानीय फ़ंक्शन कॉल करते समय विरोध नहीं करना पड़ता है। अमूर्त फिर से लीक हो गया है, और भी कठिन।
अंत में आरपीसी एक बुरा अमूर्त है क्योंकि यह हर स्तर पर छलनी की तरह लीक होता है - जब सफल और जब दोनों असफल।
Django ORM में एक उदाहरण कई-से-कई उदाहरण :
नमूना API उपयोग में सूचना जिसे आपको .save () आधार आलेख ऑब्जेक्ट a1 चाहिए, इससे पहले कि आप कई-कई विशेषताओं में प्रकाशन ऑब्जेक्ट जोड़ सकें। और ध्यान दें कि कई-से-कई विशेषता को अपडेट करने से अंतर्निहित डेटाबेस को तुरंत सहेजा जाता है, जबकि एकवचन विशेषता को अपडेट करना तब तक db में परिलक्षित नहीं होता है जब तक कि .save () नहीं कहा जाता है।
अमूर्तता यह है कि हम एक वस्तु ग्राफ के साथ काम कर रहे हैं, जहां एकल-मूल्य विशेषताएँ और बहु-मूल्य विशेषताएँ केवल विशेषताएँ हैं। लेकिन एक रिलेशनल डेटाबेस समर्थित डेटा स्टोर लीक के रूप में कार्यान्वयन ... RDBS की अखंडता प्रणाली एक वस्तु इंटरफ़ेस के पतले लिबास के माध्यम से प्रकट होती है।
सबसे पहले यह समझना सबसे अच्छा है कि "अमूर्त" क्या है?
अमूर्तता दुनिया को सरल बनाने का एक तरीका है। इसका मतलब है कि आपको इस बारे में चिंता करने की ज़रूरत नहीं है कि पर्दे के पीछे वास्तव में क्या हो रहा है। इसका मतलब है कि कुछ बेवकूफाना सबूत है। ठीक है, तो इसका क्या मतलब है? यह सबसे अच्छा उदाहरण द्वारा चित्रित किया गया है।
अमूर्तता का उदाहरण: फ्लाइंग ए 737/747 की जटिलताएं "अमूर्त" हैं
आइए हम एक बोइंग यात्री जेट का उदाहरण लेते हैं। ये विमान मशीनरी के बहुत जटिल टुकड़े हैं। आपके पास जेट इंजन, ऑक्सीजन सिस्टम, इलेक्ट्रिकल सिस्टम, लैंडिंग गियर सिस्टम आदि हैं, लेकिन पायलट को जेट इंजन की पेचीदगियों के बारे में चिंता करने की ज़रूरत नहीं है .... यह सब "सार दूर" है, जिसका अर्थ है: के अंत में दिन, एक पायलट केवल विमान को नियंत्रित करने के लिए पहिया और एक नियंत्रण स्तंभ के बारे में चिंतित है। बाएं जाने के लिए बाएं, और दाएं जाने के लिए दाएं, ऊंचाई हासिल करने के लिए ऊपर खींचें, और नीचे उतरने के लिए धक्का दें। यह काफी सरल है ...... वास्तव में मैंने झूठ बोला था: स्टीयरिंग व्हील को नियंत्रित करना थोड़ा अधिक जटिल है। एक आदर्श दुनिया में, बस यही एक चीज उसे चाहिएके बारे मे चिंता करना। लेकिन वास्तविक जीवन में ऐसा नहीं है: यदि आप एक बंदर की तरह एक विमान उड़ाते हैं, तो बिना किसी वास्तविक समझ के कि कोई विमान कैसे संचालित होता है, या कार्यान्वयन विवरणों में से कोई है, तो आप संभावित रूप से दुर्घटनाग्रस्त हो जाएंगे और सभी को बोर्ड पर मार देंगे।
वास्तव में, एक पायलट को बहुत सारी महत्वपूर्ण चीजों के बारे में चिंता करने की ज़रूरत होती है - सब कुछ दूर नहीं किया गया है: पायलटों को हवा की गति, जोर, हमले के कोण, ईंधन, ऊंचाई, मौसम की समस्याओं, वंश के कोणों के बारे में चिंता करना होगा, चाहे पायलट सही दिशा में जा रहा है, जहां विमान अभी और इसी तरह है। कंप्यूटर इन कार्यों में पायलट की मदद कर सकता है, लेकिन सब कुछ स्वचालित / सरलीकृत नहीं है।
जैसे यदि पायलट स्तंभ पर बहुत अधिक मुश्किल खींचता है - विमान पालन करेगा, लेकिन तब पायलट विमान को रोकने का जोखिम उठाएगा, और यदि आप विमान को रोकते हैं, तो जमीन पर वापस दुर्घटनाग्रस्त होने से पहले नियंत्रण हासिल करना कठिन है। ।
दूसरे शब्दों में, पायलट के लिए केवल कुछ और जाने बिना स्टीयरिंग व्हील को नियंत्रित करना पर्याप्त नहीं है ......... nooooo ....... उसे विमान के अंतर्निहित जोखिमों और सीमाओं के बारे में पता होना चाहिए इससे पहले कि वह एक उड़ान भरता है ....... उसे पता होना चाहिए कि विमान कैसे काम करता है, और विमान कैसे उड़ता है; उसे कार्यान्वयन विवरण पता होना चाहिए ..... उसे पता होना चाहिए कि बहुत मुश्किल से खींचने पर एक स्टाल हो जाएगा, या यह कि बहुत अधिक लैंडिंग विमान को नष्ट कर देगा।
वे चीजें अमूर्त नहीं हैं। बहुत सी चीजें दूर होती हैं, लेकिन सब कुछ नहीं। पायलट को केवल स्टीयरिंग कॉलम के बारे में चिंता करने की ज़रूरत है, और शायद एक या दो अन्य चीजें। अमूर्तता "लीक" है।
...... आपके कोड में भी यही बात है। यदि आप अंतर्निहित कार्यान्वयन विवरण नहीं जानते हैं, तो अधिक बार नहीं, आप अपने आप को एक कोने में काम करेंगे।
यहाँ कोडिंग में एक उदाहरण है:
ORMs डेटाबेस प्रश्नों से निपटने में बहुत परेशानी का सार करते हैं, लेकिन अगर आपने कभी ऐसा कुछ किया है:
User.all.each do |user|
puts user.name # let's print each user's name
end
तब आपको एहसास होगा कि आपके ऐप को मारने का यह एक अच्छा तरीका है यदि आपको कुछ मिलियन से अधिक उपयोगकर्ता मिले हैं। सब कुछ अमूर्त नहीं है। आपको यह जानना होगा कि User.all
25 मिलियन उपयोगकर्ताओं के साथ कॉलिंग आपके मेमोरी उपयोग को बढ़ाने वाली है, और समस्याओं का कारण बनने जा रही है। आपको कुछ अंतर्निहित विवरणों को जानना होगा। अमूर्त टपका हुआ है।
तथ्य यह है कि कुछ बिंदु पर , जो आपके पैमाने और निष्पादन द्वारा निर्देशित होगा, आपको अपने अमूर्त ढांचे के कार्यान्वयन विवरण से परिचित होने की आवश्यकता होगी ताकि यह समझ सके कि यह उस तरह से व्यवहार करता है जैसे वह व्यवहार करता है।
उदाहरण के लिए, इस SQL
प्रश्न पर विचार करें :
SELECT id, first_name, last_name, age, subject FROM student_details;
और इसका विकल्प:
SELECT * FROM student_details;
अब, वे तार्किक रूप से समतुल्य समाधानों की तरह दिखते हैं, लेकिन व्यक्तिगत कॉलम नाम विनिर्देश के कारण पहले वाले का प्रदर्शन बेहतर है।
यह एक तुच्छ उदाहरण है लेकिन अंततः यह जोएल स्पोल्स्की बोली पर वापस आता है:
सभी गैर-तुच्छ सार, कुछ हद तक टपका हुआ है।
कुछ बिंदु पर, जब आप अपने ऑपरेशन में एक निश्चित पैमाने पर पहुंचेंगे, तो आप अपने DB (SQL) के काम करने के तरीके को अनुकूलित करना चाहेंगे। ऐसा करने के लिए, आपको रिलेशनल डेटाबेस के काम करने के तरीके को जानना होगा। यह शुरुआत में आपके लिए सार था, लेकिन यह टपका हुआ है। आपको कुछ बिंदु पर इसे सीखने की जरूरत है।
मान लें, हमारे पास एक पुस्तकालय में निम्नलिखित कोड है:
Object[] fetchDeviceColorAndModel(String serialNumberOfDevice)
{
//fetch Device Color and Device Model from DB.
//create new Object[] and set 0th field with color and 1st field with model value.
}
जब उपभोक्ता एपीआई को कॉल करता है, तो उन्हें एक वस्तु मिलती है []। उपभोक्ता को यह समझना होगा कि ऑब्जेक्ट सरणी के पहले फ़ील्ड का रंग मान है और दूसरा फ़ील्ड मॉडल मान है। यहां लाइब्रेरी से कंज्यूमर कोड तक एब्स्ट्रैक्शन लीक हो गया है।
समाधानों में से एक वस्तु को वापस करना है जो डिवाइस के मॉडल और रंग को घेरता है। उपभोक्ता उस वस्तु को मॉडल और रंग मूल्य प्राप्त करने के लिए कॉल कर सकता है।
DeviceColorAndModel fetchDeviceColorAndModel(String serialNumberOfTheDevice)
{
//fetch Device Color and Device Model from DB.
return new DeviceColorAndModel(color, model);
}
लीकेज एब्स्ट्रैक्शन राज्य को घेरने वाला है। टपका हुआ अमूर्त का बहुत सरल उदाहरण:
$currentTime = new DateTime();
$bankAccount1->setLastRefresh($currentTime);
$bankAccount2->setLastRefresh($currentTime);
$currentTime->setTimestamp($aTimestamp);
class BankAccount {
// ...
public function setLastRefresh(DateTimeImmutable $lastRefresh)
{
$this->lastRefresh = $lastRefresh;
} }
और सही तरीका (लीक से हटकर नहीं):
class BankAccount
{
// ...
public function setLastRefresh(DateTime $lastRefresh)
{
$this->lastRefresh = clone $lastRefresh;
}
}
यहाँ अधिक विवरण ।