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


132

मान लें कि हमारे पास टास्क संस्थाओं की एक सूची है, और एक ProjectTaskउप प्रकार है। टास्क को कभी भी बंद किया जा सकता है, सिवाय इसके ProjectTasksकि स्टार्ट होने की स्थिति के बाद वे बंद नहीं हो सकते। यूआई को यह सुनिश्चित करना चाहिए कि प्रारंभ को बंद करने का विकल्प ProjectTaskउपलब्ध नहीं है, लेकिन कुछ सुरक्षा उपाय डोमेन में मौजूद हैं:

public class Task
{
     public Status Status { get; set; }

     public virtual void Close()
     {
         Status = Status.Closed;
     }
}

public class ProjectTask : Task
{
     public override void Close()
     {
          if (Status == Status.Started) 
              throw new Exception("Cannot close a started Project Task");

          base.Close();
     }
}

अब जब Close()टास्क पर कॉल किया जा रहा है , तो एक मौका है कि कॉल विफल हो जाएगी अगर यह ProjectTaskशुरू की गई स्थिति के साथ है, जब यह बेस टास्क नहीं होता। लेकिन यह व्यावसायिक आवश्यकताएं हैं। इसे विफल होना चाहिए। क्या इसे लिस्कोव प्रतिस्थापन सिद्धांत का उल्लंघन माना जा सकता है ?


14
Liskov प्रतिस्थापन के उल्लंघन के एक टी उदाहरण के लिए बिल्कुल सही। यहां विरासत का उपयोग न करें, और आप ठीक हो जाएंगे।
जिमी होफा

8
आप इसे बदलना चाह सकते हैं public Status Status { get; private set; }:; अन्यथा Close()विधि के आसपास काम किया जा सकता है।
अय्यूब

5
शायद यह सिर्फ उदाहरण है, लेकिन मुझे एलएसपी के अनुपालन के लिए कोई भौतिक लाभ नहीं है। मेरे लिए, प्रश्न में यह समाधान स्पष्ट है, समझने में आसान है, और एलएसपी के साथ एक से अधिक अनुपालन बनाए रखना आसान है।
बेन ली

2
@BenLee इसे बनाए रखना आसान नहीं है। यह केवल इस तरह दिखता है क्योंकि आप इसे अलगाव में देख रहे हैं। जब सिस्टम बड़ा होता है, तो यह सुनिश्चित Taskकरना कि उपप्रकार पॉलीमॉर्फिक कोड में विचित्र असंगति का परिचय नहीं देते हैं जो केवल जानता है कि Taskयह एक बड़ी बात है। एलएसपी एक सनकी नहीं है, लेकिन बड़ी प्रणालियों में स्थिरता बनाए रखने में मदद करने के लिए ठीक से पेश किया गया था।
एंड्रेस एफ।

8
@BenLee कल्पना कीजिए कि आपके पास एक TaskCloserप्रक्रिया है closesAllTasks(tasks)। यह प्रक्रिया स्पष्ट रूप से अपवादों को पकड़ने का प्रयास नहीं करती है; आखिरकार, यह स्पष्ट अनुबंध का हिस्सा नहीं है Task.Close()। अब आप परिचय देते हैं ProjectTaskऔर अचानक आपका TaskCloser(संभवतः अखंडित) अपवादों को फेंकना शुरू कर देता है। यह बड़ा सौदा है!
एंड्रेस एफ।

जवाबों:


173

हां, यह एलएसपी का उल्लंघन है। Liskov प्रतिस्थापन सिद्धांत की आवश्यकता है कि

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

आपका उदाहरण Close()विधि को कॉल करने के लिए एक पूर्व शर्त को मजबूत करके पहली आवश्यकता को तोड़ता है ।

आप वंशानुगत पदानुक्रम के शीर्ष स्तर पर मजबूत पूर्व-स्थिति लाकर इसे ठीक कर सकते हैं:

public class Task {
    public Status Status { get; set; }
    public virtual bool CanClose() {
        return true;
    }
    public virtual void Close() {
        Status = Status.Closed;
    }
}

यह कहते Close()हुए कि राज्य की एक कॉल केवल राज्य में मान्य है जब आप CanClose()रिटर्न trueपूर्व शर्त लागू करते हैं और Taskसाथ ही ProjectTaskएलएसपी उल्लंघन को ठीक करते हैं:

public class ProjectTask : Task {
    public override bool CanClose() {
        return Status != Status.Started;
    }
    public override void Close() {
        if (Status == Status.Started) 
            throw new Exception("Cannot close a started Project Task");
        base.Close();
    }
}

17
मुझे उस चेक का दोहराव पसंद नहीं है। मैं Task.Close में जा रहे अपवाद को फेंकना पसंद करूंगा और वर्चुअल को Close से हटा दूंगा।
व्यंग्यात्मक

4
@ कामुक जो सच है, शीर्ष-स्तर Closeकी जाँच कर रहा है, और संरक्षित जोड़ना DoCloseएक वैध विकल्प होगा। हालांकि, मैं ओपी के उदाहरण के जितना संभव हो उतना करीब रहना चाहता था; इस पर सुधार एक अलग प्रश्न है।
dasblinkenlight 20

5
@ यूफोरिक: लेकिन अब इस सवाल का जवाब देने का कोई तरीका नहीं है, "क्या यह काम बंद हो सकता है?" इसे बंद करने की कोशिश किए बिना। यह अनावश्यक रूप से प्रवाह नियंत्रण के लिए अपवादों के उपयोग को मजबूर करता है। हालांकि, मैं स्वीकार करूंगा कि इस तरह की चीज को बहुत दूर ले जाया जा सकता है। बहुत दूर ले जाया गया, इस तरह के समाधान से एन्ट्रापी मेस की उपज हो सकती है। भले ही, ओपी का प्रश्न मुझे सिद्धांतों के बारे में अधिक बताता है, इसलिए एक हाथीदांत टॉवर का उत्तर बहुत उपयुक्त है। +1
ब्रायन

30
@ ब्रायन द कैनकॉस अभी भी है। यह अभी भी जांच के लिए बुलाया जा सकता है कि क्या टास्क को बंद किया जा सकता है। क्लोज इन चेक को भी इसे कॉल करना चाहिए।
यूफोरिक

5
@ यूफोरिक: आह, मुझे गलत समझा गया। तुम सही हो, कि एक बहुत क्लीनर समाधान के लिए बनाता है।
ब्रायन

82

हाँ। यह एलएसपी का उल्लंघन करता है।

मेरा सुझाव CanCloseआधार कार्य में विधि / संपत्ति को जोड़ना है , इसलिए कोई भी कार्य बता सकता है कि क्या इस राज्य में कार्य बंद हो सकता है। यह कारण भी प्रदान कर सकता है। और वर्चुअल को हटा दें Close

मेरी टिप्पणी के आधार पर:

public class Task {
    public Status Status { get; private set; }

    public virtual bool CanClose(out String reason) {
        reason = null;
        return true;
    }
    public void Close() {
        String reason;
        if (!CanClose(out reason))
            throw new Exception(reason);

        Status = Status.Closed;
    }
}

public ProjectTask : Task {
    public override bool CanClose(out String reason) {
        if (Status != Status.Started)
        {
            reason = "Cannot close a started Project Task";
            return false;
        }
        return base.CanClose(out reason);
    }
}

3
इसके लिए धन्यवाद, आपने dasblinkenlight का उदाहरण एक चरण में लिया, लेकिन मुझे उनका स्पष्टीकरण nd औचित्य पसंद आया। क्षमा करें, मैं 2 उत्तर स्वीकार नहीं कर सकता!
पॉल टी डेविस

मुझे यह जानने में दिलचस्पी है कि हस्ताक्षर सार्वजनिक रूप से वर्चुअल बूल कैन्कोज (स्ट्रिंग के कारण) के रूप में है - क्या आप केवल भविष्य में प्रूफिंग का उपयोग कर रहे हैं? या फिर कुछ और सूक्ष्म है जो मुझे याद आ रहा है?
रीचर गिल्ट

3
@ReacherGilt मुझे लगता है कि आपको यह देखना चाहिए कि मैं क्या करता / करती हूं और मेरे कोड को फिर से पढ़ती हूं आप भ्रमित हैं। बस "यदि कार्य बंद नहीं हो सकता है, तो मैं जानना चाहता हूं कि क्यों।"
व्यंग्यात्मक

2
सभी भाषा में उपलब्ध नहीं है, एक टपल लौटना (या कारण और बूलियन को घेरने वाली एक साधारण वस्तु है) यह सीधे OO भाषाओं में बेहतर पोर्टेबल बना देगा, हालांकि सीधे एक बूल होने की आसानी को खोने की कीमत पर। समर्थन करें, इस उत्तर के साथ कुछ भी गलत नहीं है।
न्यूटॉपियन

1
और यह CanClose संपत्ति के लिए पूर्व शर्त को मजबूत करने के लिए ठीक है? यानी शर्त जोड़ना?
जॉन वी

24

लिस्कोव प्रतिस्थापन सिद्धांत में कहा गया है कि एक बेस क्लास को प्रोग्राम के किसी भी वांछनीय गुणों को बदलने के बिना अपने किसी भी उप-वर्ग के साथ बदली जानी चाहिए। चूंकि ProjectTaskबंद होने पर केवल एक अपवाद होता है, उसके लिए एक कार्यक्रम को एक aododate में बदलना होगा, ProjectTaskजिसका उपयोग प्रतिस्थापन में किया जाना चाहिए Taskइसलिए यह उल्लंघन है।

लेकिन यदि आप Taskइसके हस्ताक्षर में यह कहते हुए संशोधित करते हैं कि यह बंद होने पर अपवाद को बढ़ा सकता है , तो आप सिद्धांत का उल्लंघन नहीं करेंगे।


मैं c # का उपयोग करता हूं जो मुझे नहीं लगता कि यह संभावना है, लेकिन मुझे पता है कि जावा करता है।
पॉल टी डेविस

2
@PaulTDavies आप एक विधि को सजा सकते हैं कि यह किस अपवाद के साथ फेंकता है, msdn.microsoft.com/en-us/library/5ast78ax.aspx । आपको यह ध्यान में आता है जब आप बेस क्लास लाइब्रेरी से एक विधि पर होवर करते हैं तो आपको अपवादों की एक सूची मिलेगी। इसे लागू नहीं किया गया है, लेकिन यह कॉल करने वाले को फिर भी जागरूक बनाता है।
डेस्परर्ट

18

एक एलएसपी उल्लंघन के लिए तीन पक्षों की आवश्यकता होती है। टाइप T, सबटाइप S और प्रोग्राम P जो T का उपयोग करता है लेकिन S का उदाहरण दिया गया है।

आपके प्रश्न ने T (टास्क) और S (प्रोजेक्टटेस्क) प्रदान किया है, लेकिन P नहीं। इसलिए आपका प्रश्न अधूरा है और उत्तर योग्य है: यदि कोई ऐसा P मौजूद है जो अपवाद की अपेक्षा नहीं करता है, तो उस P के लिए, आपके पास एक LSP है उल्लंघन। यदि हर P एक अपवाद की उम्मीद करता है तो कोई LSP उल्लंघन नहीं है।

हालांकि, अगर आप ऐसा एक है SRP उल्लंघन। तथ्य यह है कि किसी कार्य के राज्य बदला जा सकता है, और नीति है कि कुछ राज्यों में कुछ कार्य करना चाहिए अन्य राज्यों में नहीं बदला जा, दो बहुत अलग जिम्मेदारियों कर रहे हैं।

  • जिम्मेदारी 1: किसी कार्य का प्रतिनिधित्व करना।
  • जिम्मेदारी 2: कार्यों की स्थिति को बदलने वाली नीतियों को लागू करना।

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


2
जिम्मेदारियां डोमेन पर निर्भर करती हैं और (इस उदाहरण में) कि जटिल कार्य कैसे होते हैं और इसके परिवर्तक क्या हैं। इस मामले में, ऐसी बात का कोई संकेत नहीं है, इसलिए एसआरपी के साथ कोई समस्या नहीं है। एलएसपी उल्लंघन के लिए, मेरा मानना ​​है कि हम सभी ने माना कि कॉलर अपवाद की उम्मीद नहीं करता है और आवेदन को गलत स्थिति में आने के बजाय उचित संदेश दिखाना चाहिए।
व्यंग्यात्मक

Unca 'बॉब ने जवाब दिया? "हम योग्य नहीं हैं! हम योग्य नहीं हैं!"। वैसे भी ... यदि हर पी को अपवाद की उम्मीद है तो एलएसपी उल्लंघन नहीं है। लेकिन, अगर हम एक T उदाहरण देते हैं, तो एक OpenTaskException(संकेत, संकेत) नहीं फेंक सकते हैं और हर P एक अपवाद की उम्मीद करता है, तो कोड के बारे में क्या कहता है इंटरफ़ेस के लिए, कार्यान्वयन नहीं? मैं किस बारे में बात कर रहा हूं? मुझे नहीं पता। मुझे सिर्फ इस बात पर हंसी आती है कि मैं अनका बॉब के जवाब पर टिप्पणी कर रहा हूं।
राडारोब

3
आप सही हैं कि एलएसपी उल्लंघन साबित करने के लिए तीन वस्तुओं की आवश्यकता होती है। हालांकि, एलएसपी उल्लंघन मौजूद है अगर कोई भी प्रोग्राम पी है जो एस की अनुपस्थिति में सही था, लेकिन एस के अतिरिक्त के साथ विफल रहता है
केविन क्लाइन

16

यह एलएसपी का उल्लंघन हो सकता है या नहीं भी हो सकता है।

गंभीरता से। मेरी बात सुनो।

यदि आप एलएसपी का पालन करते हैं, तो टाइप की वस्तुओं का ProjectTaskव्यवहार करना चाहिए क्योंकि टाइप की वस्तुओं Taskसे व्यवहार की उम्मीद की जाती है।

आपके कोड के साथ समस्या यह है कि आपने यह प्रलेखित नहीं किया है कि किस प्रकार की वस्तुओं के Taskव्यवहार की अपेक्षा की जाती है। आपने कोड लिखा है, लेकिन कोई अनुबंध नहीं। मैं एक अनुबंध जोड़ूंगा Task.Close। मेरे द्वारा जोड़े गए अनुबंध के आधार पर, ProjectTask.Closeया तो एलएसपी का पालन करता है या नहीं करता है।

Task.Close के लिए निम्नलिखित अनुबंध को देखते हुए, कोड एलएसपी का पालन ProjectTask.Close नहीं करता है :

     // Behaviour: Moves the task to the closed state
     // and does not throw any Exception.
     // Default behaviour: Moves the task to the closed state
     // and does not throw any Exception.
     public virtual void Close()
     {
         Status = Status.Closed;
     }

Task.Close के लिए निम्नलिखित अनुबंध को देखते हुए, कोड एलएसपी का पालन ProjectTask.Close करता है :

     // Behaviour: Moves the task to the closed status if possible.
     // If this is not possible, this method throws an Exception
     // and leaves the status unchanged.
     // Default behaviour: Moves the task to the closed state
     // and does not throw any Exception.
     public virtual void Close()
     {
         Status = Status.Closed;
     }

जिन तरीकों को ओवरराइड किया जा सकता है, उन्हें दो तरीकों से प्रलेखित किया जाना चाहिए:

  • "व्यवहार" दस्तावेज़ जो एक ग्राहक द्वारा पर भरोसा किया जा सकता है जो प्राप्तकर्ता वस्तु को जानता है एक है Task, लेकिन यह नहीं जानता कि यह किस वर्ग का प्रत्यक्ष उदाहरण है। यह उपवर्गों के डिजाइनरों को भी बताता है जो ओवरराइड उचित हैं और जो उचित नहीं हैं।

  • "डिफ़ॉल्ट व्यवहार" दस्तावेज़ एक ग्राहक द्वारा किस पर भरोसा किया जा सकता है, जो जानता है कि प्राप्तकर्ता वस्तु इसका प्रत्यक्ष उदाहरण है Task(यदि आप उपयोग करते हैं तो आपको क्या मिलता है new Task()। यह उपवर्गों के डिजाइनरों को भी बताता है कि यदि वे नहीं करते हैं तो उन्हें क्या व्यवहार विरासत में मिलेगा। विधि को ओवरराइड करें।

अब निम्नलिखित संबंध रखने चाहिए:

  • यदि S, T का उपप्रकार है, तो S के प्रलेखित व्यवहार को T के प्रलेखित व्यवहार को परिष्कृत करना चाहिए।
  • यदि S, T का उपप्रकार (या बराबर) है, तो S के कोड का व्यवहार T के प्रलेखित व्यवहार को परिष्कृत करना चाहिए।
  • यदि S, T का उपप्रकार (या बराबर) है, तो S का डिफ़ॉल्ट व्यवहार T के प्रलेखित व्यवहार को परिष्कृत करना चाहिए।
  • किसी वर्ग के लिए कोड का वास्तविक व्यवहार उसके प्रलेखित डिफ़ॉल्ट व्यवहार को परिष्कृत करना चाहिए।

@ user61852 ने यह मुद्दा उठाया कि आप विधि के हस्ताक्षर में यह बता सकते हैं कि यह एक अपवाद को बढ़ा सकता है, और बस ऐसा करने से (ऐसा कुछ जिसका वास्तविक प्रभाव कोड वार नहीं है) आप अब एलएसपी नहीं तोड़ रहे हैं।
पॉल टी डेविस

@PaulTDavies आप सही हैं। लेकिन अधिकांश भाषाओं में हस्ताक्षर यह घोषित करने का एक अच्छा तरीका नहीं है कि एक रूटीन अपवाद को फेंक सकता है। उदाहरण के लिए ओपी (C # में, मुझे लगता है) Closeथ्रो का दूसरा कार्यान्वयन है। इसलिए हस्ताक्षर की घोषणा है कि एक अपवाद को फेंक दिया जा सकता है - यह नहीं कहता कि कोई नहीं करेगा। जावा इस संबंध में बेहतर काम करता है। फिर भी, यदि आप घोषणा करते हैं कि कोई विधि अपवाद घोषित कर सकती है, तो आपको उन परिस्थितियों का दस्तावेजीकरण करना चाहिए जिनके तहत यह (या होगा)। इसलिए मेरा तर्क है कि एलएसपी का उल्लंघन किया जाता है या नहीं, इस बारे में सुनिश्चित होने के लिए, हमें हस्ताक्षर से परे प्रलेखन की आवश्यकता है।
थियोडोर नोरवेल

4
यहां बहुत सारे उत्तर इस तथ्य को पूरी तरह से नजरअंदाज करते हैं कि आप यह नहीं जान सकते हैं कि क्या अनुबंध को मान्य नहीं है यदि आप अनुबंध नहीं जानते हैं। उस उत्तर के लिए धन्यवाद।
gnasher729

अच्छा उत्तर, लेकिन अन्य उत्तर भी अच्छे हैं। वे अनुमान लगाते हैं कि बेस क्लास अपवाद नहीं फेंकता क्योंकि उस क्लास में ऐसा कुछ भी नहीं है जो उस के लक्षण दिखाता हो। तो आधार वर्ग का उपयोग करने वाले कार्यक्रम को अपवादों के लिए तैयार नहीं करना चाहिए।
inf3rno

आप सही हैं कि अपवाद सूची को कहीं दस्तावेज होना चाहिए। मुझे लगता है कि सबसे अच्छी जगह कोड में है। यहाँ एक संबंधित प्रश्न है: stackoverflow.com/questions/16700130/… लेकिन आप एनोटेशन के बिना ऐसा कर सकते हैं, आदि ... भी, बस if (false) throw new Exception("cannot start")आधार वर्ग की तरह कुछ लिखें । संकलक इसे हटा देगा, और अभी भी कोड में वह है जो आवश्यक है। Btw। हम अभी भी इन वर्कअराउंड्स के साथ एक एलएसपी उल्लंघन करते हैं, क्योंकि पूर्व शर्त अभी भी मजबूत है ...
inf3rno

6

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

Liskov प्रतिस्थापन सिद्धांत कहते हैं:

चलो क्ष (एक्स) एक संपत्ति के बारे में वस्तुओं साध्य हो एक्स प्रकार के टीS को T का उपप्रकार होने दें । प्रकार एस का उल्लंघन करती है Liskov प्रतिस्थापन सिद्धांत यदि एक वस्तु y प्रकार के एस मौजूद है, ऐसा है कि क्ष (y) साध्य नहीं है।

क्यों, उपप्रकार का आपका कार्यान्वयन लिस्कोव प्रतिस्थापन सिद्धांत का उल्लंघन नहीं है, काफी सरल है: Task::Close()वास्तव में जो कुछ भी करता है उसके बारे में कुछ भी साबित नहीं किया जा सकता है। यकीन है, ProjectTask::Close()जब एक अपवाद फेंकता है Status == Status.Started, लेकिन ऐसा हो सकता Status = Status.Closedहै Task::Close()


4

हां, यह उल्लंघन है।

मैं आपको सुझाव दूंगा कि आपका पदानुक्रम पीछे की ओर है। यदि हर कोई बंद करने योग्य नहीं Taskहै, तो close()इसमें शामिल नहीं है Task। शायद आप एक इंटरफ़ेस चाहते हैं, CloseableTaskजिसे सभी गैर- ProjectTasksकार्यान्वित कर सकें।


3
हर टास्क क्लोजेबल है, लेकिन हर परिस्थिति में नहीं।
पॉल टी डेविस

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

यदि Taskखुद को लागू नहीं करता है CloseableTaskतो वे असुरक्षित कॉल करने के लिए भी कॉल कर रहे हैं Close()
टॉम जी

@TomG यही है कि मैं किससे डरता हूं
जिमी

1
पहले से ही एक राज्य मशीन है। ऑब्जेक्ट बंद नहीं किया जा सकता क्योंकि यह गलत स्थिति में है।
कज़

3

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

ऐसा लगता है कि यह टास्कस्टेट के लिए राज्य पैटर्न को लागू करने के लिए एक अच्छी जगह है और राज्य की वस्तुओं को वैध बदलाव का प्रबंधन करने दें।


1

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


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

@ योयो हां, लेकिन जैसा कि अन्य ने कहा कि अपवाद उपप्रकार में उठाया गया है जिसने पूर्व शर्त को मजबूत किया और इस तरह (निहित) अनुबंध का उल्लंघन किया कि कॉलिंग बंद () बस कार्य बंद कर देता है।
एज़ेला वैक्का जूल

कौन सी पूर्वधारणा? मुझे कोई दिखाई नहीं देता।
गोयो जूल

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

कोई बात नहीं, मुझे सवाल में पहले से पता चला। लेकिन तब कुछ भी गलत नहीं है (डीबीसी-वार), जिसे कोड कहा जाता है, पूर्व-स्थितियों की जाँच करता है और जब वे नहीं मिलते हैं तो अपवादों को बढ़ाते हैं। इसे "रक्षात्मक प्रोग्रामिंग" कहा जाता है। इसके अलावा, यदि पूर्व स्थिति इस स्थिति के अनुसार नहीं मिलती है तो क्या होता है, यह बताते हुए कि इस स्थिति के बाद की स्थिति को सुनिश्चित करने के लिए कार्यान्वयन को पूर्व स्थिति को सत्यापित करना होगा।
गोयो जूल

0

हां, यह एलएसपी का स्पष्ट उल्लंघन है।

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

यदि आप इस मामले में एलएसपी उल्लंघन से बचना चाहते हैं तो आप डेकोरेटर पैटर्न की कोशिश कर सकते हैं। यह काम कर सकता है, मुझे नहीं पता।

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