Ruby এ `Exception=> e` উদ্ধারের খারাপ শৈলী কেন?




exception-handling (4)

এই সব ব্যতিক্রম captures কারণ। আপনার প্রোগ্রামটি যে কোনও থেকে পুনরুদ্ধার করতে পারে এমন সম্ভাবনা নেই।

আপনি থেকে পুনরুদ্ধার কিভাবে জানেন যে ব্যতিক্রম শুধুমাত্র পরিচালনা করা উচিত। আপনি যদি কোনও নির্দিষ্ট ব্যতিক্রমটির প্রত্যাশা না করেন তবে এটি পরিচালনা করবেন না, জোরে ক্র্যাশ করুন (লগের বিশদ লিখুন), তারপরে লগগুলি সনাক্ত করুন এবং কোডটি ঠিক করুন।

গ্রাসকারী ব্যতিক্রম খারাপ, এই কাজ করবেন না।

রায়ান ডেভিস এর রুবি কুইকরিফ বলেছেন (ব্যাখ্যা ছাড়া):

আপত্তি উদ্ধার করবেন না। কখনোই না। অথবা আমি আপনাকে ছোঁড়া হবে।

কেন না? কি সঠিক জিনিস কি?


এটি এমন একটি নির্দিষ্ট নিয়ম যা আপনাকে কোনও ব্যতিক্রম না ধরতে হবে যা আপনি পরিচালনা করবেন না। যদি আপনি এটি পরিচালনা করতে না জানেন তবে সিস্টেমের কিছু অংশকে ধরা এবং পরিচালনা করার জন্য এটি আরও ভাল।


বাস্তব নিয়ম হল: ব্যতিক্রম দূরে নিক্ষেপ করবেন না। আপনার উদ্ধৃতি লেখক এর objectivity সন্দেহজনক হয়, এটি শেষ সঙ্গে যে প্রমাণ দ্বারা প্রমাণিত

অথবা আমি আপনাকে ছোঁড়া হবে

অবশ্যই, সচেতন হোন যে সংকেতগুলি (ডিফল্ট অনুসারে) ব্যতিক্রমগুলি ছুঁড়ে ফেলে এবং সাধারণত লম্বা চলমান প্রসেসগুলি একটি সংকেত মাধ্যমে বাতিল করা হয়, তাই ব্যতিক্রম ব্যতিক্রম এবং সিগন্যাল ব্যতিক্রমগুলি বন্ধ না করা আপনার প্রোগ্রামটিকে বন্ধ করতে খুব কঠিন করে তোলে। সুতরাং এটি করবেন না:

#! /usr/bin/ruby

while true do
  begin
    line = STDIN.gets
    # heavy processing
  rescue Exception => e
    puts "caught exception #{e}! ohnoes!"
  end
end

না, সত্যিই, এটা করবেন না। এমনকি এটি কাজ করে দেখতে যে চালানো না।

যাইহোক, আপনি একটি থ্রেড সার্ভার আছে এবং আপনি সব ব্যতিক্রম না চান বলে:

  1. উপেক্ষা করা (ডিফল্ট)
  2. সার্ভারটি বন্ধ করুন (যদি আপনি thread.abort_on_exception = true বলে thread.abort_on_exception = true )।

তারপর এই আপনার সংযোগ হ্যান্ডলিং থ্রেডে পুরোপুরি গ্রহণযোগ্য:

begin
  # do stuff
rescue Exception => e
  myLogger.error("uncaught #{e} exception while handling connection: #{e.message}")
    myLogger.error("Stack trace: #{backtrace.map {|l| "  #{l}\n"}.join}")
end

উপরে রুবি এর ডিফল্ট ব্যতিক্রম হ্যান্ডলারের একটি বৈচিত্র্যের সাথে কাজ করে, এটি আপনার প্রোগ্রামটিকে হত্যা করে না এমন সুবিধা সহ। Rails তার অনুরোধ হ্যান্ডলার এই কাজ করে।

সংকেত ব্যতিক্রম প্রধান থ্রেড উত্থাপিত হয়। পটভূমি থ্রেড তাদের পাবেন না, তাই সেখানে তাদের ধরা চেষ্টা করার কোন বিন্দু নেই।

এটি বিশেষভাবে একটি উত্পাদন পরিবেশে দরকারী, যেখানে আপনি আপনার প্রোগ্রামটি কেবলমাত্র যখনই কিছু ভুল হয় তখন থামাতে চান না । তারপরে আপনি আপনার লগগুলিতে স্ট্যাক ডাম্প নিতে পারেন এবং কল চেইন এবং আরও বেশি সুন্দর পদ্ধতিতে নির্দিষ্ট ব্যতিক্রমগুলির সাথে মোকাবিলা করতে আপনার কোডটিতে যোগ দিতে পারেন।

উল্লেখ্য, আরেকটি রুবি মূর্তি রয়েছে যা একই রকম প্রভাব ফেলে:

a = do_something rescue "something else"

এই লাইনে, যদি do_something ব্যতিক্রম করে তবে এটি রুবি দ্বারা ধরা হয়, ফেলে দেওয়া হয় এবং a "something else"

সাধারণভাবে, তা করবেন না, বিশেষ ক্ষেত্রে যেখানে আপনি জানেন যে আপনাকে চিন্তার দরকার নেই। একটি উদাহরণ:

debugger rescue nil

debugger ফাংশনটি আপনার কোডের ব্রেকপয়েন্ট সেট করার পক্ষে আরও ভাল উপায়, তবে ডিবাগার এবং রেলগুলির বাইরে চললে এটি একটি ব্যতিক্রম বাড়ায়। এখন তাত্ত্বিকভাবে আপনি আপনার প্রোগ্রামে থাকা ডিবাগ কোডটি ছেড়ে যাবেন না (pff! যে কেউ এটি করে না!) তবে আপনি কিছু কারণে এটি কিছুক্ষণ ধরে রাখতে চান তবে আপনার ডিবাগারটি অবিরত চলতে থাকবে না।

বিঃদ্রঃ:

  1. যদি আপনি অন্যের প্রোগ্রাম চালান যা সংকেত ব্যতিক্রমগুলি ধরে রাখে এবং তাদের উপেক্ষা করে, (উপরে কোডটি বলুন) তাহলে:

    • লিনাক্সে, শেলের মধ্যে, pgrep ruby বা ps | grep ruby টাইপ করুন ps | grep ruby , আপনার আপত্তিকর প্রোগ্রামের PID সন্ধান করুন, এবং তারপর kill -9 <PID> চালান।
    • উইন্ডোজগুলিতে, টাস্ক ম্যানেজার ( CTRL - SHIFT - ESC ) ব্যবহার করুন, "প্রসেস" ট্যাবে যান, আপনার প্রক্রিয়াটি সন্ধান করুন, ডান ক্লিক করুন এবং "শেষ প্রক্রিয়া" নির্বাচন করুন।
  2. যদি আপনি অন্য কোনও প্রোগ্রামের সাথে কাজ করেন যা কোনও কারণে, এই উপেক্ষা-ব্যতিক্রম ব্লকগুলির সাথে ম্লান হয়ে থাকে, তবে মূল লাইনের শীর্ষে এটি স্থাপন করা একটি সম্ভাব্য কপ-আউট:

    %W/INT QUIT TERM/.each { |sig| trap sig,"SYSTEM_DEFAULT" }

    এটি প্রোগ্রামটিকে কোনও ক্লিনআপ ছাড়াই ব্যতিক্রম হ্যান্ডলারগুলিকে বাইপাস করে তাত্ক্ষণিকভাবে বন্ধ করে সাধারণ অবসান সংকেতগুলিতে প্রতিক্রিয়া জানায়। সুতরাং এটি তথ্য ক্ষতি বা অনুরূপ হতে পারে। সাবধান হও!

  3. যদি আপনি এই কাজ করতে হবে:

    begin
      do_something
    rescue Exception => e
      critical_cleanup
      raise
    end

    আপনি আসলে এটি করতে পারেন:

    begin
      do_something
    ensure
      critical_cleanup
    end

    দ্বিতীয় ক্ষেত্রে, critical cleanup প্রতিটি সময় বলা হবে, ব্যতিক্রম ব্যতিক্রম হয় কিনা।


টিএল; ডিআর : সাধারণ ব্যতিক্রম ধরার পরিবর্তে StandardError ইরার ব্যবহার করুন। যখন মূল ব্যতিক্রমটি পুনঃ-উত্থাপিত হয় (উদাহরণস্বরূপ শুধুমাত্র ব্যতিক্রমটি লগ ইন করার সময়), Exception উদ্ধার করা সম্ভবত ঠিক আছে।

Exception রবি এর ব্যতিক্রম অনুক্রমের রুট, তাই যখন আপনি rescue Exception থেকে rescue Exception তখন সবকিছু থেকে উদ্ধার করবেন, যেমন LoadError , LoadError এবং LoadError সহ উপশ্রেণী।

রেসকিউিং Interrupt ব্যবহারকারীকে প্রোগ্রাম থেকে বেরিয়ে যেতে CTRL সি ব্যবহার করতে বাধা দেয়।

SignalException রোধ করা প্রোগ্রামটিকে সঠিকভাবে সিগন্যালগুলিতে সাড়া দেওয়ার বাধা দেয়। এটা kill -9 ব্যতীত unkillable হবে।

SyntaxError SyntaxError মানে যে চুপচাপ করে ব্যর্থ যে eval গুলি।

এই সমস্ত প্রোগ্রামটি চালানোর মাধ্যমে এবং এটি CTRL C এর চেষ্টা করে বা এটি kill করে দেখানো যেতে পারে:

loop do
  begin
    sleep 1
    eval "djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"
  rescue Exception
    puts "I refuse to fail or be stopped!"
  end
end

Exception থেকে উদ্ধার এমনকি ডিফল্ট নয়। এরকম

begin
  # iceberg!
rescue
  # lifeboats
end

Exception থেকে উদ্ধার না, এটি StandardError থেকে উদ্ধার। আপনি সাধারণত ডিফল্ট StandardError চেয়ে আরো নির্দিষ্ট কিছু নির্দিষ্ট করতে হবে, তবে Exception থেকে উদ্ধার করা এটি সংকীর্ণ করার পরিবর্তে সুযোগকে বিস্তৃত করে এবং এর বিপর্যয়ের ফলাফল এবং বাগ-শিকারকে অত্যন্ত কঠিন করে তুলতে পারে।

যদি আপনার কোন পরিস্থিতি থাকে যেখানে আপনি StandardError থেকে রেসকিউ করতে চান এবং ব্যতিক্রমের সাথে একটি পরিবর্তনশীলের প্রয়োজন হয় তবে আপনি এই ফর্মটি ব্যবহার করতে পারেন:

begin
  # iceberg!
rescue => e
  # lifeboats
end

যা সমতুল্য:

begin
  # iceberg!
rescue StandardError => e
  # lifeboats
end

Exception থেকে উদ্ধার করার পক্ষে কয়েকটি সাধারণ মামলাগুলির মধ্যে একটি হল লগিং / প্রতিবেদনের উদ্দেশ্যে, যার ক্ষেত্রে আপনাকে অবিলম্বে ব্যতিক্রম পুনঃব্যবহার করা উচিত:

begin
  # iceberg?
rescue Exception => e
  # do some logging
  raise e  # not enough lifeboats ;)
end




exception-handling