क्या राज्य पैटर्न लिस्कोव प्रतिस्थापन सिद्धांत का उल्लंघन करता है?


17

यह छवि लागू डोमेन-संचालित डिज़ाइन और पैटर्न से ली गई है : C # और .NET में उदाहरणों के साथ

यहाँ छवि विवरण दर्ज करें

यह स्टेट पैटर्न के लिए वर्ग आरेख है जहां SalesOrderइसके जीवन काल के दौरान विभिन्न राज्य हो सकते हैं। विभिन्न राज्यों के बीच केवल कुछ बदलाव की अनुमति है।

अब OrderStateवर्ग एक abstractवर्ग है और इसकी सभी विधियाँ इसके उपवर्गों को विरासत में मिली हैं। यदि हम उपवर्ग पर विचार करते हैं, Cancelledजो एक अंतिम स्थिति है जो किसी भी अन्य राज्यों में किसी भी संक्रमण की अनुमति नहीं देता है, तो हमें overrideअपवादों को फेंकने के लिए इस वर्ग में इसके सभी तरीके होंगे।

अब यह कि लिस्कोव के प्रतिस्थापन सिद्धांत का उल्लंघन नहीं करता क्योंकि एक उपवर्ग माता-पिता के व्यवहार में परिवर्तन नहीं करना चाहिए? क्या अमूर्त वर्ग को एक अंतरफलक में बदलना इसे ठीक करता है?
इसे कैसे सुधारा जा सकता है?


चेंज ऑर्डरस्टैट को एक ऐसा ठोस वर्ग होना चाहिए जो डिफ़ॉल्ट रूप से अपने सभी तरीकों में "NotSupported" अपवादों को फेंकता है?
जेम्स

मैंने इस पुस्तक को नहीं पढ़ा है, लेकिन यह मुझे अजीब लगता है कि ऑर्डरस्टैट में रद्द () शामिल है और फिर रद्द की गई स्थिति है, जो कि अलग-अलग उप-प्रकार है।
युफोरिक

@ अजीब क्यों अजीब है? कॉलिंग cancel()राज्य को रद्द करने के लिए बदलता है।
सोंगो

कैसे? जब आप SalesOrder में राज्य का उदाहरण बदलने वाले हों, तो आप OrderState पर रद्द कैसे कर सकते हैं। मुझे लगता है कि पूरा मॉडल गलत है। मैं पूर्ण कार्यान्वयन देखना चाहूंगा।
युफोरिक E ’

जवाबों:


3

यह विशेष रूप से कार्यान्वयन, हाँ। यदि आप अमूर्त कार्यान्वयनकर्ताओं के बजाय राज्यों को ठोस वर्ग बनाते हैं तो आप इससे दूर हो जाएंगे।

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

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

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

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

लेकिन उस बिंदु पर यह इंजीनियरिंग की तुलना में अधिक कला है और इसलिए यह निश्चित रूप से उन चीजों में से कुछ करने के लिए अपने दृष्टिकोण, कि कहा व्यक्तिपरक है सिद्धांतों एक अच्छा मार्गदर्शक हैं और हाँ कार्यान्वयन आप सूची है एक LSP उल्लंघन है, बल्कि होने के लिए नहीं सुधारा जा सकता है। इस प्रकृति के किसी भी पैटर्न का उपयोग करते समय बस एसआरपी के बारे में बहुत सावधान रहें और आपके सुरक्षित होने की संभावना है।


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

3
@ जिम्मी हॉफ़ा सॉरी, लेकिन आप का क्या मतलब है "अगर आप अमूर्त कार्यान्वयनकर्ताओं के बजाय राज्यों को ठोस वर्ग बनाते हैं तो आप इससे दूर हो जाएंगे।" ?
सांगो

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

8

एक उपवर्ग माता-पिता के व्यवहार में परिवर्तन नहीं करना चाहिए?

यह एलएसपी की एक आम गलत व्याख्या है। एक उपवर्ग माता-पिता के व्यवहार को बदल सकता है, जब तक कि यह मूल प्रकार के लिए सही रहता है।

विकिपीडिया पर एक अच्छी लम्बी व्याख्या है , उन चीजों के बारे में सुझाव दे रही है जो एलएसपी का उल्लंघन करेंगी:

... वहाँ व्यवहार स्थितियों की एक संख्या है कि उपप्रकार मिलना चाहिए। ये अनुबंध कार्यप्रणाली द्वारा डिज़ाइन की गई शब्दावली में विस्तृत हैं, कुछ प्रतिबंधों के लिए अग्रणी हैं जो अनुबंध विरासत के साथ कैसे बातचीत कर सकते हैं:

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

व्यक्तिगत रूप से, मुझे यह याद रखना आसान लगता है: यदि मैं एक ऐसी विधि में एक पैरामीटर देख रहा हूं जिसमें A टाइप है, तो क्या कोई उपप्रकार बी पास करने से मुझे कोई आश्चर्य होगा? यदि वे तब एलएसपी का उल्लंघन होता है।

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

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

लेकिन तब मैं इस विशेष स्थिति के लिए राज्य के पैटर्न का उपयोग नहीं करता। राज्य का पैटर्न इस तरह के डोमेन ऑब्जेक्ट की स्थिति की तुलना में किसी एप्लिकेशन की स्थिति के लिए बहुत अधिक उपयुक्त है।

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


यह मुझे ऐसा लगता है जैसे आप एलएसपी को कम से कम आश्चर्य / विस्मय के सिद्धांत के साथ भ्रमित कर रहे हैं, मेरा मानना ​​है कि एलएसपी की अधिक स्पष्ट-कट सीमाएं हैं जहां यह उनका उल्लंघन कर रहा है, हालांकि आप अधिक व्यक्तिपरक पोला आवेदन कर रहे हैं जो अपेक्षाओं पर आधारित है जो व्यक्तिपरक है ; प्रत्येक व्यक्ति को अगले से कुछ अलग की उम्मीद है। एलएसपी प्रदाता द्वारा दिए गए संविदात्मक और अच्छी तरह से परिभाषित गारंटी पर आधारित है, उपभोक्ता द्वारा अनुमान लगाए गए अपेक्षाओं के अधीन नहीं है।
जिमी हॉफ

@JimmyHoffa: आप सही कह रहे हैं, और इसीलिए मैंने एलएसपी को याद रखने का एक सरल तरीका बताए जाने से पहले सटीक अर्थ निकाला है। हालांकि, अगर मेरे मन में एक सवाल है कि "आश्चर्य" का क्या मतलब है, तो मैं वापस जाऊंगा और एलएसपी के सटीक नियमों की जांच करूंगा (क्या आप वास्तव में उन्हें याद कर सकते हैं?)। कार्यक्षमता को प्रतिस्थापित करने वाले अपवाद (या इसके विपरीत) एक कठिन है क्योंकि यह ऊपर दिए गए किसी भी विशिष्ट खंड को भंग नहीं करता है, जो संभवतः एक सुराग है कि इसे पूरी तरह से अलग तरीके से संभाला जाना चाहिए।
प्रात: r:

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

1
@ जिमीहॉफ: मैंने कभी भी पोला और एलएसपी को दूर से जुड़ा हुआ नहीं माना (मैं यूआई के संदर्भ में पीओएल के बारे में सोचता हूं) लेकिन, अब जब आपने इसे इंगित किया है, तो वे इस तरह के हैं। मुझे यकीन नहीं है कि वे संघर्ष में हैं, या कि एक दूसरे की तुलना में अधिक व्यक्तिपरक है। क्या सॉफ्टवेयर इंजीनियरिंग की शर्तों में एलएसपी का प्रारंभिक विवरण नहीं है? उसी तरह जब मैं Ctrl-C कॉपी (POLA) नहीं होने पर निराश हो जाता हूं, तो मैं भी निराश हो जाता हूं जब एक ImmutablePoint म्यूटेबल होता है क्योंकि यह वास्तव में एक MutablePoint उपवर्ग (LSP) है।
पीडीआर p

1
मैं CircleWithFixedCenterButMutableRadiusएक संभावित एलएसपी उल्लंघन के रूप में विचार करूंगा यदि उपभोक्ता अनुबंध ImmutablePointनिर्दिष्ट करता है कि अगर X.equals(Y), उपभोक्ता वाई के लिए एक्स को स्वतंत्र रूप से स्थानापन्न कर सकते हैं, और इसके विपरीत, और इस तरह से कक्षा का उपयोग करने से बचना चाहिए ताकि इस तरह के प्रतिस्थापन से परेशानी हो। प्रकार को कानूनी रूप से परिभाषित करने में सक्षम हो सकता है equalsकि सभी उदाहरण अलग-अलग होंगे, लेकिन इस तरह के व्यवहार की संभावना इसकी उपयोगिता को सीमित करेगी।
सुपरकैट

2

(यह C # के दृष्टिकोण से लिखा गया है, इसलिए कोई जाँच अपवाद नहीं है।)

LSP के बारे में विकिपीडिया लेख के अनुसार , LSP की शर्तों में से एक है:

कोई नया अपवाद उपप्रकार के तरीकों से नहीं फेंका जाना चाहिए, सिवाय उन अपवादों के जहां वे स्वयं सुपरटेप के तरीकों द्वारा फेंके गए अपवादों के उपप्रकार हैं।

आपको यह कैसे समझना चाहिए? जब सुपरपोर्ट के तरीके अमूर्त होते हैं, तो वास्तव में "अपवाद सुपरटेकाइप के तरीकों द्वारा फेंके गए" क्या हैं? मुझे लगता है कि वे अपवाद हैं जिन्हें अपवाद के रूप में प्रलेखित किया गया है जो सुपरपाइप के तरीकों से फेंके जा सकते हैं।

इसका मतलब यह है कि अगर इस OrderState.Ship()तरह की चीज़ों को "फेंकता है InvalidOperationExceptionअगर इस ऑपरेशन को वर्तमान स्थिति द्वारा समर्थित नहीं किया जाता है", तो मुझे लगता है कि यह डिज़ाइन एलएसपी को नहीं तोड़ता है। दूसरी ओर, अगर सुपरपाइप विधियों को इस तरह से प्रलेखित नहीं किया जाता है, तो एलएसपी का उल्लंघन किया जाता है।

लेकिन इसका मतलब यह नहीं है कि यह अच्छा डिज़ाइन है, आपको सामान्य नियंत्रण प्रवाह के अपवादों का उपयोग नहीं करना चाहिए, जो यह बहुत करीब लगता है। इसके अलावा, एक वास्तविक एप्लिकेशन में, आप शायद यह जानना चाहेंगे कि क्या ऐसा करने से पहले आप ऑपरेशन कर सकते हैं , उदाहरण के लिए, UI में "शिप" बटन को निष्क्रिय करने के लिए।


वास्तव में यही वह बिंदु है जिसने मुझे सोच में भेजा है। यदि उप-वर्ग अपवाद को माता-पिता में परिभाषित नहीं करते हैं तो यह एलएसपी का उल्लंघन होना चाहिए।
सांगो

मुझे लगता है कि जिस भाषा में अपवादों की जाँच नहीं होती है, उन्हें फेंकना एलएसपी का उल्लंघन नहीं है। यह सिर्फ एक भाषा की ही अवधारणा है, कि कहीं भी किसी भी अपवाद को फेंक दिया जा सकता है। तो उसके लिए कोई भी क्लाइंट कोड तैयार होना चाहिए।
जैपाडलो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.