রুবি ইচ্ছাকৃতভাবেই কিছু এরর এবং এক্সেপশন আপনার কাছ থেকে লুকিয়ে রাখে।
কখনো কখনো এটি উপকারী হতে পারে।
যেমন Kernel#loop মেথড ব্লকের সাথে ব্যবহার করার সময়, loop থামবে যখন StopIteration এক্সেপশন থ্রো হবে।
কিন্তু অন্য সময় এটি আপনার ডিবাগিং সেশনগুলোকে অনেক কঠিন করে দিতে পারে।
আসুন কিছু উদাহরণ দেখি!
লুকানো এক্সেপশন: Comparable মডিউল + <=> মেথড
প্রথম উদাহরণ জড়িত Comparable মডিউল এবং <=> মেথড।
এখানে উদাহরণ:
class MyObject
attr_accessor :value
include Comparable
def initialize(value)
@value = value
end
def <=>(other)
raise ArgumentError, "can't compare #{other.class} with #{self.class}" unless other.is_a?(MyObject)
value <=> other.valuee
end
end
mo1 = MyObject.new(10)
mo2 = MyObject.new(10)
p mo1 == mo2
এই উদাহরণ সম্পর্কে কথা বলি।
প্রথমে:
আমাদের একটি ক্লাস আছে MyObject নামে, একটি attr_accessor value সহ, এবং Comparable মডিউল ইনক্লুড করা আছে, যা আমাদের ক্লাসে কমপারিজন মেথড (যেমন ==, <, >) যোগ করে।
এই কমপারিজন মেথডগুলো <=> মেথডের ওপর বেসড।
যেন Enumerable মেথডগুলো each মেথডের ওপর বেসড।
তারপর:
আমরা দুটি অবজেক্ট তৈরি করছি (MyObject.new) একই ভ্যালু (10) দিয়ে।
লক্ষ্য করুন যে একই ভ্যালু থাকলেও তারা ভিন্ন অবজেক্ট, এটি গুরুত্বপূর্ণ।
এখন যদি আমরা এই দুটি অবজেক্ট mo1 এবং mo2 তুলনা করি তবে আমরা false পাই...
কেন?
কারণ আমাদের <=> মেথডে একটি এরর আছে, কিন্তু রুবি সেটি লুকিয়ে রাখছে!
ঘনিষ্ঠভাবে দেখুন...
আপনি কি এররটি খুঁজে পেয়েছেন? যদি পেয়েছেন তবে খুব ভালো! না পেলে কোনো কথা নয় 🙂
এটি रहा:
value <=> other.valuee
এই valuee দেখছেন?
বের হয়েছে আমাদের একটি টাইপো আছে!
সাধারণত আমরা একটি NoMethodError এক্সেপশন পেতাম এবং খুব দ্রুত সমস্যাটি বুঝতে পারতাম। কিন্তু এই উদাহরণে না।
ভালো খবর হলো রুবি ২.৩ থেকে এটি পরিবর্তন হয়েছে। আপনি এখন এররটি দেখতে পাবেন যেহেতু এখন এটি লুকানো নয়।
আরেকটি কারণ আপগ্রেড করার জন্য যদি আপনি পুরনো রুবি ভার্সন রান করছেন।
লুকানো এক্সেপশন: Numeric অবজেক্ট + Coercion মেথড
লুকানো এক্সেপশন আরেকটি উদাহরণ হলো Numeric অবজেক্ট (Float, Integer) প্লাস coerce মেথড।
এখানে একটি উদাহরণ:
class MyObject
attr_accessor :value
def initialize(value)
@value = value
end
def +(other)
other = MyObject.new(other) if other.kind_of?(Numeric)
value + other.value
end
def coerce(other)
mo = MyObject.new
mo.valuee = other
[mo, self]
end
end
mo1 = MyObject.new 10
mo2 = MyObject.new 10
p mo1 + mo2 # 20
p mo1 + 20 # 30
এটি আরেকটি MyObject ক্লাস, কিন্তু নতুন মেথডসহ, + এবং coerce।
coerce মেথড আপনাকে দুটি ইনকম্প্যাটিবল টাইপ নিয়ে কাজ করতে দেয় এবং সেগুলোকে একই টাইপে রূপান্তর করে যাতে সেগুলো একসাথে কাজ করতে পারে।
এই কেসে আমাদের ক্লাস কিছু নিউমেরিক ভ্যালু রিপ্রেজেন্ট করে, যা সেকেন্ডের সংখ্যা, একটি প্রাইস বা এরকম কিছুই হতে পারে...
এবং আমরা এই ধরনের অপারেশন করতে চাই:
mo1 + 20 20 + mo1
প্রথমটি (mo1 + 20) সহজ যেহেতু আমরা আমাদের ক্লাসের + মেথড কন্ট্রোল করি।
কিন্তু Integer ক্লাসের বিষয়টি কেমন?
আমরা Integer-এর + মেথড পরিবর্তন করে এটি ইমপ্লিমেন্ট করতে পারতাম, কিন্তু সেটি সম্ভবত ভালো আইডিয়া নয় 🙂
সমাধান?
আপনার নিজের ক্লাসে coerce মেথড ইমপ্লিমেন্ট করুন।
Integer-এর + মেথড যা করবে 그중 একটি হলো চেক করা আপনার অবজেক্ট এই মেথডটি ইমপ্লিমেন্ট করেছে কিনা, এবং যদি করছে তবে এটি কল করবে।
এখন, এই সেকশনের শুরুতে কোড উদাহরণটি মনে করুন?
যদি আমরা এটি করার চেষ্টা করি:
20 + mo1
আমরা 30 দেখতে চাই, কারণ mo1-এর ভ্যালু 10। কিন্তু যা আমরা দেখি সেটি হলো:
MyObject can't be coerced into Fixnum
সেইম সমস্যা!
coerce মেথডের ভেতরে একটি এরর লুকানো হচ্ছে।
এটি: mo.valuee = other
আবারও আমাদের একটি টাইপো, কিন্তু এরর মেসেজ সেটি বলছে না!
MyObject can't be coerced into Fixnum
আমার আপনার জন্য ভালো খবর, এই আচরণ রুবি ২.৫-এ পরিবর্তন হচ্ছে, তাই এটি আরেকটি লুকানো এরর যাবে যাতে আপনাকে এর সম্পর্কে চিন্তা করতে হয় না।
সারসংক্ষেপ
আপনি দেখতে পাচ্ছেন এগুলো কেন আপনাকে এক্সেপশন লুকানো এড়াতে হয় তার ভালো উদাহরণ। আপনি এক্সেপশন সম্পর্কে আরও জানতে পারেন আমার বই, Ruby Deep Dive-এ।
আমি কৃতজ্ঞ হব যদি আপনি এই পোস্টটি আপনার বন্ধুদের সাথে শেয়ার করেন যাতে আরও মানুষ এটি দেখতে পারে।
পড়ার জন্য ধন্যবাদ!