গল্প:
একবার একটা ছোট্ট গ্রামে ছিল মিনা এবং তার বন্ধু সোহেল। তারা দুজনেই খুব ভালো রান্না করতে পারতো। মিনা বিশেষ করে কেক বানাতে খুব পছন্দ করত, আর সোহেল পেস্ট্রি বানাতে। তাদের মধ্যে একটা চুক্তি ছিল যে, যখনই কেউ কেক বানাবে, অন্যজন সেটা পেস্ট্রির মতো সাজাবে।
একদিন মিনা একটা বড় কেক বানালো। সে কেকটা খুব সুন্দরভাবে সাজাল এবং সোহেলকে বলল, “এই কেকটা তুমি পেস্ট্রির মতো সাজাতে পারো?”
সোহেল কেকটা দেখে বলল, “কিন্তু আমি কেক সাজাতে পারি না, কারণ আমি পেস্ট্রি বানাতে অভ্যস্ত!” মিনা বলল, “কিন্তু তুমি তো রেসিপি জানো, তাই তুমি সাজাতে পারবে।”
কিন্তু যখন সোহেল কেকটা সাজানোর চেষ্টা করল, সে বুঝতে পারলো যে কেকের জন্য তার যে দক্ষতা দরকার ছিল, তা তার নেই। ফলে কেকটা সঠিকভাবে সাজাতে পারল না এবং শেষ পর্যন্ত কেকটা নষ্ট হয়ে গেল।
এই গল্প থেকে আমরা কী শিখলাম?
এই গল্পটা “Liskov Substitution Principle (LSP)” এর উদাহরণ।
LSP বলে, একটি সাবক্লাস (subclass) ব্যবহার করা উচিত যেন মূল ক্লাস (superclass) এর প্রতিস্থাপন হিসেবে সঠিকভাবে কাজ করতে পারে। অর্থাৎ, যখনই আমরা সাবক্লাস ব্যবহার করি, সেটা যেন মূল ক্লাসের বৈশিষ্ট্যগুলো ঠিকভাবে বজায় রাখতে পারে।
এখন, প্রোগ্রামিং-এ এটা কেমন হয়?
ধরা যাক, আমাদের একটা ক্লাস আছে Bird নামে, যেটা সাধারণ পাখির জন্য:
class Bird:
def fly(self):
return "I can fly"
এখন, আমাদের Bird ক্লাসের একটি সাবক্লাস Sparrow তৈরি করি:
class Sparrow(Bird):
def fly(self):
return "Sparrow flying"
এখন, যদি আমরা আরেকটা সাবক্লাস Penguin তৈরি করি, যেটা ঠিকভাবে উড়তে পারে না:
class Penguin(Bird):
def fly(self):
raise Exception("I can't fly")
এখন আমরা যদি Penguin ক্লাসকে Bird ক্লাসের প্রতিস্থাপন হিসেবে ব্যবহার করি, তাহলে দেখা যাবে যে এটি সঠিকভাবে কাজ করছে না। কারণ পেঙ্গুইন উড়তে পারে না, তাই এটি Bird ক্লাসের বৈশিষ্ট্য বজায় রাখছে না।
LSP এর ভিত্তিতে আমরা কী করতে পারি?
আমরা যদি Bird ক্লাসের জন্য Flyable নামের একটি ইন্টারফেস তৈরি করি, তখন কেবলমাত্র উড়তে পারা পাখিরা সেই ইন্টারফেস বাস্তবায়ন করবে:
class Flyable:
def fly(self):
pass
class Sparrow(Bird, Flyable):
def fly(self):
return "Sparrow flying"
class Penguin(Bird):
def swim(self):
return "Penguin swimming"
এখন, Sparrow উড়তে পারবে এবং Penguin শুধুমাত্র সাঁতার কাটবে।
সুবিধা:
- ভুল এড়ানো: আমরা সাবক্লাস ব্যবহার করার সময় ভুলে পড়ার সম্ভাবনা কমে যাবে।
- সহজ রক্ষণাবেক্ষণ: নতুন পাখি যোগ করলেও কোডের স্থিতিশীলতা বজায় থাকবে।
- শক্তিশালী কাঠামো: প্রোগ্রাম আরও শক্তিশালী ও যুক্তিসঙ্গত হবে।
এভাবেই Liskov Substitution Principle আমাদের কোডকে আরও কার্যকর এবং সঠিকভাবে কাজ করতে সাহায্য করে।