Do you want to pick up from where you left of?
Take me there

এরর হ্যান্ডলিং

যদিও {:error, reason} টাপলটি রিটার্ন করাই বেশী জনপ্রিয়, তবে, এলিক্সির এক্সেপশন সাপোর্ট করে। এই অধ্যায়ে, আমরা দেখবো কিভাবে এরর হ্যান্ডল করা যায় এবং এর জন্যে তৈরি বিভিন্ন মেকানিজম গুলো।

সাধারণত, এলিক্সিরে রীতি হলো একটা ফাংশন তৈরি করা (example/1) যেটা {:ok, result} এবং {:error, reason} রিটার্ন করে এবং আরেকটা আলাদা ফাংশন (example!/1) যেটা সরাসরি result অথবা এরর দেখায়।

এই অধ্যায়ে, আমরা পরেরটা আলোচনা করবো।

সাধারণ রীতি

এই মুহূর্তে, এলিক্সির কমিউনিটি এরর রিটার্ন করার কিছু সাধারণ রীতি মেনে চলেঃ

আমরা সাধারণত, স্ট্যান্ডার্ড এরর ফলো হ্যান্ডল করি প্যাটার্ন ম্যাচিং ব্যবহার করে, কিন্তু এই অধ্যায়ে, আমরা দ্বিতীয় কেইসে ফোকাস করবো অর্থাৎ এক্সেপশনে খেয়াল করবো।

অনেক সময়, পাবলিক এপিআইগুলোতে, আপনি দ্বিতীয় আরেকটি ভার্সনের ফাংশন পেতে পারেন ! চিহ্ন সমেত (example!/1) যেটা সরাসরি রেসাল্ট রিটার্ন করে অথবা এরর ছুড়ে দেয়।

এরর হ্যান্ডলিং

আমাদের এরর হ্যান্ডল করার আগে, এরর তৈরি করতে পারতে হবে,এর জন্যে সবচেয়ে সহজ উপায় হলোঃ raise/1

iex> raise "Oh no!"
** (RuntimeError) Oh no!

যদি আমরা টাইপ এবং মেসেজ বলে দিতে চাই, তবে, আমাদের raise/2 ব্যবহার করতে হবেঃ

iex> raise ArgumentError, message: "the argument value is invalid"
** (ArgumentError) the argument value is invalid

যখন আমরা জানি যে এরর হতে পারে, তখন আমরা সে এরর কে হ্যান্ডল করতে try/rescue এবং প্যাটার্ন ম্যাচিং ব্যবহার করতে পারিঃ

iex> try do
...>   raise "Oh no!"
...> rescue
...>   e in RuntimeError -> IO.puts("An error occurred: " <> e.message)
...> end
An error occurred: Oh no!
:ok

একটি সিঙ্গেল রেস্কিউ দিয়ে অনেকগুলো এরর কে ম্যাচ করাও সম্ভবঃ

try do
  opts
  |> Keyword.fetch!(:source_file)
  |> File.read!()
rescue
  e in KeyError -> IO.puts("missing :source_file option")
  e in File.Error -> IO.puts("unable to read source file")
end

আফটার

অনেক সময়, try/rescue ব্যবহার এর সময় এরর হউক বা না হউক, আমাদের কিছু একশান নেয়ার প্রয়োজন হতে পারে। সে জন্যে আছে try/after। যদি আপনি রুবি এর সাথে পরিচিত থাকেন, তবে, এটা অনেকটাই begin/rescue/ensure এর মতো অথবা জাভা এর try/catch/finally এর মতোঃ

iex> try do
...>   raise "Oh no!"
...> rescue
...>   e in RuntimeError -> IO.puts("An error occurred: " <> e.message)
...> after
...>   IO.puts "The end!"
...> end
An error occurred: Oh no!
The end!
:ok

এটা সাধারণত ফাইলস অথবা কানেকশনের সাথে ব্যবহার করা হয় যেগুলো ক্লোজ করতে হয়ঃ

{:ok, file} = File.open("example.json")

try do
  # Do hazardous work
after
  File.close(file)
end

নিউ এররস

যদিও এলিক্সির বিল্ট ইন অনেক টাইপের এরর প্রদান করে যেমন RuntimeError, আমাদের যদি প্রয়োজন হয় তবে আমরা চাইলে আমাদের নিজেদের এরর টাইপও তৈরি করতে পারি। defexception/1 ম্যাক্রো ব্যবহার করে নিউ বা নতুন এরর তৈরি করা একদমই সহজ, যেটা আমাদের সুবিধার জন্যে :message অপশনটি একসেপ্ট করে যার সাহায্যে ডিফল্ট এরর মেসেজ সেট করা যায়ঃ

defmodule ExampleError do
  defexception message: "an example error has occurred"
end

চলুন, আমাদের নতুন এররটি প্রয়োগ করে দেখা যাকঃ

iex> try do
...>   raise ExampleError
...> rescue
...>   e in ExampleError -> e
...> end
%ExampleError{message: "an example error has occurred"}

থ্রোস

এছাড়াও, এলিক্সিরে এরর নিয়ে কাজ করার অন্য আরেকটা উপায় হলো throw এবং catch। ব্যবহারিক ক্ষেত্রে, এর ব্যবহার অপ্রতুল এবং নতুন এলিক্সির কোডে এর কদাচিৎ ব্যবহার হয়ে থাকে, তবে যাই হোক, এদের জানা এবং বুঝা আবশ্যক।

throw/1 ফাংশনটি আমাদের এক্সিকিউশন থেকে বেরিয়ে যাওয়ার উপায় বাতলে দেয় এর সাথে সাথে আমরা একটি নির্দিষ্ট ভ্যালু catch করে ব্যবহারও করতে পারিঃ

iex> try do
...>   for x <- 0..10 do
...>     if x == 5, do: throw(x)
...>     IO.puts(x)
...>   end
...> catch
...>   x -> "Caught: #{x}"
...> end
0
1
2
3
4
"Caught: 5"

আগেই উল্লেখ করা হয়েছে, সাধারণত লাইব্রেরী যদি পর্যাপ্ত এপিআই দিতে ব্যর্থ হয় সে সমস্ত ক্ষেত্রবিশেষ ছাড়া throw/catch খুবই কমই ব্যবহৃত হয়ে থাকে।

এক্সিটিং

exit হলো এলিক্সিরের প্রদত্ত সর্বশেষ এরর মেকানিজম। প্রসেসের মৃত্যুতে এক্সিট সিগনাল এর উৎপত্তি হয়ে থাকে, এটি এলিক্সিরের ফল্ট টলারেন্স এর অন্যতম অংশ হিসেবে বিবেচিত।

exit/1 ব্যবহার করে আমরা আমাদের ইচ্ছানুযায়ী এক্সিট করতে পারিঃ

iex> spawn_link fn -> exit("oh no") end
** (EXIT from #PID<0.101.0>) evaluator process exited with reason: "oh no"

যদিও try/catch ব্যবহার করে এক্সিট কে ক্যাচ করা যায়, তবে এরূপ ব্যবহার অত্যধিক অপ্রতুল। প্রায় সব ক্ষেত্রেই, সুপারভাইজারকে এক্সিট প্রসেস করতে দেয়ায় বুদ্ধিমানের কাজঃ

iex> try do
...>   exit "oh no!"
...> catch
...>   :exit, _ -> "exit blocked"
...> end
"exit blocked"
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!