এটি কি লিসকভ সাবস্টিটিউশন নীতি লঙ্ঘন?


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
লিসকোভ প্রতিস্থাপন লঙ্ঘনের টি-এর উদাহরণে পারফেক্ট। উত্তরাধিকার এখানে ব্যবহার করবেন না, এবং আপনি ভাল থাকবেন।
জিমি হোফা

8
আপনি এটিতে এটি পরিবর্তন করতে চাইতে পারেন public Status Status { get; private set; }:; অন্যথায় Close()পদ্ধতি প্রায় কাজ করা যেতে পারে।
কাজ

5
হতে পারে এটি কেবল এই উদাহরণ, তবে আমি এলএসপিকে মেনে চলার কোনও উপাদান উপকার দেখতে পাচ্ছি না। আমার কাছে, প্রশ্নের এই সমাধানটি পরিষ্কার, বোঝা সহজ, এবং এলএসপিতে মেনে চলার চেয়ে সহজ বজায় রাখা সহজ।
বেন লি

2
@ বেনলি এটি বজায় রাখা সহজ নয়। এটি কেবল সেভাবে দেখায় কারণ আপনি এটিকে বিচ্ছিন্নভাবে দেখছেন। যখন সিস্টেমটি বড় হয় তখন নিশ্চিত হয়ে নিন যে উপ-প্রকারগুলি Taskবহুবর্ষীয় কোডে উদ্ভট অসুবিধাগুলি প্রবর্তন করবেন না যা কেবলমাত্র Taskএটি সম্পর্কে জানে এটি একটি বড় ব্যাপার। এলএসপি কোনও কৌতুক নয়, তবে বৃহত সিস্টেমে রক্ষণাবেক্ষণে সহায়তা করার জন্য যথাযথভাবে চালু হয়েছিল।
আন্দ্রেস এফ 21

8
@ বেনলি ভাবুন আপনার একটি TaskCloserপ্রক্রিয়া আছে closesAllTasks(tasks)। এই প্রক্রিয়াটি অবশ্যই ব্যতিক্রমগুলি ধরার চেষ্টা করে না; সর্বোপরি, এটি এর সুস্পষ্ট চুক্তির অংশ নয় Task.Close()। এখন আপনি পরিচয় করিয়ে দেন ProjectTaskএবং হঠাৎ আপনার TaskCloserব্যতিক্রমগুলি ছোঁড়া শুরু করে (সম্ভবত অবিবাহিত)। এটা বড় কথা!
অ্যান্ড্রেস এফ 21

উত্তর:


173

হ্যাঁ, এটি এলএসপির লঙ্ঘন। Liskov উপকল্পন পুঁজি প্রয়োজন যে

  • পূর্ব শর্তগুলি উপ-টাইপে শক্তিশালী করা যায় না।
  • উপ-টাইপে পোস্টকন্ডিশনগুলি দুর্বল করা যায় না।
  • সুপারটাইপের আক্রমণকারীদের অবশ্যই একটি সাব টাইপে সংরক্ষণ করতে হবে।
  • ইতিহাস সীমাবদ্ধতা ("ইতিহাসের নিয়ম")। অবজেক্টগুলি কেবল তাদের পদ্ধতিগুলির মাধ্যমে (এনক্যাপসুলেশন) পরিবর্তিতযোগ্য হিসাবে বিবেচিত হয়। যেহেতু সাব টাইপগুলি এমন ধরণের পদ্ধতি প্রবর্তন করতে পারে যা সুপারটাইপটিতে উপস্থিত নেই, সুতরাং এই পদ্ধতিগুলির প্রবর্তনটি সুপার টাইপের ক্ষেত্রে অনুমতিপ্রাপ্ত নয় এমন উপ-প্রকারের রাজ্য পরিবর্তনকে অনুমতি দিতে পারে। ইতিহাসের সীমাবদ্ধতা এটি নিষিদ্ধ করে।

আপনার উদাহরণটি Close()পদ্ধতিটি কল করার জন্য পূর্বশর্ত জোরদার করে প্রথম প্রয়োজনীয়তা ভঙ্গ করে ।

উত্তরাধিকারক্রমক্রমের শীর্ষ স্তরে শক্তিশালী প্রাক-শর্তটি এনে আপনি এটি ঠিক করতে পারেন:

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

Stipulating যে একটি কল দ্বারা Close()শুধুমাত্র রাজ্যের বৈধ যখন CanClose()আয় trueআপনি পূর্বশর্ত ক্ষেত্রে প্রযোজ্য করা Taskথেকে সেইসাথে ProjectTask, LSP লঙ্ঘন ফিক্সিং:

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
আমি এই চেকটির সদৃশ পছন্দ করি না। আমি টাস্কে যাওয়ার ব্যতিক্রমটিকে পছন্দ করব lo বন্ধ করুন এবং বন্ধ থেকে ভার্চুয়াল সরান।
ইওফোরিক

4
@ ইউফোরিক এটি সত্য, শীর্ষ স্তরের Closeচেকিং করা এবং একটি সুরক্ষিত যুক্ত করা DoCloseবৈধ বিকল্প হতে পারে। যাইহোক, আমি ওপি'র উদাহরণের সাথে যতটা সম্ভব দূরে থাকতে চেয়েছিলাম; এটির উন্নতি করা একটি পৃথক প্রশ্ন।
dasblinkenlight

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
এর জন্য আপনাকে ধন্যবাদ, আপনি দশব্লিংকনলাইটের উদাহরণটি আরও এক পর্যায়ে নিয়েছিলেন, তবে আমি তার ব্যাখ্যা পছন্দ করি না tific দুঃখিত আমি 2 উত্তর গ্রহণ করতে পারি না!
পল টি ডেভিস

স্বাক্ষরটি কেন প্রকাশ্য ভার্চুয়াল বুল ক্যানক্লোজ (আউট স্ট্রিং কারণ) - তা জানতে আগ্রহী - আউট ব্যবহার করে আপনি কি কেবল ভবিষ্যতের প্রমাণ করছেন? নাকি আরও কিছু সূক্ষ্ম আছে যা আমি মিস করছি?
রিচার গিল্ট

3
@ রিচারগিল্ট আমার মনে হয় আপনার কি করা উচিত / রেফারেন্স করা উচিত এবং আমার কোডটি আবার পড়তে হবে। আপনি সন্দিহান. সহজভাবে "যদি কাজটি বন্ধ না করতে পারে তবে আমি কেন তা জানতে চাই" "
ইউফোরিক

2
সমস্ত ভাষায় আউট পাওয়া যায় না, একটি টিপল ফিরিয়ে দেওয়া (বা কোনও সহজ বিষয় যা এর কারণ এবং বুলিয়ানকে আবৃত করে তা সরাসরি একটি বোল থাকার সহজলভ্যতা ব্যয় করেও ওও ভাষাগুলিতে আরও ভাল বহনযোগ্য করে তোলে make সমর্থন করুন, এই উত্তরের সাথে কোনও ভুল নেই
নিউটোপিয়ান

1
এবং ক্যানক্লোজ সম্পত্তিটির পূর্বশর্তগুলি শক্তিশালী করা ঠিক আছে? আই শর্ত যুক্ত করছি?
জন ভি

24

লিসকভ প্রতিস্থাপন নীতিতে বলা হয়েছে যে একটি বেস শ্রেণীর প্রোগ্রামের পছন্দসই বৈশিষ্ট্যগুলির কোনও পরিবর্তন না করে তার যে কোনও উপ-শ্রেণীর সাথে প্রতিস্থাপনযোগ্য হওয়া উচিত। যেহেতু ProjectTaskবন্ধ হওয়ার পরে কেবল একটি ব্যতিক্রম উত্থাপন করা হয়, এর জন্য একটি প্রোগ্রামকে অ্যাকোমোডেটে পরিবর্তন করতে ProjectTaskহবে , প্রতিস্থাপনে ব্যবহার করা উচিত Taskসুতরাং এটি লঙ্ঘন।

তবে আপনি যদি Taskতার স্বাক্ষরে উল্লেখ করে সংশোধন করেন যে এটি বন্ধ হওয়ার সময় এটি ব্যতিক্রম বাড়াতে পারে তবে আপনি নীতি লঙ্ঘন করবেন না।


আমি সি # ব্যবহার করি যা আমি মনে করি না এই সম্ভাবনা আছে, তবে আমি জানি জাভাও তাই করে।
পল টি ডেভিস

2
@PaulTDavies আপনার সাথে একটি পদ্ধতি কি ব্যতিক্রম এটা ছোঁড়ার, সাজাইয়া পারেন msdn.microsoft.com/en-us/library/5ast78ax.aspx । আপনি এটি লক্ষ্য করুন যখন আপনি বেস ক্লাসের লাইব্রেরি থেকে কোনও পদ্ধতি ঘুরে দেখেন আপনি ব্যতিক্রমগুলির একটি তালিকা পাবেন। এটি প্রয়োগ করা হয়নি, তবে তা কলারকে সচেতন করে তোলে।
দেশ্পের্তে

18

একটি এলএসপি লঙ্ঘনের জন্য তিনটি পক্ষের প্রয়োজন। টাইপ টি, সাব টাইপ এস, এবং প্রোগ্রাম টি পি ব্যবহার করে তবে এস এর উদাহরণ দেওয়া হয় is

আপনার প্রশ্নটি টি (টাস্ক) এবং এস (প্রজেক্টটাস্ক) সরবরাহ করেছে, তবে পি নয়। সুতরাং আপনার প্রশ্নটি অসম্পূর্ণ এবং উত্তরটি যোগ্য: লঙ্ঘন। প্রতিটি পি যদি ব্যতিক্রম প্রত্যাশা করে তবে কোনও এলএসপি লঙ্ঘন নেই।

তবে আপনার কাছে একটি এসআরপি লঙ্ঘন রয়েছে। কোনও কার্যের অবস্থা পরিবর্তন করা যেতে পারে এবং নির্দিষ্ট রাজ্যে নির্দিষ্ট কাজগুলিকে অন্য রাজ্যে পরিবর্তন করা উচিত নয় এমন নীতি দুটি খুব আলাদা দায়িত্ব।

  • দায়িত্ব ১: একটি কাজের প্রতিনিধিত্ব করুন।
  • দায়িত্ব ২: নীতিগুলি কার্যকর করুন যা কার্যের স্থিতি পরিবর্তন করে।

এই দুটি দায়িত্ব বিভিন্ন কারণে পরিবর্তিত হয় এবং তাই পৃথক শ্রেণিতে থাকা উচিত। টাস্কগুলিকে একটি টাস্ক হওয়ার সত্যতা এবং কোনও কাজের সাথে সম্পর্কিত ডেটা পরিচালনা করা উচিত। টাস্কস্টেটপলিসিকে কোনও নির্দিষ্ট অ্যাপ্লিকেশনে রাজ্য থেকে রাজ্যে রূপান্তর করার উপায় পরিচালনা করতে হবে।


2
দায়িত্বগুলি ডোমেনের উপর এবং (এই উদাহরণে) কতটা জটিল টাস্কের রাষ্ট্র এবং এর পরিবর্তনকারীরা তার উপর নির্ভর করে depend এই ক্ষেত্রে, এই জাতীয় কোনও ইঙ্গিত নেই, তাই এসআরপি নিয়ে কোনও সমস্যা নেই। এলএসপি লঙ্ঘনের ক্ষেত্রে, আমি বিশ্বাস করি যে আমরা সকলেই ধরে নিয়েছি যে কলার কোনও ব্যতিক্রমের প্রত্যাশা করে না এবং অ্যাপ্লিকেশনটিকে ভুল অবস্থায় যাওয়ার পরিবর্তে যুক্তিসঙ্গত বার্তা প্রদর্শন করা উচিত।
ইওফোরিক

উনকা 'বব সাড়া দেয়? "আমরা যোগ্য নই! আমরা যোগ্য নই!"। যাইহোক ... প্রতিটি পি যদি ব্যতিক্রম প্রত্যাশা করে তবে কোনও এলএসপি লঙ্ঘন নেই। তবে আমরা যদি কোনও টি উদাহরণ নির্ধারণ করি তবে এটি একটি OpenTaskException(ইঙ্গিত, ইঙ্গিত) নিক্ষেপ করতে পারে না এবং প্রতিটি পি ব্যতিক্রম প্রত্যাশা করে তবে কোডটি ইন্টারফেসের ক্ষেত্রে কী বলে , বাস্তবায়ন নয়? আমি কি সম্পর্কে কথা বলছি? আমি জানি না। আমি কেবল জাজেড হয়েছি যে আমি একটি আনকা 'বব উত্তরে মন্তব্য করছি।
রাডারবব

3
আপনি সঠিক যে একটি এলএসপি লঙ্ঘন প্রমাণ করার জন্য তিনটি বস্তুর প্রয়োজন। যাইহোক, এলএসপি লঙ্ঘন উপস্থিত রয়েছে যদি কোনও প্রোগ্রাম পি থাকে যা এস এর অনুপস্থিতিতে সঠিক ছিল তবে এস যোগ করে ব্যর্থ হয়
কেভিন লাইন

16

এটি এলএসপির লঙ্ঘন হতে পারে বা নাও হতে পারে।

সিরিয়াসলি। আমার কথা শুনুন.

আপনি যদি এলএসপি অনুসরণ করেন তবে টাইপের অবজেক্টগুলিকে ProjectTaskঅবশ্যই আচরণ করা উচিত যেমন ধরণের অবজেক্টগুলির আচরণ করা উচিত Task

আপনার কোডের সাথে সমস্যাটি হ'ল ধরণের বস্তুগুলি কীভাবে Taskআচরণ করে বলে আশা করা যায় তা আপনি নথিভুক্ত করেননি । আপনার কোড লিখিত আছে, কিন্তু কোনও চুক্তি নেই। আমি এর জন্য একটি চুক্তি যুক্ত করব Task.Close। আমি যে চুক্তিটি যুক্ত করছি তার উপর নির্ভর করে কোডটি ProjectTask.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 নেই LSP অনুসরণ করুন:

     // 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, কিন্তু জানেন না এটি কোন শ্রেণীর প্রত্যক্ষ উদাহরণ is এটি সাবক্লাসের ডিজাইনারদেরও বলে যে কোনটি ওভাররাইড যুক্তিসঙ্গত এবং কোনটি যুক্তিসঙ্গত নয়।

  • "ডিফল্ট আচরণ" নথিটি এমন কোনও ক্লায়েন্টের উপর নির্ভর করতে পারে যা জানে যে প্রাপক অবজেক্টের প্রত্যক্ষ উদাহরণ Task(যেমন আপনি যদি ব্যবহার করেন তবে আপনি কী পাবেন new Task()sub এটি সাবক্লাসের ডিজাইনারদেরও জানিয়েছে যে তারা যদি আচরণ না করে তবে কী আচরণ উত্তরাধিকার সূত্রে প্রাপ্ত হবে) পদ্ধতিটি ওভাররাইড করুন।

এখন নিম্নলিখিত সম্পর্কগুলি রাখা উচিত:

  • যদি এস টি টির একটি উপ-প্রকার হয়, এস এর নথিভুক্ত আচরণের টি এর নথিভুক্ত আচরণকে পরিমার্জন করা উচিত।
  • যদি এস এর উপ-প্রকার টি (বা সমান) হয় তবে এস এর কোডের আচরণ টি এর নথিভুক্ত আচরণকে পরিমার্জন করা উচিত S
  • যদি এস এর উপ-প্রকার টি (বা সমান) টি হয় তবে এস এর ডিফল্ট আচরণটি টি এর নথিভুক্ত আচরণকে পরিমার্জন করবে S
  • কোনও শ্রেণীর জন্য কোডের আসল আচরণের এটির ডকুমেন্টেড ডিফল্ট আচরণটি সংশোধন করা উচিত।

@ ইউজার 18১ the৫২ পয়েন্টটি উত্থাপন করেছে যে আপনি পদ্ধতির স্বাক্ষরে উল্লেখ করতে পারেন যে এটি একটি ব্যতিক্রম বাড়াতে পারে এবং কেবল এটি করে (এমন কোনও কিছু যা বাস্তবের কোড ভিত্তিক নেই) আপনি আর আর এলএসপি ভাঙ্গছেন না।
পল টি ডেভিস

পছন্দ করেছেন তবে বেশিরভাগ ভাষায় স্বাক্ষরটি ঘোষণা করা ভাল উপায় নয় যে কোনও রুটিন ব্যতিক্রম হতে পারে। উদাহরণস্বরূপ ওপিতে (সি # তে, আমি মনে করি) এর দ্বিতীয় প্রয়োগটি Closeনিক্ষেপ করবে না। সুতরাং স্বাক্ষর ঘোষণা করে যে একটি ব্যতিক্রম ছুঁড়ে দেওয়া হতে পারে - এটি বলে না যে এটি করবে না। জাভা এ ক্ষেত্রে আরও ভাল কাজ করে। তবুও, যদি আপনি ঘোষণা করেন যে কোনও পদ্ধতি ব্যতিক্রম ঘোষণা করতে পারে, তবে আপনাকে (বা ইচ্ছা) পরিস্থিতিতে ডকুমেন্ট করা উচিত। সুতরাং আমি যুক্তি দিচ্ছি যে এলএসপি লঙ্ঘন হয়েছে কিনা তা নিশ্চিত হওয়ার জন্য আমাদের স্বাক্ষরের বাইরে ডকুমেন্টেশন প্রয়োজন।
থিওডোর নরভেল

4
এখানে প্রচুর উত্তরগুলি পুরোপুরি এই বিষয়টি এড়িয়ে গেছে বলে মনে হয় যে আপনি যদি চুক্তিটি জানেন না তবে কোনও চুক্তি বৈধ হয়েছে কিনা তা আপনি জানতে পারবেন না। এই উত্তরের জন্য ধন্যবাদ।
gnasher729

ভাল উত্তর, তবে অন্যান্য উত্তরগুলিও ভাল। তারা অনুমান করে যে বেস ক্লাসটি ব্যতিক্রম হয় না কারণ সেই শ্রেণিতে এমন কিছু নেই যা এর লক্ষণগুলি দেখায়। সুতরাং প্রোগ্রাম, যা বেস বর্গ ব্যবহার করে ব্যতিক্রমগুলির জন্য প্রস্তুত করা উচিত নয়।
inf3rno

আপনি ঠিক বলেছেন যে ব্যতিক্রম তালিকাটি কোথাও নথিভুক্ত করা উচিত। আমি মনে করি সেরা কোডটি কোডে রয়েছে। এখানে একটি সম্পর্কিত প্রশ্ন রয়েছে: stackoverflow.com/questions/16700130/… তবে আপনি এনোটোটেশন , ইত্যাদি ছাড়া এটি করতে পারেন ... খুব, কেবল if (false) throw new Exception("cannot start")বেস ক্লাসের মতো কিছু লিখুন । সংকলক এটি সরিয়ে ফেলবে, এবং এখনও কোডটিতে যা প্রয়োজন তা রয়েছে contains BTW। আমাদের এখনও এই কাজের সাথে একটি এলএসপি লঙ্ঘন আছে, কারণ পূর্বশর্তটি এখনও জোরদার ...
inf3rno

6

এটি লিসকভ সাবস্টিটিউশন নীতি লঙ্ঘন নয়।

লিসকভ সাবস্টিটিউশন নীতিতে বলা হয়েছে:

যাক কুই (x) এর একটি সম্পত্তি সম্পর্কে বস্তু প্রতিপাদ্য হতে এক্স ধরনের টি । যাক এস একটি উপপ্রকার হতে টি । প্রকার এস লস্কভ সাবস্টিটিউশন নীতি লঙ্ঘন করে যদি এস টাইপের কোনও বস্তু y থাকে, যেমন Q (y) প্রবণতাযোগ্য না হয়।

কারণ, আপনার সাব টাইপের বাস্তবায়ন কেন লিসকোভ সাবস্টিটিউশন নীতি লঙ্ঘন নয়, এটি বেশ সহজ: Task::Close()আসলে কী ঘটে তা প্রমাণিত হতে পারে না। নিশ্চিত, ProjectTask::Close()একটি ব্যতিক্রম যখন ছোঁড়ার Status == Status.Started, কিন্তু পারে Status = Status.Closedমধ্যে Task::Close()


4

হ্যাঁ, এটি লঙ্ঘন।

আমি আপনাকে পিছনে পিছনে আপনার শ্রেণিবিন্যাস আছে পরামর্শ দিতে চাই। যদি প্রতিটি Taskনিকটবর্তী না হয় তবে এর close()মধ্যে অন্তর্ভুক্ত নয় Task। সম্ভবত আপনি একটি ইন্টারফেস চান, CloseableTaskযা সমস্ত অ- ProjectTasksবাস্তবায়ন করতে পারে।


3
প্রতিটি টাস্ক ক্লোজযোগ্য, তবে প্রতিটি পরিস্থিতিতে নয়।
পল টি ডেভিস

এই পদ্ধতির বিষয়টি আমার পক্ষে ঝুঁকিপূর্ণ বলে মনে হচ্ছে লোকেরা ক্লাসেবল টাস্ক বাস্তবায়নের জন্য সমস্ত টাস্কের প্রত্যাশা কোড লিখতে পারে, যদিও এটি সমস্যার সঠিকভাবে মডেল করে। আমি এই পদ্ধতির এবং একটি রাষ্ট্রের মেশিনের মধ্যে ছিন্ন ছিটিয়েছি কারণ আমি রাষ্ট্রের মেশিনগুলিকে ঘৃণা করি।
জিমি হোফা

যদি Taskনিজেই এটি প্রয়োগ না করে CloseableTaskতবে তারা কল করার জন্য কোথাও একটি অনিরাপদ কাস্ট করছেন Close()
টম জি

@ টমজি যা থেকে আমি ভয় পাচ্ছি
জিমি হোফা

1
ইতিমধ্যে একটি রাষ্ট্রীয় মেশিন রয়েছে। বস্তুটি বন্ধ করা যায় না কারণ এটি ভুল অবস্থায় রয়েছে।
কাজ

3

এলএসপি সমস্যা হওয়া ছাড়াও, মনে হচ্ছে এটি প্রোগ্রাম প্রবাহ নিয়ন্ত্রণ করতে ব্যতিক্রম ব্যবহার করছে (আমি ধরে নিতে পারি যে আপনি কোথাও এই তুচ্ছ ব্যতিক্রমটি ধরেন এবং আপনার অ্যাপ্লিকেশনটি ক্র্যাশ না করে কিছু কাস্টম প্রবাহ করুন)।

দেখে মনে হচ্ছে এটি টাস্কস্টেটের জন্য রাজ্য প্যাটার্নটি বাস্তবায়নের জন্য ভাল জায়গা এবং রাষ্ট্রীয় বিষয়গুলি বৈধ স্থানান্তরগুলি পরিচালনা করতে দেয় manage


1

আমি এখানে এলএসপি এবং চুক্তি দ্বারা ডিজাইন সম্পর্কিত একটি গুরুত্বপূর্ণ বিষয় মিস করছি - পূর্বশর্তগুলিতে, পূর্ববর্তী শর্তগুলি পূরণ হয়েছে কিনা তা নিশ্চিত করার দায়িত্ব যার যার দায়িত্ব। DbC তত্ত্বে কল কোডটি পূর্ব শর্তটি যাচাই করা উচিত নয়। চুক্তিটি নির্দিষ্ট করা উচিত যখন কোন কাজ বন্ধ হয়ে যায় (যেমন ক্যানক্লোজ সত্য ফেরায়) এবং তারপরে কলিং কোডটি পূর্ববর্তী শর্তটি পূরণ করা উচিত, এটি ক্লোজ () বলার আগেই।


ব্যবসায়ের যে আচরণের প্রয়োজন তা চুক্তিতে উল্লেখ করা উচিত। এই ক্ষেত্রে, সেই ক্লোজ () শুরু করার পরে ডাকা হলে একটি ব্যতিক্রম উত্থাপন করবে ProjectTask। এটি একটি পোস্ট-শর্ত ( পদ্ধতিটি বলার পরে যা ঘটে তা বলে) এবং এটি পূরণ করা বলা হয় কোডের দায়িত্ব।
গায়ো

@ গায়ো হ্যাঁ, তবে অন্যরা যেমন বলেছিলেন যে ব্যতিক্রমটি সাব টাইপের ক্ষেত্রে উত্থাপিত হয়েছিল যা পূর্ব শর্তকে শক্তিশালী করে এবং এইভাবে (সংযুক্ত) চুক্তি লঙ্ঘন করে যে ক্লোজ () বলা সহজভাবে কাজটি বন্ধ করে দেয়।
ইজোইলা ভ্যাকা

কোন পূর্বশর্ত? আমি কিছু দেখতে পাচ্ছি না।
গায়ো

@ গায়ো গ্রহণযোগ্য উত্তরটি পরীক্ষা করুন, উদাহরণস্বরূপ :) বেস ক্লাসে ক্লোজের কোনও পূর্বশর্ত নেই, এটি বলা হয় এবং এটি কার্যটি বন্ধ করে দেয়। সন্তানের মধ্যে, তবে স্ট্যাটাস শুরু না হওয়ার বিষয়ে পূর্ব শর্ত রয়েছে। অন্যরা যেমন উল্লেখ করেছে, এটি শক্তিশালী মাপদণ্ড এবং আচরণটি বদলিযোগ্য নয়।
ইজোইলা ভ্যাকা

কিছু মনে করবেন না, আমি প্রশ্নটিতে পূর্বশর্ত পেয়েছি। তবে এরপরে কন্ডিশনের প্রাক-শর্তাদি পরীক্ষা করা এবং যখন সেগুলি পূরণ না হয় তখন ব্যতিক্রম বাড়াতে কোনও ভুল (ডিবিসি-ওয়াইজ) নেই। একে বলা হয় "ডিফেন্সিভ প্রোগ্রামিং"। তদ্ব্যতীত, পূর্ব-শর্তটি এই ক্ষেত্রে যেমন পূরণ করা হয় না তখন কী ঘটে থাকে তা উল্লেখ করে যদি কোনও পোস্ট-শর্ত থাকে তবে পোস্ট-শর্তটি পূরণ হয়েছে কিনা তা নিশ্চিত করার জন্য বাস্তবায়নটিকে পূর্ব-শর্তটি যাচাই করতে হবে।
গায়ো

0

হ্যাঁ, এটি এলএসপির স্পষ্ট লঙ্ঘন।

কিছু লোক এখানে যুক্তি দেয় যে বেস ক্লাসে স্পষ্ট করে দেওয়া যে সাবক্লাসগুলি ব্যতিক্রমগুলি ছুঁড়ে ফেলতে পারে এটি গ্রহণযোগ্য করে তুলবে, তবে আমি এটি সত্য বলে মনে করি না। বেস ক্লাসে আপনি কী ডকুমেন্ট করেন বা কোডটি কী বিমূর্ত স্তরটিতে আপনি সরান, তা পূর্ববর্তী শর্তগুলি সাবক্লাসে এখনও প্রসারিত হবে, কারণ আপনি এটিতে "শুরু করা প্রকল্পের কাজটি বন্ধ করতে পারবেন না" অংশটি যুক্ত করেন। এটি এমন কোনও কাজ নয় যা আপনি কাজের সাথে সমাধান করতে পারেন, আপনার একটি আলাদা মডেল দরকার, যা এলএসপি লঙ্ঘন করে না (বা আমাদের "পূর্বশর্তগুলিকে ngিলা করতে হবে" সীমাবদ্ধতা নয়)।

আপনি যদি এই ক্ষেত্রে এলএসপি লঙ্ঘন এড়াতে চান তবে আপনি ডেকোরেটর প্যাটার্নটি চেষ্টা করতে পারেন। এটা কাজ করতে পারে, আমি জানি না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.