এক্সেপশন হ্যান্ডলিং (Exception Handling) প্রোগ্রামিংয়ের একটি গুরুত্বপূর্ণ অংশ যা ত্রুটি (errors) বা অপ্রত্যাশিত পরিস্থিতি মোকাবেলা করতে ব্যবহৃত হয়। রুবিতে, এক্সেপশন হ্যান্ডলিং খুবই শক্তিশালী এবং সহজে ব্যবহারযোগ্য। এক্সেপশন হ্যান্ডলিংয়ের মাধ্যমে আপনি ত্রুটির কারণ শনাক্ত করতে, তাদের মোকাবেলা করতে এবং প্রোগ্রাম চলাকালীন ত্রুটির কারণে সম্পূর্ণ প্রোগ্রাম বন্ধ হয়ে না যাওয়ার ব্যবস্থা নিতে পারেন।
রুবিতে এক্সেপশন হ্যান্ডলিংয়ের জন্য মূলত begin, rescue, ensure, এবং raise কিওয়ার্ড ব্যবহার করা হয়। নিচে রুবিতে এক্সেপশন হ্যান্ডলিংয়ের মূল ধারণাগুলি বিস্তারিতভাবে আলোচনা করা হলো।
১. Basic Exception Handling (বেসিক এক্সেপশন হ্যান্ডলিং)
এক্সেপশন হ্যান্ডলিং শুরু করার জন্য আপনি begin এবং rescue ব্যবহার করতে পারেন। begin ব্লকের মধ্যে আপনি যেকোনো কোড লিখতে পারেন যা এক্সেপশন ঘটাতে পারে, এবং rescue ব্লকটি এক্সেপশন ঘটে গেলে কার্যকর হবে।
উদাহরণ:
begin
# Code that might raise an exception
result = 10 / 0 # This will raise a ZeroDivisionError
rescue ZeroDivisionError => e
# Handle the exception
puts "Error: Division by zero is not allowed."
puts e.message # Output: divided by 0
endএখানে, কোডের মধ্যে ১০ কে ০ দিয়ে ভাগ করার চেষ্টা করা হয়েছে, যা ZeroDivisionError সৃষ্টি করবে। rescue ব্লকটি সেই এক্সেপশনটি ক্যাচ (catch) করবে এবং একটি মেসেজ প্রিন্ট করবে।
২. Rescue for Specific Exceptions (নির্দিষ্ট এক্সেপশন হ্যান্ডলিং)
রুবি এক্সেপশন হ্যান্ডলিংয়ের মাধ্যমে আপনি নির্দিষ্ট ধরনের এক্সেপশন ক্যাচ করতে পারেন। আপনি একাধিক rescue ব্লক ব্যবহার করতে পারেন যাতে বিভিন্ন ধরনের এক্সেপশন আলাদা আলাদাভাবে হ্যান্ডল করা যায়।
উদাহরণ:
begin
# Code that might raise multiple exceptions
num = Integer("hello") # This will raise an ArgumentError
rescue ZeroDivisionError => e
puts "Error: Division by zero is not allowed."
rescue ArgumentError => e
puts "Error: Invalid argument. Please provide a number."
puts e.message
endএখানে, Integer("hello") কোডটি একটি ArgumentError সৃষ্টি করবে, যা ক্যাচ হবে এবং উপযুক্ত মেসেজ প্রিন্ট হবে।
৩. Ensure Block (এনস্যু ব্লক)
ensure ব্লকটি এমন একটি বিশেষ ব্লক যা এক্সেপশন ঘটুক বা না ঘটুক, begin ব্লকের পরে সর্বদা এক্সিকিউট হবে। এটি সাধারণত ফাইল বা ডাটাবেস কানেকশন বন্ধ করার জন্য ব্যবহার করা হয়।
উদাহরণ:
begin
puts "Opening file..."
# Some code that might raise an exception
result = 10 / 0
rescue ZeroDivisionError => e
puts "Caught an exception: #{e.message}"
ensure
puts "This will always execute, even if an exception occurred."
endএখানে, ensure ব্লকটি একটি এক্সেপশন ঘটুক বা না ঘটুক, সবসময় এক্সিকিউট হবে।
৪. Raising Exceptions (এক্সেপশন রেইজ করা)
রুবিতে আপনি নিজেও এক্সেপশন রেইজ করতে পারেন যদি কোন নির্দিষ্ট শর্তে আপনি কাস্টম এক্সেপশন চান। এটি raise কিওয়ার্ড ব্যবহার করে করা হয়।
উদাহরণ:
def divide(a, b)
raise ArgumentError, "Division by zero is not allowed" if b == 0
a / b
end
begin
result = divide(10, 0)
rescue ArgumentError => e
puts "Error: #{e.message}"
endএখানে, divide মেথডে যদি b == 0 হয়, তবে একটি ArgumentError এক্সেপশন রেইজ করা হয়, এবং এটি rescue ব্লকে হ্যান্ডল করা হয়।
৫. Custom Exceptions (কাস্টম এক্সেপশন)
রুবিতে আপনি নিজের কাস্টম এক্সেপশন তৈরি করতে পারেন, যা StandardError বা এর কোনো সাবক্লাস থেকে ইনহেরিট করে তৈরি করা হয়।
উদাহরণ:
class MyCustomError < StandardError
def initialize(msg="Something went wrong")
super
end
end
begin
raise MyCustomError, "Custom error occurred!"
rescue MyCustomError => e
puts "Caught custom error: #{e.message}"
endএখানে, MyCustomError একটি কাস্টম এক্সেপশন তৈরি করা হয়েছে এবং এটি একটি StandardError এর সাবক্লাস। এই কাস্টম এক্সেপশনটি raise মেথডের মাধ্যমে রেইজ করা হয়েছে এবং rescue ব্লক দ্বারা হ্যান্ডল করা হয়েছে।
৬. Retrying an Operation (অপারেশন পুনরায় চেষ্টা করা)
রুবিতে retry কিওয়ার্ড ব্যবহার করে আপনি কোনো এক্সেপশন ঘটলে পুনরায় চেষ্টা করতে পারেন।
উদাহরণ:
attempts = 0
begin
attempts += 1
puts "Attempting to connect to the server..."
raise "Connection failed" if attempts < 2
puts "Connected successfully!"
rescue => e
puts "#{e.message}. Retrying..."
retry if attempts < 3
endএখানে, প্রথম দুইটি অ্যাটেম্পট ব্যর্থ হলে retry ব্যবহার করে আবার চেষ্টা করা হবে, তবে সর্বোচ্চ ৩টি অ্যাটেম্পটের পরে প্রোগ্রাম থামবে।
সারসংক্ষেপ
রুবির এক্সেপশন হ্যান্ডলিং একটি অত্যন্ত শক্তিশালী এবং সহজ পদ্ধতি, যা প্রোগ্রাম চলাকালীন যেকোনো অপ্রত্যাশিত ত্রুটি বা সমস্যা হ্যান্ডল করতে সাহায্য করে। এটি begin, rescue, ensure, raise, এবং retry কিওয়ার্ড ব্যবহার করে কার্যকরীভাবে এক্সেপশন পরিচালনা করতে পারে। এক্সেপশন হ্যান্ডলিংয়ের মাধ্যমে প্রোগ্রাম নিরাপদে চলতে থাকে এবং ত্রুটির কারণে প্রোগ্রাম বন্ধ হওয়ার ঝুঁকি কমে।
Exception Handling হলো প্রোগ্রামিংয়ে একটি গুরুত্বপূর্ণ ধারণা, যা একটি প্রোগ্রামে কোনো ত্রুটি (Error) বা ব্যতিক্রম (Exception) ঘটলে তা সঠিকভাবে পরিচালনা করতে সাহায্য করে। রুবি ভাষায়, ত্রুটির কারণে প্রোগ্রামটি ক্র্যাশ না হয়ে সঠিকভাবে কাজ করতে exception handling ব্যবহৃত হয়। এর মাধ্যমে প্রোগ্রামটি চলাকালে যেকোনো ধরনের অপ্রত্যাশিত ত্রুটি ধরা এবং সেগুলোর সাথে সঠিকভাবে ব্যবস্থা নেয়া সম্ভব হয়।
Exception Handling এর কাঠামো
রুবিতে exception handling করার জন্য begin, rescue, ensure, এবং else ব্লক ব্যবহার করা হয়।
1. begin Block:
এই ব্লকটি দিয়ে আপনি সেই কোড লেখেন যা আপনি রান করাতে চান এবং সেখানে যদি কোনো exception (ত্রুটি) ঘটতে পারে, তবে সেটি ক্যাচ করার জন্য প্রস্তুত থাকেন।
2. rescue Block:
যখন একটি exception ঘটে, তখন rescue ব্লকটি তা হ্যান্ডল করে। এখানে আপনি নির্দিষ্ট exception টাইপগুলো ক্যাচ করে প্রয়োজনীয় ব্যবস্থা নিতে পারেন।
3. ensure Block:
ensure ব্লকটি ত্রুটি ঘটুক বা না ঘটুক, এটি সবসময় এক্সিকিউট হবে। এটি মূলত সেই কোডকে রাখতে ব্যবহৃত হয়, যা শেষের দিকে অবশ্যই চলবে (যেমন ফাইল বন্ধ করা, সংস্থান মুক্ত করা ইত্যাদি)।
4. else Block:
else ব্লকটি শুধুমাত্র তখন এক্সিকিউট হবে, যখন begin ব্লকে কোনো ত্রুটি (exception) ঘটবে না।
Exception Handling এর Syntax
begin
# কোড যা আপনি রান করতে চান
rescue SomeError => e
# ত্রুটি হলে কী করতে হবে
else
# কোনো ত্রুটি না হলে এটি এক্সিকিউট হবে
ensure
# সবসময় এই কোড এক্সিকিউট হবে
endException Handling উদাহরণ
১. Basic Example (বেসিক উদাহরণ)
begin
# এমন কোড যা ত্রুটি ঘটাতে পারে
num = 10 / 0 # ডিভিশন বাই জিরো
rescue ZeroDivisionError => e
# ত্রুটি হলে এই ব্লকটি কার্যকর হবে
puts "Error: #{e.message}"
endএখানে, 10 / 0 ত্রুটি ঘটাবে কারণ শূন্য দিয়ে ভাগ করা যাবে না। এই exception ZeroDivisionError ক্যাচ করা হবে এবং একটি ত্রুটি মেসেজ দেখানো হবে।
আউটপুট:
Error: divided by 0২. Multiple Exceptions (একাধিক Exception হ্যান্ডলিং)
রুবি আপনাকে একাধিক exception টাইপ হ্যান্ডল করতে দেয়। একাধিক rescue ব্লক ব্যবহার করা যায়।
begin
num = 10 / 0 # প্রথম ত্রুটি
arr = [1, 2, 3]
arr.fetch(5) # দ্বিতীয় ত্রুটি
rescue ZeroDivisionError => e
puts "Error: #{e.message}" # 'ZeroDivisionError' হ্যান্ডল
rescue IndexError => e
puts "Error: #{e.message}" # 'IndexError' হ্যান্ডল
endআউটপুট:
Error: divided by 0এখানে প্রথমে ZeroDivisionError ত্রুটি ঘটবে এবং তা হ্যান্ডল করা হবে।
৩. else ব্লক ব্যবহার (When No Exception Occurs)
যখন begin ব্লকটি কোনো ত্রুটি ছাড়াই এক্সিকিউট হয়, তখন else ব্লকটি কাজ করবে।
begin
puts "This is a safe operation."
rescue => e
puts "Error: #{e.message}"
else
puts "No errors occurred."
ensure
puts "This code will always run."
endআউটপুট:
This is a safe operation.
No errors occurred.
This code will always run.এখানে, ত্রুটি না ঘটলে else ব্লক এক্সিকিউট হয়, এবং ensure ব্লক সবসময় চলবে।
৪. ensure ব্লক:
ensure ব্লকটি এমন কোড রাখার জন্য ব্যবহৃত হয়, যা প্রোগ্রাম যেকোনো অবস্থায় এক্সিকিউট করবে, যেমন ফাইল বা ডাটাবেস কানেকশন বন্ধ করা।
begin
# কোড যা ত্রুটি ঘটাতে পারে
file = File.open("example.txt", "w")
file.puts "Hello, World!"
rescue => e
puts "Error: #{e.message}"
ensure
file.close if file # ফাইল বন্ধ করা
puts "File has been closed."
endআউটপুট:
File has been closed.এখানে, ensure ব্লকটি নিশ্চিত করবে যে ফাইল বন্ধ হয়ে যাবে, যা ত্রুটি ঘটুক বা না ঘটুক।
Exception Types (ত্রুটির ধরণ)
রুবিতে বিভিন্ন ধরনের exception (ত্রুটি) রয়েছে। কিছু সাধারণ exception টাইপ হচ্ছে:
StandardError: সাধারণ ত্রুটি যা ক্লাসের অভ্যন্তরে ঘটে।ZeroDivisionError: শূন্য দিয়ে ভাগ করা হলে ঘটে।ArgumentError: ভুল আর্গুমেন্ট প্রদান করলে ঘটে।IndexError: অ্যারে বা তালিকা থেকে অবৈধ ইনডেক্সে অ্যাক্সেস করলে ঘটে।
রুবি ত্রুটি ধরতে rescue ব্লকের মধ্যে নির্দিষ্ট exception টাইপ উল্লেখ করা যায়, অথবা সমস্ত ত্রুটির জন্য rescue => e ব্যবহার করা যায়।
Custom Exception (কাস্টম exception)
রুবি আপনাকে আপনার নিজস্ব exception তৈরি করার সুযোগ দেয়, যা নির্দিষ্ট ধরনের ত্রুটির জন্য ব্যবহৃত হয়। আপনি একটি নতুন exception ক্লাস তৈরি করতে পারেন যা StandardError অথবা অন্য কোনো এক্সেপশন ক্লাস থেকে উত্তরাধিকার লাভ করবে।
class MyCustomError < StandardError
def initialize(msg="This is a custom error")
super(msg)
end
end
begin
raise MyCustomError.new("Something went wrong!")
rescue MyCustomError => e
puts "Caught custom error: #{e.message}"
endআউটপুট:
Caught custom error: Something went wrong!এখানে, MyCustomError একটি কাস্টম exception যা আমাদের নির্ধারিত মেসেজ দিয়ে রাইজ করা হয়েছে।
Conclusion (সারসংক্ষেপ)
- Exception Handling হল প্রোগ্রামে ত্রুটি বা ব্যতিক্রম ঘটলে সেগুলি সঠিকভাবে হ্যান্ডল করার প্রক্রিয়া।
- রুবিতে
begin,rescue,else,ensureব্লক ব্যবহার করে exception handling করা হয়। rescueব্লকের মাধ্যমে বিভিন্ন ধরনের exception ক্যাচ করা যায়।ensureব্লক সবসময় এক্সিকিউট হয়, এবং এটি সিস্টেম ক্লিনআপের জন্য ব্যবহৃত হয়।- কাস্টম exception তৈরি করার জন্য নিজস্ব exception ক্লাস তৈরি করা যায়।
Exception handling এর মাধ্যমে আপনি প্রোগ্রামের ত্রুটির সাথে নিরাপদভাবে কাজ করতে পারেন এবং ব্যবহারকারীর জন্য আরও উন্নত অভিজ্ঞতা তৈরি করতে পারেন।
রুবি প্রোগ্রামিং ভাষায় exception handling (ত্রুটি ব্যবস্থাপনা) পরিচালনা করার জন্য begin, rescue, এবং ensure ব্লক ব্যবহার করা হয়। এগুলি কোডের মধ্যে ত্রুটি (error) ঘটলে সেই ত্রুটির মোকাবেলা করতে এবং পরবর্তী কোড নিরাপদভাবে চালানোর জন্য ব্যবহৃত হয়। রুবিতে এই তিনটি ব্লক একসাথে ব্যবহার করে আপনি কোডের স্থিতিশীলতা এবং নিরাপত্তা নিশ্চিত করতে পারেন।
১. begin ব্লক
begin ব্লক দিয়ে আপনি কোডের একটি সেগমেন্ট চিহ্নিত করেন, যেখানে ত্রুটি ঘটতে পারে। এই ব্লকের মধ্যে কোড লেখা হয় যেটি আপনি চালাতে চান এবং যার মধ্যে ত্রুটি ঘটলে সেই ত্রুটির জন্য rescue ব্লক ট্রিগার হবে।
begin
# কোড যা ত্রুটি ঘটাতে পারে
num = 10 / 0
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
endএখানে, begin ব্লকের মধ্যে num = 10 / 0 কোডটি একটি ZeroDivisionError ত্রুটি তৈরি করবে। এই ত্রুটি rescue ব্লক দ্বারা ধরা হবে এবং ত্রুটির বার্তা প্রদর্শিত হবে।
২. rescue ব্লক
rescue ব্লক ব্যবহৃত হয় ত্রুটির ধরন (exception type) চিহ্নিত করার জন্য এবং সেই ত্রুটির জন্য ব্যবস্থা নেওয়ার জন্য। যখন begin ব্লকের মধ্যে কোনো ত্রুটি ঘটে, তখন রুবি স্বয়ংক্রিয়ভাবে rescue ব্লকটি এক্সিকিউট করবে।
২.১ Basic Rescue
begin
# কোড যা ত্রুটি ঘটাতে পারে
file = File.open("nonexistent_file.txt")
rescue StandardError => e
puts "Caught an error: #{e.message}"
endএখানে, যদি "nonexistent_file.txt" ফাইলটি না থাকে, তাহলে একটি StandardError ত্রুটি হবে এবং rescue ব্লকটি এক্সিকিউট হবে, যা ত্রুটির বার্তা মুদ্রণ করবে।
২.২ Multiple Rescue Blocks
একাধিক ধরনের ত্রুটি ধরতে আপনি একাধিক rescue ব্লক ব্যবহার করতে পারেন।
begin
# কোড যা বিভিন্ন ত্রুটি ঘটাতে পারে
num = 10 / 0
file = File.open("nonexistent_file.txt")
rescue ZeroDivisionError => e
puts "Cannot divide by zero: #{e.message}"
rescue Errno::ENOENT => e
puts "File not found: #{e.message}"
endএখানে, ZeroDivisionError এবং Errno::ENOENT ত্রুটিগুলি পৃথকভাবে ধরা হচ্ছে এবং তাদের জন্য আলাদা বার্তা মুদ্রিত হচ্ছে।
৩. ensure ব্লক
ensure ব্লকটি একটি বিকল্প ব্লক যা সবসময় এক্সিকিউট হয়, ত্রুটি ঘটুক বা না ঘটুক। এটি সাধারণত ত্রুটি হ্যান্ডলিংয়ের পর পরবর্তী কাজের জন্য ব্যবহৃত হয়, যেমন রিসোর্স ক্লোজ করা বা পরিষ্কার করা (e.g., ফাইল বন্ধ করা, ডাটাবেস সংযোগ বন্ধ করা)।
begin
# কোড যা ত্রুটি ঘটাতে পারে
file = File.open("example.txt", "r")
content = file.read
puts content
rescue StandardError => e
puts "Caught an error: #{e.message}"
ensure
puts "This will always execute"
file.close if file # ফাইলটি যদি খোলা থাকে, তবে বন্ধ হবে
endএখানে, ensure ব্লকটি ত্রুটি ঘটুক বা না ঘটুক, সর্বদা এক্সিকিউট হবে। এটি ফাইল বা অন্য রিসোর্সের ক্লোজিং কাজ সম্পন্ন করবে।
৪. retry স্টেটমেন্ট
retry স্টেটমেন্টটি ত্রুটি ঘটলে কোডের শুরু থেকে পুনরায় চেষ্টা করতে ব্যবহৃত হয়। এটি সাধারণত একটি লুপের মধ্যে ব্যবহার করা হয়।
begin
# কোড যা ত্রুটি ঘটাতে পারে
num = 10 / 0
rescue ZeroDivisionError => e
puts "Error: #{e.message}, retrying..."
retry # আবার শুরু থেকে চেষ্টা করবে
endএখানে, ZeroDivisionError ত্রুটি ঘটলে, retry স্টেটমেন্টের মাধ্যমে পুনরায় begin ব্লকটি এক্সিকিউট করা হবে।
সারসংক্ষেপ
begin: কোডের অংশ যেখানে ত্রুটি ঘটতে পারে। এটি ত্রুটি হ্যান্ডলিং শুরু করে।rescue: ত্রুটি ঘটলে, সেই ত্রুটির জন্য ব্যবস্থাপনা করা হয়। এটি একাধিক ত্রুটি ধরতে ব্যবহৃত হতে পারে।ensure: এটি একটি বিকল্প ব্লক যা ত্রুটি ঘটুক বা না ঘটুক, সর্বদা এক্সিকিউট হয়। এটি কোডের শেষের দিকে রিসোর্স পরিষ্কার করার জন্য ব্যবহৃত হয়।retry: ত্রুটি ঘটলে কোড পুনরায় চালাতে ব্যবহৃত হয়।
রুবিতে এই তিনটি ব্লক ত্রুটি হ্যান্ডলিংয়ের জন্য একটি শক্তিশালী ও পরিষ্কার ব্যবস্থা সরবরাহ করে, যা আপনার কোডের স্থিতিশীলতা নিশ্চিত করে এবং ত্রুটি মোকাবেলায় সহায়ক।
Custom Exceptions বা ব্যক্তিগত ব্যতিক্রম (exception) রুবি প্রোগ্রামিং ভাষায় তৈরি করা সম্ভব, যা ব্যবহারকারীর প্রয়োজনীয়তা অনুযায়ী নির্দিষ্ট ত্রুটি বা ব্যতিক্রম তৈরি করে। রুবিতে Exception ক্লাসটি সব ধরনের ত্রুটি ধারণ করে, এবং আপনি এই ক্লাসটি সম্প্রসারণ (inherit) করে নিজের কাস্টম ত্রুটি তৈরি করতে পারেন।
১. Custom Exception তৈরি করা
রুবিতে custom exceptions তৈরি করতে, আপনি Exception ক্লাসকে এক্সটেন্ড করে একটি নতুন ক্লাস তৈরি করবেন। এরপর, আপনার কাস্টম ত্রুটির নাম ব্যবহার করে নির্দিষ্ট শর্তে ত্রুটি উত্তোলন করতে পারবেন।
Syntax:
class CustomError < StandardError
# Custom error logic
endএখানে, StandardError হলো রুবির ডিফল্ট Exception ক্লাস, যা সাধারণত ব্যবহার করা হয়। আপনি চাইলে এটি পরিবর্তন করতে পারেন, তবে সাধারণত এটি ব্যবহার করা হয়।
উদাহরণ:
class MyCustomError < StandardError
def initialize(msg = "A custom error occurred")
super(msg) # StandardError এর constructor কল করা হচ্ছে
end
end
# Raising the custom exception
begin
raise MyCustomError, "Something went wrong"
rescue MyCustomError => e
puts "Caught error: #{e.message}"
endআউটপুট:
Caught error: Something went wrongএখানে, MyCustomError নামে একটি কাস্টম ত্রুটি তৈরি করা হয়েছে, যা StandardError থেকে ইনহেরিট করছে। আমরা raise কমান্ড দিয়ে এই কাস্টম ত্রুটিটি উত্থাপন করেছি এবং rescue ব্লক দিয়ে ত্রুটিটি ধরেছি।
২. Custom Exception এর সাথে কাজ করা
যখন আপনি Custom Exception তৈরি করবেন, তখন তাতে আরো কাস্টম মেসেজ বা নির্দিষ্ট ফিল্ড যোগ করতে পারেন। এছাড়া, আপনি সেই ত্রুটি সম্পর্কে আরও বিস্তারিত তথ্যও যোগ করতে পারেন।
উদাহরণ:
class InvalidAgeError < StandardError
def initialize(msg = "Invalid age value provided")
super(msg)
end
end
def check_age(age)
raise InvalidAgeError, "Age must be a positive number" if age <= 0
puts "Age is valid"
end
begin
check_age(-5)
rescue InvalidAgeError => e
puts "Error: #{e.message}"
endআউটপুট:
Error: Age must be a positive numberএখানে, InvalidAgeError একটি কাস্টম ত্রুটি তৈরি করেছে যা শুধুমাত্র নির্দিষ্ট শর্ত (যেমন বয়সের মান ঋণাত্মক বা শূন্য) পূর্ণ হলে ত্রুটি উত্থাপন করে। raise দিয়ে সেই ত্রুটি উত্থাপন করা হয়েছে এবং rescue ব্লকে এটি ধরা হয়েছে।
৩. Custom Exception এ আরও ডেটা যুক্ত করা
আপনি কাস্টম এক্সসেপশনের মধ্যে অতিরিক্ত ডেটা সংরক্ষণ করতে পারেন, যেমন ত্রুটির কোড বা ট্রেস (stack trace)।
উদাহরণ:
class FileProcessingError < StandardError
attr_reader :file_name, :error_code
def initialize(file_name, error_code, msg = "File processing failed")
@file_name = file_name
@error_code = error_code
super(msg)
end
end
def process_file(file_name)
raise FileProcessingError.new(file_name, 404, "File not found") unless File.exist?(file_name)
puts "Processing file..."
end
begin
process_file("non_existent_file.txt")
rescue FileProcessingError => e
puts "Error: #{e.message}"
puts "File: #{e.file_name}"
puts "Error Code: #{e.error_code}"
endআউটপুট:
Error: File not found
File: non_existent_file.txt
Error Code: 404এখানে, FileProcessingError কাস্টম এক্সসেপশনটির মধ্যে ফাইলের নাম এবং ত্রুটির কোড ধারণ করা হচ্ছে। যখন ত্রুটি উত্থাপন করা হয়, তখন সেই ডেটা e.file_name এবং e.error_code দিয়ে অ্যাক্সেস করা হয়।
৪. Custom Exception এর সাথে ensure ব্যবহার
ensure ব্লক ব্যবহার করে আপনি এমন কোড চালাতে পারেন যা ত্রুটি ঘটুক বা না ঘটুক, নিশ্চয়ই চালানো হবে। এটি সাধারণত ক্লিনআপ (যেমন ফাইল বন্ধ করা, সংযোগ বিচ্ছিন্ন করা ইত্যাদি) করার জন্য ব্যবহার করা হয়।
উদাহরণ:
class DatabaseError < StandardError; end
def connect_to_database
raise DatabaseError, "Unable to connect to database" if rand > 0.5
puts "Connected to database"
end
begin
connect_to_database
rescue DatabaseError => e
puts "Error: #{e.message}"
ensure
puts "Closing database connection..."
endআউটপুট (ধরা যাক ত্রুটি ঘটেছে):
Error: Unable to connect to database
Closing database connection...এখানে, ensure ব্লকটি নিশ্চিত করবে যে, ত্রুটি ঘটুক বা না ঘটুক, "Closing database connection..." মেসেজটি অবশ্যই আউটপুট হবে।
৫. Multiple Custom Exceptions Handling
রুবিতে একাধিক কাস্টম এক্সসেপশন একত্রে ধরাও সম্ভব, যা বিভিন্ন ধরনের ত্রুটি একত্রে হ্যান্ডল করতে সাহায্য করে।
উদাহরণ:
class NotFoundError < StandardError; end
class UnauthorizedError < StandardError; end
def fetch_data(status)
if status == 404
raise NotFoundError, "Data not found"
elsif status == 401
raise UnauthorizedError, "Unauthorized access"
else
puts "Data fetched successfully"
end
end
begin
fetch_data(404)
rescue NotFoundError => e
puts "Error: #{e.message}"
rescue UnauthorizedError => e
puts "Error: #{e.message}"
endআউটপুট:
Error: Data not foundএখানে, NotFoundError এবং UnauthorizedError দুটি আলাদা কাস্টম এক্সসেপশন তৈরি করা হয়েছে এবং এগুলোর জন্য আলাদা আলাদা rescue ব্লক ব্যবহৃত হয়েছে।
সারসংক্ষেপ
- Custom Exceptions তৈরি করতে আপনি Exception ক্লাস থেকে ইনহেরিট করতে পারেন এবং নতুন কাস্টম ত্রুটি ক্লাস তৈরি করতে পারেন।
raiseকমান্ড ব্যবহার করে আপনি কাস্টম এক্সসেপশন উত্তোলন করতে পারেন এবংrescueব্লক দিয়ে ত্রুটিগুলি ধরা হয়।- কাস্টম এক্সসেপশনে অতিরিক্ত তথ্য (যেমন ত্রুটির কোড, ফাইল নাম ইত্যাদি) অন্তর্ভুক্ত করা যায়।
ensureব্লকটি সব সময় কার্যকর হয়, ত্রুটি ঘটুক বা না ঘটুক।
কাস্টম এক্সসেপশন ব্যবহারের মাধ্যমে কোডে ত্রুটি বা ব্যতিক্রমের সঠিক পরিচালনা করা সম্ভব, যা কোডের কার্যকারিতা এবং রক্ষণাবেক্ষণ সহজ করে তোলে।
Exceptions Logging এবং Debugging Techniques হল সফটওয়্যার ডেভেলপমেন্টে গুরুত্বপূর্ণ কৌশল, যা কোডের ত্রুটি (error) এবং সমস্যাগুলো চিহ্নিত এবং সমাধান করতে ব্যবহৃত হয়। রুবি প্রোগ্রামিং ভাষায় এ দুটি প্রক্রিয়া কার্যকরভাবে ব্যবহার করা যেতে পারে কোডের কার্যকারিতা নিশ্চিত করতে এবং উৎপাদন পরিবেশে (production environment) ত্রুটি সমাধান করতে।
১. Exceptions Logging
Exceptions Logging হল সেই প্রক্রিয়া যেখানে কোডের মধ্যে ত্রুটি ঘটলে তার বিস্তারিত তথ্য লগ (log) আকারে সংরক্ষণ করা হয়। এটি ডেভেলপারদের ত্রুটি শনাক্ত করতে সহায়তা করে, যাতে ত্রুটির কারণ বোঝা যায় এবং ভবিষ্যতে তা সমাধান করা যায়।
রুবি ভাষায় ত্রুটির লগ করার জন্য আপনি begin...rescue...end ব্লক ব্যবহার করতে পারেন, এবং লগ তথ্য সংরক্ষণ করতে Logger ক্লাস ব্যবহার করা হয়।
১.১ Logger ক্লাস ব্যবহার করে Exception Logging
রুবির Logger ক্লাসটি ত্রুটির তথ্য (exception) লগ করার জন্য একটি সুবিধাজনক উপায় প্রদান করে। এটি বিভিন্ন লগ স্তর (level) যেমন INFO, ERROR, DEBUG, ইত্যাদি সমর্থন করে।
Syntax:
require 'logger'
logger = Logger.new('logfile.log') # Creating a new logger and specifying the log file
logger.level = Logger::ERROR # Set the log level to ERROR (other levels can be INFO, DEBUG, etc.)
begin
# Code that may raise an exception
raise "Something went wrong!"
rescue => e
logger.error("Error occurred: #{e.message}") # Log the error message
endউদাহরণ:
require 'logger'
logger = Logger.new('error_log.txt') # Log file
logger.level = Logger::DEBUG # Set the logging level to DEBUG
begin
# Some code that might cause an exception
result = 10 / 0 # Division by zero error
rescue ZeroDivisionError => e
logger.error("Error: #{e.message}") # Log the exception message as error
logger.debug("Stack trace: #{e.backtrace.join("\n")}") # Log the stack trace at the debug level
endআউটপুট (error_log.txt):
Error: divided by 0
Stack trace: <stack trace details>এখানে, logger.error ত্রুটির বার্তা এবং logger.debug স্ট্যাক ট্রেস সংরক্ষণ করেছে। লগ ফাইলটি এভাবে ত্রুটির তথ্য এবং ডিবাগ তথ্য সংরক্ষণ করে, যা ডেভেলপারদের ত্রুটি চিহ্নিত এবং সমাধান করতে সাহায্য করে।
Logger এর বিভিন্ন স্তর:
Logger::DEBUG: ডিবাগging স্তর, বিস্তারিত তথ্য লগ করে।Logger::INFO: সাধারণ তথ্য লগ করে।Logger::WARN: সতর্কতা লগ করে।Logger::ERROR: ত্রুটি লগ করে।Logger::FATAL: মারাত্মক ত্রুটি লগ করে।
২. Debugging Techniques (ডিবাগিং কৌশল)
ডিবাগিং হল প্রোগ্রামিংয়ের একটি প্রক্রিয়া, যেখানে কোডের ত্রুটি (bugs) শনাক্ত এবং সংশোধন করা হয়। রুবিতে কিছু কার্যকরী ডিবাগিং কৌশল রয়েছে, যা ডেভেলপারদের ত্রুটি চিহ্নিত করতে এবং সমস্যার সমাধান করতে সাহায্য করে।
২.১ puts এবং print ব্যবহার করে ডিবাগিং
একটি সাধারণ এবং প্রাথমিক ডিবাগিং কৌশল হল puts বা print মেথড ব্যবহার করে কোডের বিভিন্ন অংশের মান বের করা। এতে করে ডেভেলপাররা কোডের নির্দিষ্ট অংশের আউটপুট দেখতে পায় এবং ত্রুটি চিহ্নিত করতে সাহায্য পায়।
উদাহরণ:
def divide(a, b)
puts "a = #{a}, b = #{b}" # Debugging line
result = a / b
puts "result = #{result}" # Debugging line
result
end
divide(10, 2)এখানে, puts মেথড ব্যবহার করে আমরা ভেরিয়েবল a, b, এবং result এর মান আউটপুট করে দেখতে পারি।
২.২ pry বা byebug ব্যবহার করে ডিবাগিং
pry এবং byebug হল দুইটি শক্তিশালী ডিবাগিং টুল, যা কোডের মধ্যে ব্রেকপয়েন্ট (breakpoint) সেট করতে এবং কোড লাইনে থেমে গিয়ে ডেটা পরীক্ষা করতে ব্যবহৃত হয়। এগুলি interactive debugging এর জন্য ব্যবহৃত হয়, যেখানে ডেভেলপার কোডের স্টেট চেক করতে পারেন।
pry এবং byebug ব্যবহারের জন্য আপনাকে তাদের ইনস্টল করতে হবে:
gem install pry
gem install byebugউদাহরণ (pry):
require 'pry'
def divide(a, b)
binding.pry # Debugging breakpoint
result = a / b
result
end
divide(10, 2)এখানে, binding.pry একটি ব্রেকপয়েন্ট যোগ করেছে, যেখানে কোড থেমে যাবে এবং আপনি ইন্টারঅ্যাকটিভভাবে কোডের ভেরিয়েবল চেক করতে পারবেন।
উদাহরণ (byebug):
require 'byebug'
def divide(a, b)
byebug # Debugging breakpoint
result = a / b
result
end
divide(10, 2)এখানে, byebug ব্যবহৃত হয়েছে এবং ব্রেকপয়েন্টে থেমে গিয়ে আপনি বিভিন্ন ভেরিয়েবল পরীক্ষা করতে পারবেন এবং কোডের কার্যকারিতা পরীক্ষা করতে পারবেন।
২.৩ Error Backtrace Analysis
রুবিতে যখন কোনো ত্রুটি (error) ঘটে, তখন আপনি সেই ত্রুটির backtrace দেখতে পারেন। এটি আপনাকে ত্রুটির সঠিক অবস্থান এবং সেই অবস্থানে গিয়ে কিভাবে ত্রুটিটি ঘটেছে, তা বুঝতে সহায়তা করে।
উদাহরণ:
begin
# Some code that might cause an exception
result = 10 / 0 # Division by zero error
rescue ZeroDivisionError => e
puts "Error message: #{e.message}"
puts "Backtrace: #{e.backtrace.join("\n")}"
endআউটপুট:
Error message: divided by 0
Backtrace: /path/to/file.rb:3:in `/'
/path/to/file.rb:3:in `block in <main>'এখানে, e.backtrace দিয়ে আপনি ত্রুটির ঘটনার পুরো স্ট্যাক ট্রেস দেখতে পাচ্ছেন, যা ডিবাগিংয়ের জন্য খুবই সহায়ক।
সারসংক্ষেপ
- Exception Logging: ত্রুটির লগ রাখার জন্য রুবির
Loggerক্লাস ব্যবহৃত হয়। এটি ত্রুটি সংক্রান্ত তথ্য, যেমন ত্রুটি বার্তা এবং স্ট্যাক ট্রেস লগ করে, যা ডেভেলপারদের ত্রুটি চিহ্নিত এবং সমাধান করতে সহায়তা করে। - Debugging Techniques: ডিবাগিংয়ের জন্য
puts,pry,byebug, এবং backtrace analysis ব্যবহার করা হয়। এগুলি ডেভেলপারদের কোডের ত্রুটি বা সমস্যাগুলি দ্রুত চিহ্নিত করতে এবং সমাধান করতে সহায়তা করে।
এই কৌশলগুলির মাধ্যমে আপনি ত্রুটি শনাক্ত এবং সমাধান করতে সক্ষম হবেন, যা কোডের উন্নয়ন এবং রক্ষণাবেক্ষণকে সহজ করে তোলে।
Read more