सी ++ संक्षिप्त नाम धोखा पत्रक और अधिक। भाग 2: "और न केवल"

यह मेरा संक्षिप्त नाम चीट शीट का दूसरा और अंतिम भाग है जिसे C ++ डेवलपर को जानना चाहिए। C ++ का उल्लेख यहाँ केवल इसलिए किया गया है क्योंकि मैंने मुख्य रूप से अपने लिए चीट शीट बनाई थी, और मैं केवल C ++ डेवलपर हूं।

वास्तव में, इस भाग में ऐसी अवधारणाएँ हैं जिनका दायरा C ++ तक सीमित नहीं है। इसलिए चयन व्यापक दर्शकों के लिए दिलचस्पी का हो सकता है।



पहले भाग की तरह , संक्षिप्तीकरण को समूहीकृत किया जाता है, यदि यह समझ में आता है। अगर इससे कोई मतलब नहीं है, तो वे वर्णानुक्रम में सूचीबद्ध हैं।

समरूपता और परमाणु संचालन:
कैस
ए.बी.ए.
एफएए
आर सी यू

डेटा भंडारण:
ACID
कैप
PACELC
आधार

सॉफ्टवेयर विकास सिद्धांत:
DRY
KISS
YAGNI
एनआईएच
एफटीएसई
जीआरएएसपी
ठोस

अन्य:
ए.बी.आई.
• • गाय
एफबीसी, एफबीसीपी
LRU

कंसीडर और एटॉमिक ऑपरेशंस


कैस


तुलना और स्वैप। विनिमय के साथ तुलना। यह तीन तर्कों के साथ एक परमाणु निर्देश है: परमाणु चर या स्मृति पता, अपेक्षित मूल्य, नया मूल्य। यदि और केवल तभी चर का मान अपेक्षित मान से मेल खाता है, तो चर नया मान प्राप्त करता है और निर्देश सफलतापूर्वक पूरा होता है। कैस या तो बस एक बूलियन मान लौटाता है (और फिर इसे तुलना और सेट कहा जा सकता है), या यदि यह विफल रहता है, तो यह पहले तर्क के वर्तमान मूल्य को भी लौटाता है।

छद्म कोड
bool cas(int* addr, int& expected, int new_value) { if (*addr != expected) { expected = *addr; return false; } *addr = new_value; return true; } 

C ++ में, CAS का प्रतिनिधित्व विधियों std::atomic<T>::compare_exchange_weak , std::atomic<T>::compare_exchange_strong और मुक्त फ़ंक्शंस std::atomic_compare_exchange_weak , std::atomic_compare_exchange_strong* कमजोर और * मजबूत के बीच का अंतर यह है कि पूर्व गलत नकारात्मक परिणाम उत्पन्न कर सकता है। यानी यदि मूल्य अपेक्षित है, तो वे false वापस आएंगे और इसे एक नए के साथ प्रतिस्थापित नहीं करेंगे। * कमजोर संचालन के अस्तित्व का कारण कुछ आर्किटेक्चर पर * मजबूत अपेक्षाकृत महंगा है। ज्यादातर मामलों में, कैस निर्देश एक लूप (तथाकथित कैस लूप) में स्पिन करता है, इसलिए * मजबूत के बजाय * कमजोर का उपयोग करने से तर्क में बदलाव नहीं होगा, लेकिन यह प्रदर्शन में सुधार कर सकता है।

कैस निर्देश का उपयोग सिंक्रोनाइज़ेशन प्राइमेटिव (जैसे म्यूटेक्स और सेमाफोर्स) को लागू करने के लिए किया जाता है और लॉक-फ्री एल्गोरिदम। अक्सर एक ABA समस्या होती है।

और पढ़ें: एक बार (रूसी) , दो (अंग्रेजी)

ए.बी.ए.


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

  • धागा 1 चर के मूल्य को पढ़ता है, यह ए के बराबर है
  • थ्रेड 1 को मजबूर किया जा रहा है, थ्रेड 2 शुरू हो रहा है
  • थ्रेड 2 ए से बी तक चर के मूल्य में परिवर्तन करता है, परिवर्तन का एक गुच्छा बनाता है (परिवर्तन के साथ जुड़े कुछ मूल्य या बस मेमोरी को मुक्त करता है), और फिर फिर से मूल्य बदलता है - बी से ए तक
  • थ्रेड 1, ऑपरेशन फिर से शुरू करता है, पहले प्राप्त मूल्य की वर्तमान के साथ तुलना करता है और निष्कर्ष निकालता है कि कुछ भी नहीं बदला है

समस्या के संभावित समाधान:

  1. सबसे सरल और सबसे स्पष्ट ताले का उपयोग करना है। इसके परिणामस्वरूप सामान्य थ्रेड-सुरक्षित एल्गोरिदम महत्वपूर्ण खंडों के साथ होगा। लेकिन यह ताले से मुक्त होना बंद हो जाएगा। लेकिन अगर यह कैस और एबीए की बात आती है, तो यह सबसे अधिक संभावना है कि कोई विकल्प नहीं है।
  2. तुलनात्मक मानों में विशेष लेबल जोड़ें। उदाहरण के लिए, परिवर्तनों की संख्या का एक काउंटर। एक ओर, यह काउंटर ओवरफ्लो हो सकता है, लेकिन दूसरी ओर, आधुनिक x86_64 प्रोसेसर 128-बिट कैस संचालन का समर्थन करते हैं। यानी जब किसी काउंटर से पॉइंटर्स की तुलना की जाती है, तो आप 64 बिट्स तक दे सकते हैं, और किसी को लगा कि यह एल्गोरिथ्म के निरंतर संचालन के 10 वर्षों के लिए पर्याप्त है।
  3. कुछ आर्किटेक्चर (एआरएम, उदाहरण के लिए) एलएल / एससी (लोड लिंक्ड, स्टोर सशर्त) निर्देश प्रदान करते हैं जो न केवल आपको स्मृति में पते का वर्तमान मूल्य प्राप्त करने की अनुमति देते हैं, बल्कि यह भी समझने के लिए कि क्या यह मूल्य पिछले पढ़ने के बाद बदल गया है।

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

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

एफएए


लायें और जोड़ें। अहम ... प्राप्त करें और जोड़ें (ऐसा लगता है कि इस अवधारणा का रूसी में अनुवाद नहीं किया गया है)। दो तर्कों के साथ एक परमाणु संचालन: स्मृति में एक परमाणु चर या एक पता और जिसके द्वारा इस चर को बदलना होगा। यदि आर्किटेक्चर अनुमति देता है, तो ऑपरेशन बदले हुए चर का पिछला मान लौटाता है (x86 i486 के बाद से अनुमति देता है)। CAS के विपरीत, FAA हमेशा सफल होता है।

छद्म कोड
 int faa(int* addr, int diff) { int value = *addr; *addr = value + diff; return value; } 

C ++ में, इसे विधियों std::atomic<T>::fetch_add , fetch_sub , fetch_and , fetch_or , fetch_xor और इसी मुक्त कार्य std::atomic_fetch_add , आदि के परिवारों के रूप में लागू किया जाता है।

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

और पढ़ें: एक बार (रूसी) , दो (अंग्रेजी)

RCU


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

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

बहुत सरल आरसीयू इस तरह काम करता है:

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

RCU डेटा के लिए बहुत अच्छा है जिसे अक्सर पढ़ा जाता है और शायद ही कभी अपडेट किया जाता है। यह तंत्र सक्रिय रूप से लिनक्स कर्नेल में उपयोग किया जाता है, जहां अनुग्रह अवधि समाप्त होने पर यह निर्धारित करना काफी सरल है।

नुकसान:

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

और पढ़ें: एक बार (रूसी) , दो (अंग्रेजी)

डेटा भंडारण


एसिड


परमाणु, संगति, अलगाव, स्थायित्व। एटोमिसिटी, संगति, अलगाव, स्थायित्व। यह एक डीबीएमएस में लेनदेन आवश्यकताओं का एक समूह है। एसीआईडी त्रुटियों के मामले में भी विश्वसनीय और अनुमानित डीबीएमएस ऑपरेशन प्रदान करता है।

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

सभी प्रमुख संबंधपरक डीबीएमएस पूरी तरह से एसीआईडी ​​का समर्थन करते हैं। NoSQL दुनिया में, ऐसे पूर्ण समर्थन की संभावना अधिक अपवाद है।

और पढ़ें: एक समय (अंग्रेजी) , दो (अंग्रेजी)

कैप


कैप प्रमेय। कैप प्रमेय। प्रमेय बताता है कि किसी भी वितरित प्रणाली में सूची से दो से अधिक गुण नहीं हो सकते हैं: डेटा संगति ( संगति ), उपलब्धता ( उपलब्धता ), पृथक्करण का प्रतिरोध ( विभाजन सहिष्णुता )।

  • इस मामले में संगति का अर्थ है (सरलीकृत) सुसंगत संगति। यानी जैसे ही एक नोड पर डेटा अपडेट ऑपरेशन सफलतापूर्वक पूरा हो गया है, अन्य सभी नोड्स में पहले से ही यह अपडेट किया गया डेटा है। तदनुसार, सभी नोड्स एक सुसंगत स्थिति में हैं। यह ACID द्वारा अपेक्षित संगतता नहीं है।
  • उपलब्धता का मतलब है कि प्रत्येक विफल नोड उचित समय में प्रत्येक अनुरोध (पढ़ने और लिखने के लिए) के लिए एक सही उत्तर देता है। इसमें कोई गारंटी नहीं है कि विभिन्न नोड्स से प्रतिक्रियाएं मेल खाती हैं।
  • पृथक्करण के प्रतिरोध का मतलब है कि सिस्टम अपने नोड्स के बीच मनमाने ढंग से संदेशों के नुकसान के मामले में सही ढंग से काम करना जारी रखेगा।

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

चुनाव सीपी और एपी के बीच है, अर्थात, स्थिरता और उपलब्धता के बीच। पारंपरिक संबंधपरक डीबीएमएस जो एसीआईडी ​​सिद्धांतों का पालन करते हैं, संगति पसंद करते हैं। जबकि कई NoSQL समाधान पहुंच और BASE चुनते हैं।

नेटवर्क के सामान्य संचालन के मामले में, अर्थात्, जब कोई नेटवर्क पृथक्करण नहीं होता है, तो कैप प्रमेय स्थिरता और उपलब्धता पर कोई प्रतिबंध नहीं लगाता है। यानी कुछ दान करना आवश्यक नहीं है।

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

PACELC


PACELC प्रमेय। PACELC प्रमेय। यह सीएपी प्रमेय का एक विस्तार है, जिसमें कहा गया है कि नेटवर्क विभाजन ( विभाजन ) के मामले में एक वितरित प्रणाली उपलब्धता ( संगतता ) के बीच चयन करने के लिए मजबूर है, और सामान्य नेटवर्क संचालन ( एल्स ) के मामले में, आपको विलंबता ( संगतता) का चयन करना होगा )।

तदनुसार, यदि कैप प्रमेय सिस्टम के 2 वर्गों को अलग करता है जो नेटवर्क पृथक्करण के साथ स्थिर हैं, तो PACELC उनमें से 4 हैं: PA / EL , PA / EC , PC / EL और PC / EC । कुछ NoSQL डेटाबेस सेटिंग्स के आधार पर अपनी कक्षा बदल सकते हैं।

और पढ़ें: एक बार (रूसी) , दो (अंग्रेजी)

आधार


मूल रूप से उपलब्ध, नरम स्थिति, अंततः स्थिरता। बुनियादी उपलब्धता, नाजुक स्थिति, लंबे समय में स्थिरता। वितरित प्रणालियों में CAP प्रमेय के अनुसार, कुछ को छोड़ना होगा। लंबे समय में सुसंगतता के पक्ष में सख्त सहवास को आमतौर पर छोड़ दिया जाता है। जिसका अर्थ है कि डेटा परिवर्तनों की अनुपस्थिति में, सिस्टम किसी दिन अंततः एक सुसंगत स्थिति में आ जाएगा।

इस तरह के एक समझौते को इंगित करने के लिए, संक्षिप्त नाम BASE को कुछ कसकर इस्तेमाल किया जाने लगा, और रासायनिक शब्दों का एक खेल निकला ( ACID - अम्लता, BASE - मूलता)।

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

और पढ़ें: एक समय (अंग्रेजी) , दो (अंग्रेजी)

सॉफ्टवेयर विकास सिद्धांत


सूखी


अपने आप को दोहराएं नहीं। दोहराओ मत। यह सॉफ्टवेयर विकास का सिद्धांत है, जिसका मुख्य विचार सिस्टम में डुप्लिकेट जानकारी की मात्रा को कम करना है, और लक्ष्य सिस्टम की जटिलता को कम करना और इसकी प्रबंधन क्षमता को बढ़ाना है।

एंड्रयू हंट और डेविड थॉमस द्वारा मूल ( द प्रोगैमैटिक प्रोग्रामर बुक) में, इस सिद्धांत को इस प्रकार तैयार किया गया है: "ज्ञान के प्रत्येक टुकड़े में प्रणाली के भीतर एक एकल, सुसंगत और आधिकारिक प्रतिनिधित्व होना चाहिए।" इस मामले में, ज्ञान को किसी विषय क्षेत्र या एल्गोरिथ्म के किसी भी भाग का मतलब समझा जाता है: एक कोड, एक डेटाबेस स्कीमा, एक निश्चित इंटरैक्शन प्रोटोकॉल, आदि। इस प्रकार, सिस्टम में एक परिवर्तन करने के लिए, केवल एक "ज्ञान" को एक स्थान पर अपडेट करने की आवश्यकता होती है।

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

कोड दोहराव DRY उल्लंघन का सिर्फ एक विशेष मामला है। और हमेशा ऐसा नहीं होता है। यदि कोड के दो टुकड़े समान दिखते हैं, लेकिन प्रत्येक अपने स्वयं के व्यावसायिक तर्क को लागू करते हैं, तो DRY टूटा नहीं है।

किसी भी अन्य सिद्धांत की तरह, DRY एक उपकरण है, न कि हठधर्मिता। सिस्टम जितना बड़ा होगा, इस सिद्धांत का उल्लंघन करना उतना ही आसान होगा। पहला, आदर्श अप्राप्य है। और दूसरी बात, अगर आँख बंद करके DRY अधिक जटिल कोड की ओर ले जाता है और इसे समझना अधिक कठिन हो जाता है, तो इसे छोड़ देना बेहतर है।

और पढ़ें: एक (रूसी) , दो (रूसी)

KISS


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

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

इस सब के साथ, किसी को यह नहीं भूलना चाहिए कि सादगी एक लक्ष्य नहीं है, बल्कि केवल एक गैर-कार्यात्मक आवश्यकता है। मुख्य बात यह है कि डिजाइन / कार्यान्वयन लक्ष्य को प्राप्त करना है, और इसे सरलतम संभव तरीके से करना उचित है।

और अधिक पढ़ें: एक (रूसी) , दो (रूसी) , तीन (अंग्रेजी)

YAGNI


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

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

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

सिद्धांत YAGNI कई कट्टरपंथी सूखी और KISS । यदि वे सिस्टम को समझने योग्य भागों में तोड़ते हैं और निर्णय को सरल बनाते हैं, तो YAGNI बस अनावश्यक भागों और समाधानों को काट देता है।

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

एनआईएच


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

यहाँ NIH को सही ठहराने वाले कुछ मामले दिए गए हैं:

  • तीसरे पक्ष के समाधान की गुणवत्ता पर्याप्त उच्च नहीं है, या कीमत काफी कम नहीं है।
  • एक तृतीय-पक्ष समाधान में लाइसेंस प्रतिबंध हैं।
  • तृतीय-पक्ष समाधान का उपयोग करने से इसके आपूर्तिकर्ता पर निर्भरता पैदा होती है और इस तरह से व्यापार को खतरा होता है।

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

एफटीएसई


सॉफ्टवेयर इंजीनियरिंग के मौलिक सिद्धांत। सॉफ्टवेयर विकास का मौलिक प्रमेय। दरअसल, यह कोई प्रमेय नहीं है, इसका कोई प्रमाण नहीं है। एंड्रयू कोएनिग द्वारा यह एक प्रसिद्ध कहावत है:
अमूर्त की एक और परत जोड़कर किसी भी समस्या को हल किया जा सकता है।
कभी-कभी वे इस वाक्यांश को जोड़ते हैं "... अमूर्तता की बहुत सारी परतों की समस्या को छोड़कर।" सामान्य तौर पर, "प्रमेय" कोई गंभीर बात नहीं है, लेकिन इसके बारे में जानने लायक है।

और पढ़ें: एक समय (अंग्रेजी) , दो (अंग्रेजी)

GRASP


सामान्य जिम्मेदारी असाइनमेंट सॉफ्टवेयर पैटर्न। सामान्य जिम्मेदारी आवंटन टेम्पलेट। ये नौ पैटर्न क्रेग लर्मन द्वारा यूएमएल और पैटर्न लागू करने में तैयार किए गए हैं। प्रत्येक टेम्पलेट एक (लेकिन सामान्य) सॉफ़्टवेयर डिज़ाइन समस्या का एक विशिष्ट समाधान है।

  1. सूचना विशेषज्ञ । समस्या: वस्तुओं के बीच जिम्मेदारियों के वितरण का सामान्य सिद्धांत क्या है? निर्णय: इस दायित्व को पूरा करने के लिए आवश्यक जानकारी रखने वाले व्यक्ति को एक कर्तव्य सौंपें।
  2. प्रजापति (निर्माता)। समस्या: एक नई वस्तु बनाने के लिए कौन जिम्मेदार होना चाहिए? समाधान: कक्षा बी को कक्षा ए के उदाहरण बनाने होंगे यदि निम्न में से एक या अधिक स्थिति सत्य है:
    - क्लास बी ए या के उदाहरण हैं
    - बी लिखता है ए
    - B सक्रिय रूप से A का उपयोग करता है
    - B में आरंभीकरण डेटा A है
  3. कम युग्मन समस्या: परिवर्तन के प्रभाव को कैसे कम करें? पुन: उपयोग की संभावना कैसे बढ़ाएं? समाधान: जिम्मेदारियों को वितरित करें ताकि कनेक्टिविटी कम हो। युग्मन इस बात का मापक है कि तत्व कितने कठोर रूप से जुड़े हुए हैं, वे एक दूसरे पर कितना निर्भर हैं। यानी वस्तुओं को जोड़ने की सिफारिश की जाती है ताकि वे एक दूसरे के बारे में केवल आवश्यक न्यूनतम के बारे में जान सकें।
  4. उच्च गियरिंग ( उच्च सामंजस्य )। समस्या: मैं जटिलता का प्रबंधन कैसे करूँ? समाधान: जिम्मेदारियों को वितरित करें ताकि उच्च जुड़ाव बना रहे। उच्च जुड़ाव का मतलब है कि एक तत्व की जिम्मेदारियां एक क्षेत्र पर केंद्रित हैं।
  5. एक नियंत्रक (नियंत्रक)। समस्या: इनपुट घटनाओं को संभालने के लिए कौन जिम्मेदार होना चाहिए? समाधान: जिम्मेदार होने के लिए एक वर्ग असाइन करें, जो या तो पूरे (बाहरी नियंत्रक) के रूप में पूरे सिस्टम या सबसिस्टम का प्रतिनिधित्व करता है, या एक विशिष्ट स्क्रिप्ट (स्क्रिप्ट या सत्र नियंत्रक)। उसी समय, नियंत्रक घटनाओं की प्रतिक्रिया को लागू नहीं करता है; यह इसे संबंधित निष्पादकों को सौंपता है।
  6. बहुरूपता ( बहुरूपता )। समस्या: प्रकार के आधार पर विभिन्न व्यवहारों को कैसे संभालना है? : , , , .
  7. ( Pure Fabrication ). : , ? : , .
  8. ( Indirection ). : , Low Coupling ? : .
  9. परिवर्तनों का विरोध ( संरक्षित विविधताएँ )। समस्या: वस्तुओं और उप-प्रणालियों को कैसे डिज़ाइन करें ताकि उनमें परिवर्तन अन्य तत्वों पर अवांछनीय प्रभाव न डालें? समाधान: संभव अस्थिरता बिंदुओं को ढूंढें और उनके चारों ओर एक स्थिर इंटरफ़ेस बनाएं, केवल ऐसे इंटरफ़ेस के माध्यम से संवाद करें।

GRASP पैटर्न लगातार गैंग फोर पैटर्न और SOLID सिद्धांतों के साथ प्रतिच्छेद करते हैं यह सामान्य है, क्योंकि वे सभी सामान्य समस्या को हल करते हैं - उच्च गुणवत्ता वाले सॉफ़्टवेयर के निर्माण को सरल बनाने के लिए।

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (रूसी)

ठोस


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

  1. एकल जिम्मेदारी के सिद्धांत ( एकल जिम्मेदारी सिद्धांत, SRP )। एक वर्ग या मॉड्यूल की केवल एक जिम्मेदारी होनी चाहिए। "केवल एक ही काम करो, लेकिन इसे अच्छी तरह से करो।"
  2. / ( Open Closed Principle, OCP ). (, , ) , . : , .
  3. ( Liskov Substitution Principle, LSP ). , . यानी - .
  4. ( Interface Segregation Principle, ISP ). , . , . , , . , .
  5. निर्भरता उलट सिद्धांत ( निर्भरता के उलट सिद्धांत, DIP )। ऊपरी स्तर के मॉड्यूल को निचले स्तर के मॉड्यूल पर निर्भर नहीं होना चाहिए। सभी मॉड्यूल अमूर्तता पर निर्भर होना चाहिए। विवरण विवरण पर निर्भर नहीं होना चाहिए। विवरण अमूर्तता पर निर्भर होना चाहिए। उदाहरण के लिए, न तो इंटरफेस और न ही ठोस वर्गों में अन्य ठोस वर्गों को उनके तरीकों के तर्क के रूप में शामिल या स्वीकार करना चाहिए, लेकिन केवल इंटरफेस (जावा और सी # के अर्थ में)।

और अधिक पढ़ें: एक (रूसी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

अन्य


ABI


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

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

पुस्तकालयों और निष्पादन योग्य फ़ाइलों के स्तर पर, एबीआई एक वर्ग के भीतर क्षेत्रों के स्थान, वंश के अंदर आधार कक्षाएं, आभासी कार्यों को लागू करने के लिए तंत्र, कॉल स्टैक फ्रेम के प्रारूप, निर्धारित फ़ंक्शन के लिए तर्क पारित करने के लिए नियम आदि का निर्धारण कर सकता है।

सी ++ में एक भी नहीं है। मानक एबीआई , जो आश्चर्य की बात नहीं है, क्योंकि यह वास्तुकला और ओएस पर निर्भर करता है। उदाहरण के लिए, X86_64 पर कई यूनिक्स जैसे ऑपरेटिंग सिस्टम (लिनक्स, FreeBSD, MacOS) के लिए C ++ कंपाइलर ARM V - ARM C ++ ABI पर सिस्टम V AMD64 ABI को फॉलो करते हैं । विजुअल C ++ ABI आधिकारिक तौर पर प्रकाशित नहीं है, लेकिन कम से कम आंशिक रूप से फिर से इंजीनियर है। यह सिस्टम वी एबीआई से बहुत अलग है, उनके पास नाम (मैनबलिंग) छिपाने के लिए पूरी तरह से अलग नियम हैं औरकहा जाता है फ़ंक्शन के लिए तर्क (लिनक्स 6 रजिस्टरों का उपयोग करता है, विंडोज 4 रजिस्टरों का उपयोग करता है), और अन्य अंतरों का एक गुच्छा।

यहां तक ​​कि अगर एपीआई और एबीआई एक ही रहते हैं, और केवल कार्यान्वयन विवरण बदलते हैं, तो बाइनरी संगतता टूट सकती है उदाहरण के लिए, C ++ 11 में, वर्णों को क्रमिक रूप से संग्रहीत करने के लिए तार की आवश्यकता थी (जैसा कि एक वेक्टर में है)। इस वजह से, जीसीसी 5 को स्ट्रिंग्स के कार्यान्वयन को बदलना पड़ा ( गाय का उपयोग पहले वहां किया गया था ), जिसके कारण द्विआधारी असंगति हुई।

और पढ़ें: एक बार (रूसी) , दो (अंग्रेजी) और दो पिछले पैराग्राफ के सभी लिंक।

गाय


लिखने पर कॉपी करें। रिकॉर्डिंग पर कॉपी करें। यह एक संसाधन प्रबंधन तंत्र है, जिसे अंतर्निहित साझाकरण और आलसी प्रतिलिपि के रूप में भी जाना जाता है। विचार यह है कि जब एक प्रतिलिपि की आवश्यकता होती है, तो संसाधन वास्तव में कॉपी नहीं किया जाता है, लेकिन इसके लिए एक लिंक बनाया जाता है। और केवल तभी जब परिवर्तन के लिए अनुरोध किया जाता है - मूल या "कॉपी" में - तभी एक पूर्ण प्रतिलिपि का निर्माण होता है। गाय का

लाभ स्पष्ट है: किसी भी वस्तु की नकल करना तुरन्त होता है। यदि वस्तुओं को अक्सर कॉपी किया जाता है लेकिन शायद ही कभी बदला जाता है, तो प्रदर्शन लाभ महत्वपूर्ण हो सकता है। गाय का उपयोग करने के उदाहरण :



  • लिनक्स में वर्चुअल प्रोसेस मेमोरी मैनेजमेंट। जब fork()पृष्ठों को कॉल किया जाता है, तो प्रक्रिया मेमोरी कॉपी नहीं की जाती है, लेकिन केवल साझा के रूप में चिह्नित की जाती है।
  • कुछ फ़ाइल सिस्टम (Btrfs, ZFS) और डेटाबेस (MS SQL सर्वर) में स्नैपशॉट।
  • सी ++ 11 करने के लिए, कुछ कार्यान्वयन std::stringका उपयोग गायC ++ 11 में, std::stringपरिवर्तन की आवश्यकताएं ( ABI देखें )।
  • क्यूटी उपयोग में कई प्रकार गाय

और पढ़ें: एक समय (अंग्रेजी) , दो (अंग्रेजी)

एफबीसी, एफबीसीपी


फ्रैजाइल बेस क्लास (समस्या)। एक नाजुक आधार वर्ग की समस्या। यह एक मौलिक ओओपी समस्या है, इसका सार यह है कि आधार वर्ग के सही परिवर्तन से वारिस में से एक में त्रुटि हो सकती है।

उदाहरण के लिए, अनंत पुनरावृत्ति के लिए
 struct Base { virtual void method1() { // ... } virtual void method2() { // ... method1(); // <--      } }; struct Derived : Base { void method1() override { method2(); } }; 

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

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

और अधिक पढ़ें: एक (अंग्रेजी) , दो (अंग्रेजी) , तीन (अंग्रेजी)

LRU


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

LRUउनके कैश तत्व को बदल देता है, जिसे किसी ने सबसे लंबे समय तक एक्सेस नहीं किया है। यह शायद सबसे प्रसिद्ध कैशिंग एल्गोरिथ्म है। संभवतः दक्षता और सादगी के संयोजन के कारण। एलआरयू की मेमोरी खपत ओ (एन) है, मूल्य तक औसत पहुंच समय ओ (1) है, एक तत्व जोड़ने का औसत समय भी ओ (1) है। कार्यान्वयन के लिए, एक हैश तालिका और एक डबल लिंक की गई सूची का आमतौर पर उपयोग किया जाता है।

उदाहरण के लिए, इसलिए
 template <class K, class V> class LRU { private: using Queue = std::list<std::pair<K, V>>; using Iterator = typename Queue::iterator; using Hash = std::unordered_map<K, Iterator>; Queue queue_; Hash hash_; const size_t limit_; public: LRU(size_t limit) : limit_(limit) { } std::optional<V> get(const K& key) { const auto it = hash_.find(key); if (it == hash_.end()) { return {}; } it->second = reorder(it->second); return { it->second->second }; } void add(K&& key, V&& value) { if (hash_.size() >= limit_) { pop(); } queue_.emplace_front(std::move(key), std::move(value)); const auto it = queue_.begin(); hash_[it->first] = it; } private: Iterator reorder(Iterator it) { queue_.emplace_front(std::move(it->first), std::move(it->second)); queue_.erase(it); return queue_.begin(); } void pop() { hash_.erase(queue_.back().first); queue_.pop_back(); } }; 

LRU का स्पष्ट दोष उच्च मेमोरी खपत है, क्योंकि यह प्रत्येक n तत्वों की दो संरचनाओं का उपयोग करता है। LRU के अलावा , कई अन्य मामलों के लिए कई अन्य कैशिंग एल्गोरिदम हैं: MRU (सबसे हाल ही में प्रयुक्त), LFU (कम से कम अक्सर इस्तेमाल किया गया), खंडित LRU, 2Q, आदि।

फिर से पढ़ें: एक समय (अंग्रेजी) , दो (रूसी) , तीन (eng।)

पुनश्च


अगर मुझे कुछ याद आया या कहीं गलत था - टिप्पणियों में लिखें।

Source: https://habr.com/ru/post/hi470317/


All Articles