"রুবিতে কখনো Exception রেসকিউ করবেন না!"
হয়তো আপনি এই কথা শোনেছেন। এটা ভালো পরামর্শ, কিন্তু আপনি যদি ইতিমধ্যে না জানেন তবে এটা খুব কনফিউজিং। চলুন এই স্টেটমেন্টটি ভাঙিয়ে দেখি কি বোঝায়।
আপনি সম্ভবত জানেন রুবিতে আপনি এক্সেপশন রেসকিউ করতে পারেন এইভাবে:
begin
do_something()
rescue => e
puts e # e হলো এক্সেপশন অবজেক্ট যাতে এরর সম্পর্কিত তথ্য থাকে।
end
এবং আপনি স্পেসifique এক্সেপশন ক্লাসের নাম দিয়ে নির্দিষ্ট এরর রেসকিউ করতে পারেন।
begin
do_something()
rescue ActiveRecord::RecordNotFound => e
puts e # শুধু RecordNotFound এক্সেপশন, বা সেটা থেকে ইনহেরিট করা ক্লাসগুলো রেসকিউ হবে
end
রুবিতে প্রতিটি টাইপের এক্সেপশন শুধু একটি ক্লাস। উপরের উদাহরণে, ActiveRecord::RecordNotFound শুধু একটি ক্লাসের নাম যা নির্দিষ্ট কনভেনশন মানى।
এটা গুরুত্বপূর্ণ কারণ আপনি যখন RecordNotFound রেসকিউ করেন, আপনি সেটা থেকে ইনহেরিট করা যেকোনো এক্সেপশনও রেসকিউ করেন।
কেন আপনাকে Exception রেসকিউ করা উচিত নয়
Exception রেসকিউ করার সমস্যা হলো এটা আসলে Exception থেকে ইনহেরিট করা সব এক্সেপশন রেসকিউ করে। যেটা হলো...সব!
এটা সমস্যা কারণ কিছু এক্সেপশন রুবি আত্মিকভাবে ব্যবহার করে। এগুলোর আপনার অ্যাপের সাথে কোনো সম্পর্ক নেই, এবং এগুলোর গিলে ফেললে খারাপ জিনিসগুলো ঘটবে।
এখানে বড় কিছু উদাহরণ:
SignalException::Interrupt - আপনি এটা রেসকিউ করলে, কন্ট্রোল-সি দিয়ে অ্যাপ বন্ধ করতে পারবেন না।
ScriptError::SyntaxError - সিনট্যাক্স এরর গিলে ফেললে
puts("Forgot something)এর মতো জিনিস সাইলেন্টলি ফেল হয়ে যাবে।NoMemoryError - আপনার প্রোগ্রাম সকল র্যাম ব্যবহার করার পরও চলতে থাকলে কি হবে? আমি জানতে চাই না।
begin
do_something()
rescue Exception => e # এটি করবেন না। এটি প্রতিটি একক এক্সেপশন গিলে ফেলবে। কিছুই এর পাশ দিয়ে যাবে না।
end
আমি অনুমান করি আপনি আসলে এই সিস্টেম-লেভেল এক্সেপশনগুলো গিলে ফেলতে চান না। আপনি শুধু আপনার অ্যাপ্লিকেশন লেভেল এররগুলো ক্যাচ করতে চান। আপনার কোডের কারণে হওয়া এক্সেপশনগুলো।
خوشবর, এটা করার একটি সহজ উপায় আছে।
বদলে StandardError রেসকিউ করুন
আপনার যত্নের সব এক্সেপশন StandardError থেকে ইনহেরিট করে। এগুলো আমাদের পুরানো বন্ধু:
NoMethodError - অস্তিত্বহীন মেথড ইনভোক করলে উত্থাপিত হয়
TypeError -
1 + ""এর মতো জিনিসের কারণে হয়RuntimeError - কে ভুলে পারে ভালো পুরানো RuntimeError কে?
এই জাতীয় এরর রেসকিউ করতে, আপনাকে StandardError রেসকিউ করতে হবে। আপনি এটা এইভাবে লিখতে পারেন:
begin
do_something()
rescue StandardError => e
# শুধু আপনার অ্যাপের এক্সেপশনগুলো গিলে ফেলা হয়। SyntaxError এর মতো জিনিস অছutet থাকে।
end
কিন্তু রুবি আমাদের জন্য এটা অনেক সহজ করে দিয়েছে।
আপনি যদি এক্সেপশন ক্লাস নির্দিষ্ট না করেন, রুবি অনুমান করে আপনি StandardError মানে। তাই নিচের কোড উপরের কোডের সমান:
begin
do_something()
rescue => e
# এটি StandardError রেসকিউ করার সমান
end
কাস্টোম এক্সেপশন StandardError থেকে ইনহেরিট করা উচিত
তো আপনার জন্য এটা কি বোঝায় যদি আপনি নিজস্ব কাস্টোম এক্সেপশন তৈরি করেন?
এটা বোঝায় আপনাকে সবসময় StandardError থেকে ইনহেরিট করতে হবে, এবং কখনো Exception থেকে নয়। Exception থেকে ইনহেরিট করা খারাপ কারণ এটা rescue-র প্রত্যাশিত আচরণ ভাঙে দেয়। লোকভাববে তারা সব অ্যাপ্লিকেশন-লেভেল এরর রেসকিউ করছে কিন্তু আপনার এক্সেপশনই চুপচাপ পাশ দিয়ে যাবে।
class SomethingBad < StandardError
end
raise SomethingBad
দ্যা এক্সেপশন ট্রি
যেহেতু রুবির এক্সেপশনগুলো ক্লাস হায়ারার্কি হিসেবে ইমপ্লিমেন্টেড, তাই সেটা লে আউট করে দেখতে সাহায্যকারী। নিচে রুবির স্ট্যান্ডার্ড লাইব্রেরির সাথে আসা এক্সেপশন ক্লাসের তালিকা। থার্ড-পার্টি জেমস যেন রেলস এই চার্টে অতিরিক্ত এক্সেপশন ক্লাস যোগ করবে, কিন্তু সেগুলো সব এই লিস্টের যেকোনো ক্লাস থেকে ইনহেরিট করবে।
Exception
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SignalException
Interrupt
StandardError
ArgumentError
IOError
EOFError
IndexError
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit
fatal